package database import ( "errors" "gopkgs.com/unidecode.v1" "labix.org/v2/mgo" "labix.org/v2/mgo/bson" "strings" "unicode" ) const ( books_coll = "books" ) type Book struct { Id string `bson:"_id"` Title string Author []string Contributor string Publisher string Description string Subject []string Date string Lang []string Isbn string Type string Format string Source string Relation string Coverage string Rights string Meta string File bson.ObjectId FileSize int Cover bson.ObjectId CoverSmall bson.ObjectId Active bool Keywords []string } func addBook(coll *mgo.Collection, book map[string]interface{}) error { book["keywords"] = keywords(book) return coll.Insert(book) } func getBooks(coll *mgo.Collection, query string, length int, start int) (books []Book, num int, err error) { return _getBooks(coll, buildQuery(query), length, start) } func getNewBooks(coll *mgo.Collection, length int, start int) (books []Book, num int, err error) { return _getBooks(coll, bson.M{"$nor": []bson.M{{"active": true}}}, length, start) } func _getBooks(coll *mgo.Collection, query bson.M, length int, start int) (books []Book, num int, err error) { q := coll.Find(query).Sort("-_id") num, err = q.Count() if err != nil { return } if start != 0 { q = q.Skip(start) } if length != 0 { q = q.Limit(length) } err = q.All(&books) for i, b := range books { books[i].Id = bson.ObjectId(b.Id).Hex() } return } func getBookId(coll *mgo.Collection, id string) (Book, error) { var book Book if !bson.IsObjectIdHex(id) { return book, errors.New("Not valid book id") } err := coll.FindId(bson.ObjectIdHex(id)).One(&book) book.Id = bson.ObjectId(book.Id).Hex() return book, err } func deleteBook(coll *mgo.Collection, id bson.ObjectId) error { return coll.Remove(bson.M{"_id": id}) } func updateBook(coll *mgo.Collection, id bson.ObjectId, data map[string]interface{}) error { data["keywords"] = keywords(data) return coll.Update(bson.M{"_id": id}, bson.M{"$set": data}) } func bookActive(coll *mgo.Collection, id bson.ObjectId) bool { var book Book err := coll.Find(bson.M{"_id": id}).One(&book) if err != nil { return false } return book.Active } func buildQuery(q string) bson.M { var keywords []string query := bson.M{"active": true} words := strings.Split(q, " ") for _, w := range words { tag := strings.SplitN(w, ":", 2) if len(tag) > 1 { query[tag[0]] = bson.RegEx{tag[1], "i"} } else { toks := tokens(w) keywords = append(keywords, toks...) } } if len(keywords) > 0 { query["keywords"] = bson.M{"$all": keywords} } return query } func keywords(b map[string]interface{}) (k []string) { title, _ := b["title"].(string) k = tokens(title) author, _ := b["author"].([]string) for _, a := range author { k = append(k, tokens(a)...) } publisher, _ := b["publisher"].(string) k = append(k, tokens(publisher)...) subject, _ := b["subject"].([]string) for _, s := range subject { k = append(k, tokens(s)...) } return } func tokens(str string) []string { str = unidecode.Unidecode(str) str = strings.ToLower(str) f := func(r rune) bool { return unicode.IsControl(r) || unicode.IsPunct(r) || unicode.IsSpace(r) } return strings.FieldsFunc(str, f) }