-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsearchquerybuilder.go
140 lines (120 loc) · 2.88 KB
/
searchquerybuilder.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
package tantivy_go
type QueryType int
const (
BoolQuery QueryType = iota
PhraseQuery
PhrasePrefixQuery
TermPrefixQuery
TermQuery
EveryTermQuery
OneOfTermQuery
)
type QueryModifier int
const (
Must QueryModifier = iota
Should
MustNot
)
type FieldQuery struct {
FieldIndex int `json:"field_index"`
TextIndex int `json:"text_index"`
Boost float64 `json:"boost"`
}
type QueryElement struct {
Query Query `json:"query"`
Modifier QueryModifier `json:"query_modifier"`
QueryType QueryType `json:"query_type"`
}
type BooleanQuery struct {
Subqueries []QueryElement `json:"subqueries"`
Boost float64 `json:"boost"`
}
type FinalQuery struct {
Texts []string `json:"texts"`
Fields []string `json:"fields"`
Query *BooleanQuery `json:"query"`
}
type sharedStore struct {
texts map[string]int
fields map[string]int
textList []string
fieldList []string
}
type QueryBuilder struct {
store *sharedStore
subqueries []QueryElement
}
func NewQueryBuilder() *QueryBuilder {
return &QueryBuilder{
store: &sharedStore{
texts: make(map[string]int),
fields: make(map[string]int),
textList: []string{},
fieldList: []string{},
},
subqueries: []QueryElement{},
}
}
func (qb *QueryBuilder) NestedBuilder() *QueryBuilder {
return &QueryBuilder{
store: qb.store,
subqueries: []QueryElement{},
}
}
func (qb *QueryBuilder) AddText(text string) int {
if idx, exists := qb.store.texts[text]; exists {
return idx
}
idx := len(qb.store.textList)
qb.store.texts[text] = idx
qb.store.textList = append(qb.store.textList, text)
return idx
}
func (qb *QueryBuilder) AddField(field string) int {
if idx, exists := qb.store.fields[field]; exists {
return idx
}
idx := len(qb.store.fieldList)
qb.store.fields[field] = idx
qb.store.fieldList = append(qb.store.fieldList, field)
return idx
}
func (qb *QueryBuilder) Query(modifier QueryModifier, field string, text string, queryType QueryType, boost float64) *QueryBuilder {
textIndex := qb.AddText(text)
fieldIndex := qb.AddField(field)
qb.subqueries = append(qb.subqueries, QueryElement{
Query: &FieldQuery{
FieldIndex: fieldIndex,
TextIndex: textIndex,
Boost: boost,
},
Modifier: modifier,
QueryType: queryType,
})
return qb
}
func (qb *QueryBuilder) BooleanQuery(modifier QueryModifier, subBuilder *QueryBuilder, boost float64) *QueryBuilder {
qb.subqueries = append(qb.subqueries, QueryElement{
Query: &BooleanQuery{
Subqueries: subBuilder.subqueries,
Boost: boost,
},
Modifier: modifier,
QueryType: BoolQuery,
})
return qb
}
func (qb *QueryBuilder) Build() FinalQuery {
return FinalQuery{
Texts: qb.store.textList,
Fields: qb.store.fieldList,
Query: &BooleanQuery{
Subqueries: qb.subqueries,
},
}
}
type Query interface {
IsQuery()
}
func (fq *FieldQuery) IsQuery() {}
func (bq *BooleanQuery) IsQuery() {}