Move the query parsing to the database

This implies to move the tokeinzation as well.
This commit is contained in:
Las Zenow 2014-07-02 20:58:00 -05:00
parent 44d3a191f6
commit 93d31b53fe
7 changed files with 73 additions and 66 deletions

View file

@ -95,7 +95,6 @@ func saveHandler(h handler) {
"author": author, "author": author,
"subject": subject, "subject": subject,
"lang": lang} "lang": lang}
book["keywords"] = keywords(book)
err := h.db.UpdateBook(id, book) err := h.db.UpdateBook(id, book)
if err != nil { if err != nil {
notFound(h) notFound(h)
@ -155,8 +154,8 @@ func newHandler(h handler) {
} }
for i, b := range res { for i, b := range res {
data.Books[i].B = b data.Books[i].B = b
_, data.Books[i].TitleFound, _ = h.db.GetBooks(buildQuery("title:"+b.Title), 1, 0) _, data.Books[i].TitleFound, _ = h.db.GetBooks("title:"+b.Title, 1, 0)
_, data.Books[i].AuthorFound, _ = h.db.GetBooks(buildQuery("author:"+strings.Join(b.Author, " author:")), 1, 0) _, data.Books[i].AuthorFound, _ = h.db.GetBooks("author:"+strings.Join(b.Author, " author:"), 1, 0)
} }
data.Page = page + 1 data.Page = page + 1
if num > (page+1)*NEW_ITEMS_PAGE { if num > (page+1)*NEW_ITEMS_PAGE {

View file

@ -2,8 +2,11 @@ package database
import ( import (
"errors" "errors"
"gopkgs.com/unidecode.v1"
"labix.org/v2/mgo" "labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"strings"
"unicode"
) )
const ( const (
@ -36,11 +39,20 @@ type Book struct {
Keywords []string Keywords []string
} }
func addBook(coll *mgo.Collection, book interface{}) error { func addBook(coll *mgo.Collection, book map[string]interface{}) error {
book["keywords"] = keywords(book)
return coll.Insert(book) return coll.Insert(book)
} }
func getBooks(coll *mgo.Collection, query bson.M, length int, start int) (books []Book, num int, err error) { 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") q := coll.Find(query).Sort("-_id")
num, err = q.Count() num, err = q.Count()
if err != nil { if err != nil {
@ -75,7 +87,8 @@ func deleteBook(coll *mgo.Collection, id bson.ObjectId) error {
return coll.Remove(bson.M{"_id": id}) return coll.Remove(bson.M{"_id": id})
} }
func updateBook(coll *mgo.Collection, id bson.ObjectId, data interface{}) error { 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}) return coll.Update(bson.M{"_id": id}, bson.M{"$set": data})
} }
@ -87,3 +100,47 @@ func bookActive(coll *mgo.Collection, id bson.ObjectId) bool {
} }
return book.Active 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)
}

View file

