diff --git a/db/bookmarks.go b/db/bookmarks.go index 81530c8..005c8da 100644 --- a/db/bookmarks.go +++ b/db/bookmarks.go @@ -18,6 +18,11 @@ type BookmarkManager struct { scrapeQueue chan *entity.Bookmark } +type SearchOptions struct { + Query string + Tags []string +} + func NewBookmarkManager(db *DB) *BookmarkManager { return &BookmarkManager{db: db, scrapeQueue: make(chan *entity.Bookmark)} } @@ -94,28 +99,12 @@ func (m *BookmarkManager) LoadBookmarkByID(id uint64) entity.Bookmark { return ret } -func (m *BookmarkManager) LoadBookmarksByIDs(ids []uint64) []entity.Bookmark { - // log.Printf("loading %v", ids) - ret := make([]entity.Bookmark, 0, 0) - - s := make([]interface{}, len(ids)) - for i, v := range ids { - s[i] = v - } - - err := m.db.store.Find(&ret, bolthold.Where("ID").In(s...)) - if err != nil { - panic(err) - } - return ret -} - -func (m *BookmarkManager) Search(query string, tags []string) ([]entity.Bookmark, error) { - rets := make([]uint64, 0, 0) +func (m *BookmarkManager) Search(opts SearchOptions) ([]entity.Bookmark, error) { + // first get a list of all the ids that match our query + idsMatchingQuery := make([]uint64, 0, 0) counts := make(map[uint64]uint8) - - words := content.StringToSearchWords(query) + words := content.StringToSearchWords(opts.Query) for _, word := range words { var wi *entity.WordIndex @@ -133,30 +122,33 @@ func (m *BookmarkManager) Search(query string, tags []string) ([]entity.Bookmark for k, v := range counts { if v == uint8(len(words)) { - rets = append(rets, k) - if len(rets) > 10 { + idsMatchingQuery = append(idsMatchingQuery, k) + if len(idsMatchingQuery) > 10 { break } } } - if tags != nil && len(tags) > 0 { - rets = m.LimitToIdsWithTags(rets, tags) + // now we can do our search + bhQuery := bolthold.Query{} + if opts.Query != "" { + bhQuery = bolthold.Query(*bhQuery.And("ID").In(bolthold.Slice(idsMatchingQuery)...)) + } + if opts.Tags != nil && len(opts.Tags) > 0 { + bhQuery = bolthold.Query(*bhQuery.And("Tags").ContainsAll(bolthold.Slice(opts.Tags)...)) } - return m.LoadBookmarksByIDs(rets), nil -} -func (m *BookmarkManager) LimitToIdsWithTags(ids []uint64, tags []string) []uint64 { - outIds := []uint64{} - err := m.db.store.ForEach(bolthold.Where("ID").ContainsAny(bolthold.Slice(ids)...).And("Tags").ContainsAll(bolthold.Slice(tags)...), + out := []entity.Bookmark{} + err := m.db.store.ForEach(&bhQuery, func(bm *entity.Bookmark) error { - outIds = append(outIds, bm.ID) + out = append(out, *bm) return nil }) if err != nil { panic(err) } - return outIds + + return out, nil } func (m *BookmarkManager) ScrapeAndIndex(bm *entity.Bookmark) error { diff --git a/db/bookmarks_test.go b/db/bookmarks_test.go index 6326c28..9536bc8 100644 --- a/db/bookmarks_test.go +++ b/db/bookmarks_test.go @@ -73,7 +73,7 @@ func BenchmarkOneWordSearch(b *testing.B) { bmm := NewBookmarkManager(&dbh) b.ResetTimer() for i := 0; i < b.N; i++ { - bmm.Search("hello", nil) + bmm.Search(SearchOptions{Query: "hello"}) } } @@ -84,7 +84,7 @@ func BenchmarkTwoWordSearch(b *testing.B) { bmm := NewBookmarkManager(&dbh) b.ResetTimer() for i := 0; i < b.N; i++ { - bmm.Search("human relate", nil) + bmm.Search(SearchOptions{Query: "human relate"}) } } @@ -95,6 +95,6 @@ func BenchmarkThreeWordSearch(b *testing.B) { bmm := NewBookmarkManager(&dbh) b.ResetTimer() for i := 0; i < b.N; i++ { - bmm.Search("human wiki editor", nil) + bmm.Search(SearchOptions{Query: "human wiki editor"}) } } diff --git a/db/index_test.go b/db/index_test.go index 602cad2..8bf640e 100644 --- a/db/index_test.go +++ b/db/index_test.go @@ -47,7 +47,7 @@ func TestAddRemove(t *testing.T) { t.Errorf("scrape index returned %s", err) } - searchRes, err := bmm.Search("fox", nil) + searchRes, err := bmm.Search(SearchOptions{Query: "fox"}) if err != nil { t.Errorf("search returned %s", err) } @@ -62,7 +62,7 @@ func TestAddRemove(t *testing.T) { t.Errorf("scrape index returned %s", err) } - searchRes, err = bmm.Search("fox", nil) + searchRes, err = bmm.Search(SearchOptions{Query: "fox"}) if err != nil { t.Errorf("search returned %s", err) } @@ -70,7 +70,7 @@ func TestAddRemove(t *testing.T) { t.Error("got result when should not") } - searchRes, err = bmm.Search("rabbit", nil) + searchRes, err = bmm.Search(SearchOptions{Query: "rabbit"}) if err != nil { t.Errorf("search returned %s", err) } @@ -83,7 +83,7 @@ func TestAddRemove(t *testing.T) { t.Errorf("got error when deleting: %s", err) } - searchRes, err = bmm.Search("rabbit", nil) + searchRes, err = bmm.Search(SearchOptions{Query: "rabbit"}) if err != nil { t.Errorf("search returned %s", err) } @@ -119,7 +119,7 @@ func TestTagIndexing(t *testing.T) { t.Errorf("scrape index returned %s", err) } - searchRes, err := bmm.Search("fox", nil) + searchRes, err := bmm.Search(SearchOptions{Query: "fox"}) if err != nil { t.Errorf("search returned %s", err) } @@ -133,7 +133,7 @@ func TestTagIndexing(t *testing.T) { if err != nil { t.Errorf("scrape index returned %s", err) } - searchRes, err = bmm.Search("sloth", nil) + searchRes, err = bmm.Search(SearchOptions{Query: "sloth"}) if err != nil { t.Errorf("search returned %s", err) } diff --git a/web/web.go b/web/web.go index da85e67..23436cc 100644 --- a/web/web.go +++ b/web/web.go @@ -95,7 +95,7 @@ func Create(bmm *db.BookmarkManager, cmm *db.ConfigManager) *Server { if c.PostForm("tags_hidden") != "" { tags = strings.Split(c.PostForm("tags_hidden"), "|") } - allBookmarks, _ := bmm.Search(query, tags) + allBookmarks, _ := bmm.Search(db.SearchOptions{Query: query, Tags: tags}) meta := gin.H{"config": config, "bookmarks": allBookmarks} log.Printf("query is %s, tags %v", query, tags) @@ -125,7 +125,7 @@ func Create(bmm *db.BookmarkManager, cmm *db.ConfigManager) *Server { r.POST("/search", func(c *gin.Context) { query := c.PostForm("query") - sr, err := bmm.Search(query, nil) + sr, err := bmm.Search(db.SearchOptions{Query: query}) data := gin.H{ "results": sr, "error": err,