This repository has been archived on 2025-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
trantor/database/books.go

220 lines
5 KiB
Go
Raw Normal View History

2014-06-29 19:41:29 -05:00
package database
import (
2014-08-31 15:09:59 -05:00
log "github.com/cihub/seelog"
2014-08-30 13:17:50 -05:00
"strings"
2015-01-22 21:58:27 -06:00
"time"
2014-08-30 13:17:50 -05:00
2014-08-18 19:27:53 -05:00
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
2014-06-29 19:41:29 -05:00
)
const (
books_coll = "books"
)
type Book struct {
2014-09-07 21:13:52 -05:00
Id string
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
FileSize int
Cover bool
Active bool
BadQuality int `bad_quality`
BadQualityReporters []string `bad_quality_reporters`
2014-06-29 19:41:29 -05:00
}
2015-01-22 21:58:27 -06:00
type history struct {
Date time.Time
Changes bson.M
}
2014-08-31 15:09:59 -05:00
func indexBooks(coll *mgo.Collection) {
indexes := []mgo.Index{
{
Key: []string{"id"},
Unique: true,
Background: true,
},
{
Key: []string{"active", "-_id"},
Background: true,
},
2014-09-07 20:22:24 -05:00
{
Key: []string{"active", "-bad_quality", "-_id"},
Background: true,
},
2015-01-24 11:53:28 -06:00
{
Key: []string{"$text:title", "$text:author", "$text:contributor",
"$text:publisher", "$text:subject", "$text:description"},
Weights: map[string]int{"title": 20, "author": 20, "contributor": 15,
"publisher": 15, "subject": 10, "description": 5},
LanguageOverride: "_lang",
Background: true,
},
2014-08-31 15:09:59 -05:00
}
2014-10-26 12:12:27 -06:00
for _, k := range []string{"lang", "title", "author", "subject"} {
2014-08-31 15:09:59 -05:00
idx := mgo.Index{
Key: []string{"active", k, "-_id"},
Background: true,
}
indexes = append(indexes, idx)
}
for _, idx := range indexes {
err := coll.EnsureIndex(idx)
if err != nil {
log.Error("Error indexing books: ", err)
}
}
}
func addBook(coll *mgo.Collection, book map[string]interface{}) error {
2014-10-26 12:12:27 -06:00
book["_lang"] = metadataLang(book)
2014-06-29 19:41:29 -05:00
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) {
2014-10-26 12:12:27 -06:00
sort := []string{"$textScore:score"}
2014-09-07 20:22:24 -05:00
if _, present := query["bad_quality"]; present {
sort = append(sort, "-bad_quality")
}
sort = append(sort, "-_id")
2014-10-26 12:12:27 -06:00
q := coll.Find(query).Select(bson.M{"score": bson.M{"$meta": "textScore"}}).Sort(sort...)
2014-06-29 19:41:29 -05:00
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)
return
}
2014-07-02 20:40:24 -05:00
func getBookId(coll *mgo.Collection, id string) (Book, error) {
var book Book
2014-08-21 19:24:23 -05:00
err := coll.Find(bson.M{"id": id}).One(&book)
2014-07-02 20:40:24 -05:00
return book, err
}
func deleteBook(coll *mgo.Collection, id string) error {
2014-08-21 19:24:23 -05:00
return coll.Remove(bson.M{"id": id})
2014-06-29 19:41:29 -05:00
}
func updateBook(coll *mgo.Collection, id string, data map[string]interface{}) error {
2014-08-21 19:24:23 -05:00
var book map[string]interface{}
2015-01-22 21:58:27 -06:00
record := history{time.Now(), bson.M{}}
2014-08-21 19:24:23 -05:00
err := coll.Find(bson.M{"id": id}).One(&book)
if err != nil {
return err
}
2015-01-22 21:58:27 -06:00
for k, _ := range data {
record.Changes[k] = book[k]
if k == "lang" {
if lang := metadataLang(data); lang != "" {
data["_lang"] = lang
}
}
2014-08-21 19:24:23 -05:00
}
2015-01-22 21:58:27 -06:00
return coll.Update(bson.M{"id": id}, bson.M{"$set": data, "$push": bson.M{"history": record}})
2014-06-29 19:41:29 -05:00
}
2014-09-07 21:13:52 -05:00
func flagBadQuality(coll *mgo.Collection, id string, user string) error {
b, err := getBookId(coll, id)
if err != nil {
return err
}
for _, reporter := range b.BadQualityReporters {
if reporter == user {
return nil
}
}
return coll.Update(
bson.M{"id": id},
bson.M{
"$inc": bson.M{"bad_quality": 1},
"$addToSet": bson.M{"bad_quality_reporters": user},
},
)
2014-09-07 20:22:24 -05:00
}
2014-08-21 19:24:23 -05:00
func activeBook(coll *mgo.Collection, id string) error {
data := map[string]interface{}{"active": true}
return coll.Update(bson.M{"id": id}, bson.M{"$set": data})
}
func isBookActive(coll *mgo.Collection, id string) bool {
2014-06-29 19:41:29 -05:00
var book Book
2014-08-21 19:24:23 -05:00
err := coll.Find(bson.M{"id": id}).One(&book)
2014-06-29 19:41:29 -05:00
if err != nil {
return false
}
return book.Active
}
func buildQuery(q string) bson.M {
2014-10-26 12:12:27 -06:00
text := ""
query := bson.M{"active": true}
words := strings.Split(q, " ")
for _, w := range words {
tag := strings.SplitN(w, ":", 2)
if len(tag) > 1 {
2014-09-07 20:22:24 -05:00
if tag[0] == "flag" {
query[tag[1]] = bson.M{"$gt": 0}
} else {
query[tag[0]] = bson.RegEx{tag[1], "i"} //FIXME: this should be a list
}
} else {
2014-10-26 12:12:27 -06:00
if len(text) != 0 {
text += " "
}
text += w
}
}
2014-10-26 12:12:27 -06:00
if len(text) > 0 {
query["$text"] = bson.M{"$search": text}
}
return query
}
2014-10-26 12:12:27 -06:00
func metadataLang(book map[string]interface{}) string {
lang, ok := book["lang"].([]string)
if !ok || len(lang) == 0 || len(lang[0]) < 2 {
return ""
}
2014-10-26 12:12:27 -06:00
return strings.ToLower(lang[0][0:2])
}