@ -43,37 +43,37 @@ func (db *DB) Copy() *DB {
return dbCopy return dbCopy
} }
func (db *DB) AddBook(book interface{}) error { func (db *DB) AddBook(book map[string]interface{}) error {
booksColl := db.session.DB(db.name).C(books_coll) booksColl := db.session.DB(db.name).C(books_coll)
return addBook(booksColl, book) return addBook(booksColl, book)
} }
// FIXME: don't export bson data func (db *DB) GetBooks(query string, length int, start int) (books []Book, num int, err error) {
func (db *DB) GetBooks(query bson.M, length int, start int) (books []Book, num int, err error) {
booksColl := db.session.DB(db.name).C(books_coll) booksColl := db.session.DB(db.name).C(books_coll)
return getBooks(booksColl, query, length, start) return getBooks(booksColl, query, length, start)
} }
func (db *DB) GetNewBooks(length int, start int) (books []Book, num int, err error) {
booksColl := db.session.DB(db.name).C(books_coll)
return getNewBooks(booksColl, length, start)
}
func (db *DB) GetBookId(id string) (Book, error) { func (db *DB) GetBookId(id string) (Book, error) {
booksColl := db.session.DB(db.name).C(books_coll) booksColl := db.session.DB(db.name).C(books_coll)
return getBookId(booksColl, id) return getBookId(booksColl, id)
} }
// FIXME: don't export bson data
func (db *DB) DeleteBook(id bson.ObjectId) error { func (db *DB) DeleteBook(id bson.ObjectId) error {
booksColl := db.session.DB(db.name).C(books_coll) booksColl := db.session.DB(db.name).C(books_coll)
return deleteBook(booksColl, id) return deleteBook(booksColl, id)
} }
func (db *DB) UpdateBook(id bson.ObjectId, data interface{}) error { func (db *DB) UpdateBook(id bson.ObjectId, data map[string]interface{}) error {
booksColl := db.session.DB(db.name).C(books_coll) booksColl := db.session.DB(db.name).C(books_coll)
return updateBook(booksColl, id, data) return updateBook(booksColl, id, data)
} }
func (db *DB) GetNewBooks(length int, start int) (books []Book, num int, err error) {
booksColl := db.session.DB(db.name).C(books_coll)
return getBooks(booksColl, bson.M{"$nor": []bson.M{{"active": true}}}, length, start)
}
func (db *DB) BookActive(id bson.ObjectId) bool { func (db *DB) BookActive(id bson.ObjectId) bool {
booksColl := db.session.DB(db.name).C(books_coll) booksColl := db.session.DB(db.name).C(books_coll)
return bookActive(booksColl, id) return bookActive(booksColl, id)

View file

@ -2,31 +2,11 @@ package main
import ( import (
"git.gitorious.org/trantor/trantor.git/database" "git.gitorious.org/trantor/trantor.git/database"
"labix.org/v2/mgo/bson"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
) )
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
}
type searchData struct { type searchData struct {
S Status S Status
Found int Found int
@ -52,7 +32,7 @@ func searchHandler(h handler) {
} }
} }
items_page := itemsPage(h.r) items_page := itemsPage(h.r)
res, num, _ := h.db.GetBooks(buildQuery(req), items_page, page*items_page) res, num, _ := h.db.GetBooks(req, items_page, page*items_page)
var data searchData var data searchData
data.S = GetStatus(h) data.S = GetStatus(h)

View file

@ -4,13 +4,11 @@ import (
"bytes" "bytes"
"git.gitorious.org/go-pkg/epubgo.git" "git.gitorious.org/go-pkg/epubgo.git"
"git.gitorious.org/trantor/trantor.git/database" "git.gitorious.org/trantor/trantor.git/database"
"gopkgs.com/unidecode.v1"
"io" "io"
"io/ioutil" "io/ioutil"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"regexp" "regexp"
"strings" "strings"
"unicode"
) )
func OpenBook(id bson.ObjectId, db *database.DB) (*epubgo.Epub, error) { func OpenBook(id bson.ObjectId, db *database.DB) (*epubgo.Epub, error) {
@ -115,28 +113,3 @@ func parseDate(date []string) string {
} }
return strings.Replace(date[0], "Unspecified: ", "", -1) return strings.Replace(date[0], "Unspecified: ", "", -1)
} }
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)
}

View file

@ -6,7 +6,6 @@ import (
"git.gitorious.org/trantor/trantor.git/database" "git.gitorious.org/trantor/trantor.git/database"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"io" "io"
"labix.org/v2/mgo/bson"
"net/http" "net/http"
"strings" "strings"
) )
@ -103,7 +102,7 @@ func indexHandler(h handler) {
data.Tags, _ = h.db.GetTags() data.Tags, _ = h.db.GetTags()
data.S = GetStatus(h) data.S = GetStatus(h)
data.S.Home = true data.S.Home = true
data.Books, data.Count, _ = h.db.GetBooks(bson.M{"active": true}, BOOKS_FRONT_PAGE, 0) data.Books, data.Count, _ = h.db.GetBooks("", BOOKS_FRONT_PAGE, 0)
data.VisitedBooks, _ = h.db.GetVisitedBooks() data.VisitedBooks, _ = h.db.GetVisitedBooks()
data.DownloadedBooks, _ = h.db.GetDownloadedBooks() data.DownloadedBooks, _ = h.db.GetDownloadedBooks()
data.News = getNews(1, DAYS_NEWS_INDEXPAGE, h.db) data.News = getNews(1, DAYS_NEWS_INDEXPAGE, h.db)

View file

@ -142,6 +142,5 @@ func parseFile(epub *epubgo.Epub, db *database.DB) map[string]interface{} {
book["cover"] = cover book["cover"] = cover
book["coversmall"] = coverSmall book["coversmall"] = coverSmall
} }
book["keywords"] = keywords(book)
return book return book
} }