diff --git a/config.go b/config.go index 2dfd90e..44841a4 100644 --- a/config.go +++ b/config.go @@ -1,22 +1,25 @@ package main const ( - PORT = "8080" - DB_IP = "127.0.0.1" - DB_NAME = "trantor" - BOOKS_COLL = "books" - USERS_COLL = "users" - PASS_SALT = "ImperialLibSalt" - TAGS_DISPLAY = 50 - SEARCH_ITEMS_PAGE = 20 - NEW_ITEMS_PAGE = 50 - TEMPLATE_PATH = "templates/" - BOOKS_PATH = "books/" - COVER_PATH = "cover/" - NEW_PATH = "new/" - CSS_PATH = "css/" - JS_PATH = "js/" - IMG_PATH = "img/" - RESIZE_CMD = "/usr/bin/convert -resize 300 -quality 60 " - RESIZE_THUMB_CMD = "/usr/bin/convert -resize 60 -quality 60 " + PORT = "8080" + DB_IP = "127.0.0.1" + DB_NAME = "trantor" + META_COLL = "meta" + BOOKS_COLL = "books" + TAGS_COLL = "tags" + USERS_COLL = "users" + PASS_SALT = "ImperialLibSalt" + MINUTES_UPDATE_TAGS = 10 + TAGS_DISPLAY = 50 + SEARCH_ITEMS_PAGE = 20 + NEW_ITEMS_PAGE = 50 + TEMPLATE_PATH = "templates/" + BOOKS_PATH = "books/" + COVER_PATH = "cover/" + NEW_PATH = "new/" + CSS_PATH = "css/" + JS_PATH = "js/" + IMG_PATH = "img/" + RESIZE_CMD = "/usr/bin/convert -resize 300 -quality 60 " + RESIZE_THUMB_CMD = "/usr/bin/convert -resize 60 -quality 60 " ) diff --git a/database.go b/database.go index f9f29ee..bc00874 100644 --- a/database.go +++ b/database.go @@ -4,7 +4,11 @@ import ( "crypto/md5" "labix.org/v2/mgo" "labix.org/v2/mgo/bson" - "sort" + "time" +) + +const ( + META_TYPE_TAGS = "tags updated" ) var db *DB @@ -35,7 +39,9 @@ type Book struct { type DB struct { session *mgo.Session + meta *mgo.Collection books *mgo.Collection + tags *mgo.Collection user *mgo.Collection } @@ -48,7 +54,9 @@ func initDB() *DB { } database := d.session.DB(DB_NAME) + d.meta = database.C(META_COLL) d.books = database.C(BOOKS_COLL) + d.tags = database.C(TAGS_COLL) d.user = database.C(USERS_COLL) return d } @@ -169,25 +177,25 @@ func (d *DB) BookActive(id bson.ObjectId) bool { return book.Active } -type tagsList []struct { - Subject string "_id" - Count int "value" +func (d *DB) areTagsOutdated() bool { + var result struct { + Id bson.ObjectId `bson:"_id"` + } + err := d.meta.Find(bson.M{"type": META_TYPE_TAGS}).One(&result) + if err != nil { + return true + } + + lastUpdate := result.Id.Time() + return time.Since(lastUpdate).Minutes() > MINUTES_UPDATE_TAGS } -func (t tagsList) Len() int { - return len(t) -} -func (t tagsList) Less(i, j int) bool { - return t[i].Count > t[j].Count -} -func (t tagsList) Swap(i, j int) { - aux := t[i] - t[i] = t[j] - t[j] = aux -} +func (d *DB) updateTags() error { + _, err := d.meta.RemoveAll(bson.M{"type": META_TYPE_TAGS}) + if err != nil { + return err + } -func (d *DB) GetTags() (tagsList, error) { - // TODO: cache the tags var mr mgo.MapReduce mr.Map = "function() { " + "if (this.active) { this.subject.forEach(function(s) { emit(s, 1); }); }" + @@ -197,10 +205,33 @@ func (d *DB) GetTags() (tagsList, error) { "vals.forEach(function() { count += 1; });" + "return count;" + "}" - var result tagsList - _, err := d.books.Find(bson.M{"active": true}).MapReduce(&mr, &result) - if err == nil { - sort.Sort(result) + mr.Out = bson.M{"replace": TAGS_COLL} + _, err = d.books.Find(bson.M{"active": true}).MapReduce(&mr, nil) + if err != nil { + return err } - return result, err + + return d.meta.Insert(bson.M{"type": META_TYPE_TAGS}) +} + +func (d *DB) GetTags(numTags int) ([]string, error) { + if d.areTagsOutdated() { + err := d.updateTags() + if err != nil { + return nil, err + } + } + + var result []struct { + Tag string "_id" + } + err := d.tags.Find(nil).Sort("-value").Limit(numTags).All(&result) + if err != nil { + return nil, err + } + tags := make([]string, len(result)) + for i, r := range result { + tags[i] = r.Tag + } + return tags, nil } diff --git a/trantor.go b/trantor.go index a647dc8..1fcd09b 100644 --- a/trantor.go +++ b/trantor.go @@ -82,24 +82,7 @@ type indexData struct { func indexHandler(w http.ResponseWriter, r *http.Request) { var data indexData - /* get the tags */ - tags, err := db.GetTags() - if err == nil { - length := len(tags) - if length > TAGS_DISPLAY { - length = TAGS_DISPLAY - } - data.Tags = make([]string, length) - for i, tag := range tags { - if i == TAGS_DISPLAY { - break /* display only 50 */ - } - if tag.Subject != "" { - data.Tags[i] = tag.Subject - } - } - } - + data.Tags, _ = db.GetTags(TAGS_DISPLAY) data.S = GetStatus(w, r) data.S.Home = true data.Books, data.Count, _ = db.GetBooks(bson.M{"active": true}, 6)