Skip to content

Commit c76a1be

Browse files
committed
Add IntervalQueryRuleFuzzy
This commit adds the missing `IntervalQueryRuleFuzzy`. Close #1564
1 parent 15cfb75 commit c76a1be

2 files changed

+191
-0
lines changed

search_queries_interval_integration_test.go

+100
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ func TestIntervalQuery_Integration(t *testing.T) {
2020
t.Run("Prefix", func(t *testing.T) {
2121
testIntervalQueryPrefix(client, t)
2222
})
23+
t.Run("Wildcard", func(t *testing.T) {
24+
testIntervalQueryWildcard(client, t)
25+
})
26+
t.Run("Fuzzy", func(t *testing.T) {
27+
testIntervalQueryFuzzy(client, t)
28+
})
2329
}
2430

2531
func testIntervalQueryMatch(client *Client, t *testing.T) {
@@ -115,3 +121,97 @@ func testIntervalQueryPrefix(client *Client, t *testing.T) {
115121
}
116122
}
117123
}
124+
125+
func testIntervalQueryWildcard(client *Client, t *testing.T) {
126+
q := NewIntervalQuery(
127+
"message",
128+
NewIntervalQueryRuleAllOf(
129+
NewIntervalQueryRuleAnyOf(
130+
NewIntervalQueryRuleMatch("Golang").Ordered(true),
131+
NewIntervalQueryRuleMatch("Cycling").MaxGaps(0).Filter(
132+
NewIntervalQueryFilter().NotContaining(
133+
NewIntervalQueryRuleWildcard("Hockey*"),
134+
),
135+
),
136+
),
137+
).Ordered(true),
138+
)
139+
140+
// Match all should return all documents
141+
searchResult, err := client.Search().
142+
Index(testIndexName).
143+
Query(q).
144+
Size(10).
145+
Pretty(true).
146+
Do(context.TODO())
147+
if err != nil {
148+
t.Fatal(err)
149+
}
150+
if searchResult.Hits == nil {
151+
t.Errorf("expected SearchResult.Hits != nil; got nil")
152+
}
153+
if got, want := searchResult.TotalHits(), int64(2); got != want {
154+
t.Errorf("expected SearchResult.TotalHits() = %d; got %d", want, got)
155+
}
156+
if got, want := len(searchResult.Hits.Hits), 2; got != want {
157+
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got)
158+
}
159+
160+
for _, hit := range searchResult.Hits.Hits {
161+
if hit.Index != testIndexName {
162+
t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
163+
}
164+
item := make(map[string]interface{})
165+
err := json.Unmarshal(hit.Source, &item)
166+
if err != nil {
167+
t.Fatal(err)
168+
}
169+
}
170+
}
171+
172+
func testIntervalQueryFuzzy(client *Client, t *testing.T) {
173+
q := NewIntervalQuery(
174+
"message",
175+
NewIntervalQueryRuleAllOf(
176+
NewIntervalQueryRuleAnyOf(
177+
NewIntervalQueryRuleMatch("Golang").Ordered(true),
178+
NewIntervalQueryRuleMatch("Cycling").MaxGaps(0).Filter(
179+
NewIntervalQueryFilter().NotContaining(
180+
NewIntervalQueryRuleFuzzy("Hocky").Fuzziness("auto"),
181+
),
182+
),
183+
),
184+
).Ordered(true),
185+
)
186+
187+
// Match all should return all documents
188+
searchResult, err := client.Search().
189+
Index(testIndexName).
190+
Query(q).
191+
Size(10).
192+
Pretty(true).
193+
Do(context.TODO())
194+
if err != nil {
195+
t.Fatal(err)
196+
}
197+
if searchResult.Hits == nil {
198+
t.Errorf("expected SearchResult.Hits != nil; got nil")
199+
}
200+
if got, want := searchResult.TotalHits(), int64(2); got != want {
201+
t.Errorf("expected SearchResult.TotalHits() = %d; got %d", want, got)
202+
}
203+
if got, want := len(searchResult.Hits.Hits), 2; got != want {
204+
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got)
205+
}
206+
207+
for _, hit := range searchResult.Hits.Hits {
208+
if hit.Index != testIndexName {
209+
t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
210+
}
211+
item := make(map[string]interface{})
212+
err := json.Unmarshal(hit.Source, &item)
213+
if err != nil {
214+
t.Fatal(err)
215+
}
216+
}
217+
}
+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package elastic
2+
3+
var (
4+
_ IntervalQueryRule = (*IntervalQueryRuleFuzzy)(nil)
5+
)
6+
7+
// IntervalQueryRuleFuzzy is an implementation of IntervalQueryRule.
8+
//
9+
// See https://www.elastic.co/guide/en/elasticsearch/reference/7.16/query-dsl-intervals-query.html#intervals-fuzzy
10+
// for details.
11+
type IntervalQueryRuleFuzzy struct {
12+
term string
13+
prefixLength *int
14+
transpositions *bool
15+
fuzziness interface{}
16+
analyzer string
17+
useField string
18+
}
19+
20+
// NewIntervalQueryRuleFuzzy initializes and returns a new instance
21+
// of IntervalQueryRuleFuzzy.
22+
func NewIntervalQueryRuleFuzzy(term string) *IntervalQueryRuleFuzzy {
23+
return &IntervalQueryRuleFuzzy{term: term}
24+
}
25+
26+
// PrefixLength is the number of beginning characters left unchanged when
27+
// creating expansions. Defaults to 0.
28+
func (q *IntervalQueryRuleFuzzy) PrefixLength(prefixLength int) *IntervalQueryRuleFuzzy {
29+
q.prefixLength = &prefixLength
30+
return q
31+
}
32+
33+
// Fuzziness is the maximum edit distance allowed for matching.
34+
// It can be integers like 0, 1 or 2 as well as strings
35+
// like "auto", "0..1", "1..4" or "0.0..1.0". Defaults to "auto".
36+
func (q *IntervalQueryRuleFuzzy) Fuzziness(fuzziness interface{}) *IntervalQueryRuleFuzzy {
37+
q.fuzziness = fuzziness
38+
return q
39+
}
40+
41+
// Transpositions indicates whether edits include transpositions of two
42+
// adjacent characters (ab -> ba). Defaults to true.
43+
func (q *IntervalQueryRuleFuzzy) Transpositions(transpositions bool) *IntervalQueryRuleFuzzy {
44+
q.transpositions = &transpositions
45+
return q
46+
}
47+
48+
// Analyzer specifies the analyzer used to analyze terms in the query.
49+
func (r *IntervalQueryRuleFuzzy) Analyzer(analyzer string) *IntervalQueryRuleFuzzy {
50+
r.analyzer = analyzer
51+
return r
52+
}
53+
54+
// UseField, if specified, matches the intervals from this field rather than
55+
// the top-level field.
56+
func (r *IntervalQueryRuleFuzzy) UseField(useField string) *IntervalQueryRuleFuzzy {
57+
r.useField = useField
58+
return r
59+
}
60+
61+
// Source returns JSON for the function score query.
62+
func (r *IntervalQueryRuleFuzzy) Source() (interface{}, error) {
63+
source := make(map[string]interface{})
64+
65+
source["term"] = r.term
66+
67+
if r.prefixLength != nil {
68+
source["prefix_length"] = *r.prefixLength
69+
}
70+
if r.transpositions != nil {
71+
source["transpositions"] = *r.transpositions
72+
}
73+
if r.fuzziness != "" {
74+
source["fuzziness"] = r.fuzziness
75+
}
76+
if r.analyzer != "" {
77+
source["analyzer"] = r.analyzer
78+
}
79+
if r.useField != "" {
80+
source["use_field"] = r.useField
81+
}
82+
83+
return map[string]interface{}{
84+
"fuzzy": source,
85+
}, nil
86+
}
87+
88+
// isIntervalQueryRule implements the marker interface.
89+
func (r *IntervalQueryRuleFuzzy) isIntervalQueryRule() bool {
90+
return true
91+
}

0 commit comments

Comments
 (0)