Move all the code to a lib folder
This commit is contained in:
parent
e963d00014
commit
9d1f1ad5c0
31 changed files with 123 additions and 98 deletions
234
lib/database/books.go
Normal file
234
lib/database/books.go
Normal file
|
@ -0,0 +1,234 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
log "github.com/cihub/seelog"
|
||||
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
const (
|
||||
books_coll = "books"
|
||||
)
|
||||
|
||||
type Book struct {
|
||||
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`
|
||||
}
|
||||
|
||||
type history struct {
|
||||
Date time.Time
|
||||
Changes bson.M
|
||||
}
|
||||
|
||||
func indexBooks(coll *mgo.Collection) {
|
||||
indexes := []mgo.Index{
|
||||
{
|
||||
Key: []string{"id"},
|
||||
Unique: true,
|
||||
Background: true,
|
||||
},
|
||||
{
|
||||
Key: []string{"active", "-_id"},
|
||||
Background: true,
|
||||
},
|
||||
{
|
||||
Key: []string{"active", "-bad_quality", "-_id"},
|
||||
Background: true,
|
||||
},
|
||||
{
|
||||
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,
|
||||
},
|
||||
}
|
||||
for _, k := range []string{"lang", "title", "author", "subject"} {
|
||||
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 {
|
||||
book["_lang"] = metadataLang(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 getBooksIter(coll *mgo.Collection) Iter {
|
||||
return coll.Find(bson.M{}).Iter()
|
||||
}
|
||||
|
||||
func _getBooks(coll *mgo.Collection, query bson.M, length int, start int) (books []Book, num int, err error) {
|
||||
q := getBookQuery(coll, query)
|
||||
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
|
||||
}
|
||||
|
||||
func getBookQuery(coll *mgo.Collection, query bson.M) *mgo.Query {
|
||||
sort := []string{"$textScore:score"}
|
||||
if _, present := query["bad_quality"]; present {
|
||||
sort = append(sort, "-bad_quality")
|
||||
}
|
||||
sort = append(sort, "-_id")
|
||||
|
||||
return coll.Find(query).Select(bson.M{"score": bson.M{"$meta": "textScore"}}).Sort(sort...)
|
||||
}
|
||||
|
||||
func getBookId(coll *mgo.Collection, id string) (Book, error) {
|
||||
var book Book
|
||||
err := coll.Find(bson.M{"id": id}).One(&book)
|
||||
return book, err
|
||||
}
|
||||
|
||||
func deleteBook(coll *mgo.Collection, id string) error {
|
||||
return coll.Remove(bson.M{"id": id})
|
||||
}
|
||||
|
||||
func updateBook(coll *mgo.Collection, id string, data map[string]interface{}) error {
|
||||
var book map[string]interface{}
|
||||
record := history{time.Now(), bson.M{}}
|
||||
|
||||
err := coll.Find(bson.M{"id": id}).One(&book)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k, _ := range data {
|
||||
record.Changes[k] = book[k]
|
||||
if k == "lang" {
|
||||
data["_lang"] = metadataLang(data)
|
||||
}
|
||||
}
|
||||
|
||||
return coll.Update(bson.M{"id": id}, bson.M{"$set": data, "$push": bson.M{"history": record}})
|
||||
}
|
||||
|
||||
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},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
text := ""
|
||||
query := bson.M{"active": true}
|
||||
words := strings.Split(q, " ")
|
||||
for _, w := range words {
|
||||
tag := strings.SplitN(w, ":", 2)
|
||||
if len(tag) > 1 {
|
||||
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 {
|
||||
if len(text) != 0 {
|
||||
text += " "
|
||||
}
|
||||
text += w
|
||||
}
|
||||
}
|
||||
if len(text) > 0 {
|
||||
query["$text"] = bson.M{"$search": text}
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func metadataLang(book map[string]interface{}) string {
|
||||
text_search_langs := map[string]bool{
|
||||
"da": true, "nl": true, "en": true, "fi": true, "fr": true, "de": true,
|
||||
"hu": true, "it": true, "nb": true, "pt": true, "ro": true, "ru": true,
|
||||
"es": true, "sv": true, "tr": true}
|
||||
|
||||
lang, ok := book["lang"].([]string)
|
||||
if !ok || len(lang) == 0 || len(lang[0]) < 2 {
|
||||
return "none"
|
||||
}
|
||||
lcode := strings.ToLower(lang[0][0:2])
|
||||
if text_search_langs[lcode] {
|
||||
return lcode
|
||||
}
|
||||
return "none"
|
||||
}
|
Reference in a new issue