-
Notifications
You must be signed in to change notification settings - Fork 0
/
searchkey.go
152 lines (126 loc) · 3.18 KB
/
searchkey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package main
import (
"errors"
"log"
"time"
bleve "github.com/blevesearch/bleve/v2"
"github.com/blevesearch/bleve/v2/mapping"
"github.com/blevesearch/bleve/v2/search"
pb "github.com/cheggaaa/pb/v3"
bolt "go.etcd.io/bbolt"
)
var keywordDBchan chan KeywordIndex
var repopulateKeywordDB = true
var (
imapping mapping.IndexMapping
index bleve.Index
)
type KeywordIndex struct {
Author string
Text string
ID []byte
ThreadID []byte
}
func DoKeywordSearch(keywords string) (ids [][]byte, err error) {
query := bleve.NewQueryStringQuery(keywords)
searchRequest := bleve.NewSearchRequest(query)
var searchResult *bleve.SearchResult
searchResult, err = index.Search(searchRequest)
if err != nil {
return
}
/*
Extract only the IDs from this searchResult
*/
var hits []*search.DocumentMatch = searchResult.Hits
for _, h := range hits {
ids = append(ids, []byte(h.ID))
}
return
}
func makeKeywordIndex(author, text string, ID, threadID []byte) KeywordIndex {
var current KeywordIndex
current.Author = author
current.Text = text
current.ID = make([]byte, 16)
copy(current.ID, ID)
current.ThreadID = make([]byte, 16)
copy(current.ThreadID, threadID)
return current
}
func sendPostToKeywordDB(author, text string, ID, threadID []byte) {
/*
Automatically handles if keywordDBchan is nil
(not set during testing)
*/
if keywordDBchan == nil {
return
}
current := makeKeywordIndex(author, text, ID, threadID)
keywordDBchan <- current
}
func keywordDBloop() {
for {
newIndex := <-keywordDBchan
index.Index(string(newIndex.ID), newIndex)
log.Printf("Added post %s to database", newIndex.ID)
}
}
func initKeyword() error {
keywordDBchan = make(chan KeywordIndex, 64)
go keywordDBloop()
var err error
imapping = bleve.NewIndexMapping()
if repopulateKeywordDB {
index, err = bleve.New(Configuration.Keywords, imapping)
if err != nil {
if errors.Is(err, bleve.ErrorIndexPathExists) {
// delete file and start over
return errors.New("Keywords database already exists. Please remove this directory and try again.")
}
return err
}
/*
Read all posts from database and populate keyword database
*/
if err := db.View(func(tx *bolt.Tx) error {
posts := tx.Bucket(DBALLPOSTS)
/*
Read the current value (current, not increment
will EQUAL highest id of post
and setup progress bar for that.
*/
progress := pb.Full.Start64(int64(posts.Sequence()))
progress.SetRefreshRate(time.Millisecond * 100)
defer progress.Finish()
var k []byte
c := posts.Cursor()
for k, _ = c.First(); k != nil; k, _ = c.Next() {
post := posts.Bucket(k)
if post == nil {
// deleted
continue
}
current := makeKeywordIndex(string(post.Get([]byte("user"))), string(post.Get([]byte("text"))), k, post.Get([]byte("thread")))
index.Index(string(k), current)
progress.Increment()
}
return nil
}); err != nil {
return nil
}
} else {
index, err = bleve.Open(Configuration.Keywords)
if err != nil {
if errors.Is(err, bleve.ErrorIndexPathDoesNotExist) {
/*
Doesn't exist. Create new database
*/
repopulateKeywordDB = true
return initKeyword()
}
return err
}
}
return nil
}