/
term.go
153 lines (138 loc) · 3.42 KB
/
term.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
package search
import (
"encoding/json"
"fmt"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
)
type Term struct {
Value string
Boost float64
CaseInsensitive bool
}
func (t Term) Rule() (Rule, error) {
return t.Term()
}
func (t Term) Term() (*TermRule, error) {
q := &TermRule{}
if t.Value == "" {
return q, ErrValueRequired
}
q.SetValue(t.Value)
q.SetBoost(t.Boost)
q.SetCaseInsensitive(t.CaseInsensitive)
return q, nil
}
func (t Term) Type() Type {
return TypeTerm
}
// TermRule query returns documents that contain an exact term in a provided field.
//
// You can use the term query to find documents based on a precise value such as
// a price, a product ID, or a username.
//
// Avoid using the term query for text fields.
//
// By default, Elasticsearch changes the values of text fields as part of
// analysis. This can make finding exact matches for text field values
// difficult.
//
// To search text field values, use the match query instead.
//
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html
type TermRule struct {
TermValue string `json:"value" bson:"value"`
BoostParam `json:",inline" bson:",inline"`
CaseInsensitiveParam `json:",inline" bson:",inline"`
}
func (t *TermRule) UnmarshalJSON(data []byte) error {
g := gjson.ParseBytes(data)
if g.Type == gjson.String {
t.TermValue = g.String()
t.BoostParam = BoostParam{}
t.CaseInsensitiveParam = CaseInsensitiveParam{}
return nil
}
var tt term
err := json.Unmarshal(data, &tt)
if err != nil {
return err
}
t.BoostParam = tt.BoostParam
t.TermValue = tt.TermValue
t.CaseInsensitiveParam = tt.CaseInsensitiveParam
return nil
}
func (t *TermRule) Type() Type {
return TypeTerm
}
func (t *TermRule) SetValue(v string) {
t.TermValue = v
}
func (t TermRule) Value() string {
return t.TermValue
}
type term TermRule
// TermQuery returns documents that contain an exact term in a provided field.
//
// You can use the term query to find documents based on a precise value such as
// a price, a product ID, or a username.
//
// Avoid using the term query for text fields.
//
// By default, Elasticsearch changes the values of text fields as part of
// analysis. This can make finding exact matches for text field values
// difficult.
//
// To search text field values, use the match query instead.
//
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html
type TermQuery struct {
TermField string
TermRule *TermRule
}
func (t TermQuery) MarshalJSON() ([]byte, error) {
return sjson.SetBytes([]byte{}, t.TermField, t.TermRule)
}
func (t *TermQuery) UnmarshalJSON(data []byte) error {
fmt.Println("inside term")
t.TermField = ""
t.TermRule = nil
g := gjson.ParseBytes(data)
var val gjson.Result
g.ForEach(func(key, value gjson.Result) bool {
t.TermField = key.Str
val = value
return false
})
switch val.Type {
case gjson.JSON:
err := unmarshalRule(val, t.TermRule, nil)
return err
case gjson.String:
t.TermRule = &TermRule{
TermValue: val.Str,
}
}
return nil
}
func (t *TermQuery) SetTerm(field string, term *Term) error {
if term == nil {
t.RemoveTerm()
return nil
}
if field == "" {
return NewQueryError(ErrFieldRequired, TypeTerm)
}
r, err := term.Term()
if err != nil {
return err
}
t.TermField = field
t.TermRule = r
return nil
}
func (t *TermQuery) RemoveTerm() {
t.TermField = ""
t.TermRule = nil
}