/
index.go
156 lines (125 loc) · 3.37 KB
/
index.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
153
154
155
156
package core
import (
"strings"
"github.com/blevesearch/bleve/v2"
"github.com/blevesearch/bleve/v2/mapping"
"github.com/golang/glog"
)
// Index defines indexing API
type Index interface {
Add(key string, data interface{}) error
Search(query string) ([]SearchResult, error)
Status() SearchStatus
Close() error
}
// SearchStatus maintains current search result status
type SearchStatus struct {
Total int
Failed int
Successful int
}
// SearchResult is the returned object by an Index.Search query
type SearchResult struct {
Key string
Score float64
}
type bleveIndex struct {
index bleve.Index
addInc int
batch *bleve.Batch
}
// CreateIndex instanciates a new Index implementation
func CreateIndex(excludedPaths []string) (Index, error) {
glog.V(1).Infof("CreateIndex(%v)", excludedPaths)
mapping := bleve.NewIndexMapping()
if len(excludedPaths) > 0 {
customMapping := bleve.NewDocumentMapping()
for _, path := range excludedPaths {
paths := strings.Split(path, ".")
pathToMapping(paths, customMapping)
}
mapping.DefaultMapping = customMapping
}
index, err := bleve.NewMemOnly(mapping)
if err != nil {
glog.Error(err)
return nil, err
}
batch := index.NewBatch()
return &bleveIndex{
index: index,
addInc: 0,
batch: batch,
}, nil
}
func pathToMapping(path []string, documentMapping *mapping.DocumentMapping) error {
localPath := strings.TrimSpace(path[0])
if len(path) == 1 {
ignoreMapping := bleve.NewTextFieldMapping()
ignoreMapping.IncludeInAll = false
ignoreMapping.Store = false
documentMapping.AddFieldMappingsAt(localPath, ignoreMapping)
documentMapping.AddSubDocumentMapping(localPath, mapping.NewDocumentDisabledMapping())
return nil
}
if property, found := documentMapping.Properties[localPath]; !found {
property = mapping.NewDocumentMapping()
documentMapping.AddSubDocumentMapping(localPath, property)
pathToMapping(path[1:], property)
} else {
pathToMapping(path[1:], property)
}
return nil
}
func (instance *bleveIndex) Add(key string, data interface{}) error {
glog.V(4).Infof("Add(%s,%#v)", key, data)
err := instance.batch.Index(key, data)
if err != nil {
glog.Error(err)
return err
}
instance.addInc++
if instance.addInc > 1000 {
err = instance.index.Batch(instance.batch)
instance.addInc = 0
if err != nil {
glog.Error(err)
return err
}
}
return nil
}
func (instance *bleveIndex) Search(query string) ([]SearchResult, error) {
glog.V(3).Infof("Search(%s)", query)
if instance.addInc > 0 {
err := instance.index.Batch(instance.batch)
instance.addInc = 0
if err != nil {
glog.Error(err)
return nil, err
}
}
search := bleve.NewSearchRequest(bleve.NewQueryStringQuery(query))
bleeveSearchResults, err := instance.index.Search(search)
if err != nil {
glog.Error(err)
return nil, err
}
searchResults := make([]SearchResult, 0, len(bleeveSearchResults.Hits))
for _, hit := range bleeveSearchResults.Hits {
searchResults = append(searchResults, SearchResult{hit.ID, hit.Score})
}
glog.V(3).Infof("Search result: %v", searchResults)
return searchResults, nil
}
func (instance *bleveIndex) Status() SearchStatus {
return SearchStatus{
Total: instance.Status().Total,
Successful: instance.Status().Successful,
Failed: instance.Status().Failed,
}
}
func (instance *bleveIndex) Close() error {
glog.V(1).Info("Close()")
return instance.index.Close()
}