Skip to content

Commit 1afb9e8

Browse files
authored
Search suggest (#1)
add option search.suggest
1 parent 10c4eca commit 1afb9e8

File tree

5 files changed

+218
-2
lines changed

5 files changed

+218
-2
lines changed

effdsl.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ type (
2828
RewriteParameter = objs.RewriteParameter
2929

3030
SortOrder = objs.SortOrder
31+
32+
SuggestSort = objs.SuggestSort
33+
SuggestMode = objs.SuggestMode
3134
)
3235

3336
//--------------------------------------------------------------------------------------//
@@ -101,6 +104,16 @@ var (
101104
WithIncludes = objs.WithIncludes
102105
WithExcludes = objs.WithExcludes
103106
SourceFilter = objs.SourceFilter
107+
108+
// search_source_filtering.go
109+
Suggesters = objs.Suggesters
110+
WithSuggest = objs.WithSuggest
111+
TermSuggester = objs.TermSuggester
112+
Term = objs.Term
113+
WithTermSuggestAnalyzer = objs.WithTermSuggestAnalyzer
114+
WithTermSuggestSize = objs.WithTermSuggestSize
115+
WithTermSuggestSort = objs.WithTermSuggestSort
116+
WithTermSuggestMode = objs.WithTermSuggestMode
104117
)
105118

106119
//--------------------------------------------------------------------------------------//

objects/body.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type SearchBody struct {
2020
SearchAfter SearchAfterType `json:"search_after,omitempty"`
2121
Collapse json.Marshaler `json:"collapse,omitempty"`
2222
PIT json.Marshaler `json:"pit,omitempty"`
23+
Suggest Suggest `json:"suggest,omitempty"`
2324
}
2425

2526
type BodyOption func(*SearchBody) error
@@ -174,7 +175,7 @@ func WithCollpse(field string) BodyOption {
174175
//--------------------------------------------------------------------------------------//
175176

176177
// You can use the _source parameter to select what fields of the source are returned. This is called source filtering.
177-
//The following search API request sets the _source request body parameter to false. The document source is not included in the response.
178+
// The following search API request sets the _source request body parameter to false. The document source is not included in the response.
178179
// [Source filtering]: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-fields.html#source-filtering
179180
func WithSourceFilter(opts ...SourceFitlerOption) BodyOption {
180181
sourceFilter := SourceFilter(opts...)
@@ -200,3 +201,28 @@ func Define(opts ...BodyOption) (body *SearchBody, err error) {
200201
}
201202
return body, nil
202203
}
204+
205+
//--------------------------------------------------------------------------------------//
206+
// Suggest //
207+
//--------------------------------------------------------------------------------------//
208+
209+
type Suggest interface {
210+
SuggestInfo() string
211+
json.Marshaler
212+
}
213+
214+
type SuggestResult struct {
215+
Ok Suggest
216+
Err error
217+
}
218+
219+
// WithSuggest - allows you to use suggest
220+
func WithSuggest(suggestResult SuggestResult) BodyOption {
221+
suggest := suggestResult.Ok
222+
err := suggestResult.Err
223+
// Type assertion
224+
return func(b *SearchBody) error {
225+
b.Suggest = suggest
226+
return err
227+
}
228+
}

objects/q_range_query.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func RangeQuery(field string, opts ...RangeQueryOption) QueryResult {
7373
if rangeQuery.GT == nil && rangeQuery.GTE == nil && rangeQuery.LT == nil && rangeQuery.LTE == nil {
7474
return QueryResult{
7575
Ok: rangeQuery,
76-
Err: errors.New("One of WithGT, WithGTE, WithLT, WithLTE should be proveded for range query"),
76+
Err: errors.New("one of WithGT, WithGTE, WithLT, WithLTE should be proveded for range query"),
7777
}
7878
}
7979
return QueryResult{

objects/search_suggest.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package objects
2+
3+
import "encoding/json"
4+
5+
type SuggestS struct {
6+
GlobalText string `json:"text,omitempty"` // To avoid repetition of the suggest text, it is possible to define a global text.
7+
Suggester
8+
}
9+
10+
func (s SuggestS) MarshalJSON() ([]byte, error) {
11+
type SuggesterBase SuggestS
12+
return json.Marshal((SuggesterBase)(s))
13+
}
14+
15+
func (s SuggestS) SuggestInfo() string {
16+
return "Suggest"
17+
}
18+
19+
// Suggests similar looking terms based on a provided text by using a suggester.
20+
// [Suggesters]: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html#search-suggesters
21+
func Suggesters(globalText string, s Suggester) SuggestResult {
22+
sugest := SuggestS{
23+
GlobalText: globalText,
24+
Suggester: s,
25+
}
26+
27+
return SuggestResult{
28+
Ok: sugest,
29+
Err: nil,
30+
}
31+
}
32+
33+
// ----------------------------------------------------
34+
35+
type Suggester interface {
36+
json.Marshaler
37+
_type() string
38+
}
39+
40+
// ----------------------------------------------------
41+
42+
// TermSuggester - https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html#term-suggester
43+
type TermsSuggest []TermSuggest
44+
45+
func (ts TermsSuggest) MarshalJSON() ([]byte, error) {
46+
type TermSuggesterBase TermSuggest
47+
48+
terms := make(M, len(ts))
49+
for i := range ts {
50+
terms[ts[i].GetName()] = (TermSuggesterBase)(ts[i])
51+
}
52+
53+
return json.Marshal(terms)
54+
}
55+
56+
func (ts TermsSuggest) _type() string {
57+
return "term suggester"
58+
}
59+
60+
type TermSuggesterS struct {
61+
Name string `json:"-"` //
62+
Text string `json:"text,omitempty"` // The suggest text. The suggest text is a required option that needs to be set globally or per suggestion.
63+
Term TermS `json:"term"` // (Required) The term suggester suggests terms based on edit distance. The provided suggest text is analyzed before terms are suggested. The suggested terms are provided per analyzed suggest text token. The term suggester doesn’t take the query into account that is part of request.
64+
}
65+
66+
func (t TermSuggesterS) GetName() string {
67+
return t.Name
68+
}
69+
70+
type TermS struct {
71+
Field string `json:"field"` // The field to fetch the candidate suggestions from. This is a required option that either needs to be set globally or per suggestion.
72+
Analyzer string `json:"analyzer,omitempty"` // The analyzer to analyse the suggest text with. Defaults to the search analyzer of the suggest field.
73+
Size int `json:"size,omitempty"` // The maximum corrections to be returned per suggest text token.
74+
Sort SuggestSort `json:"sort,omitempty"` // Defines how suggestions should be sorted per suggest text term. Two possible values: score, frequency
75+
SuggestMode SuggestMode `json:"suggest_mode,omitempty"`
76+
}
77+
78+
// SuggestSort - Defines how suggestions should be sorted per suggest text term.
79+
type SuggestSort string
80+
81+
const (
82+
// SortScore - Sort by score first, then document frequency and then the term itself.
83+
SortScore SuggestSort = "score"
84+
// FrequencyScore - Sort by document frequency first, then similarity score and then the term itself.
85+
FrequencyScore SuggestSort = "frequency"
86+
)
87+
88+
// SuggestMode - The suggest mode controls what suggestions are included or controls
89+
// for what suggest text terms, suggestions should be suggested.
90+
type SuggestMode string
91+
92+
const (
93+
// SuggestModeMissing - Only provide suggestions for suggest text terms that are not in the index (default).
94+
SuggestModeMissing SuggestMode = "score"
95+
// SuggestModePopular - Only suggest suggestions that occur in more docs than the original suggest text term.
96+
SuggestModePopular SuggestMode = "popular"
97+
// Suggest any matching suggestions based on terms in the suggest text.
98+
SuggestModeAlways SuggestMode = "always"
99+
)
100+
101+
type TermSuggestOption func(*TermS)
102+
103+
func WithTermSuggestAnalyzer(analyzer string) TermSuggestOption {
104+
return func(termSuggest *TermS) {
105+
termSuggest.Analyzer = analyzer
106+
}
107+
}
108+
109+
func WithTermSuggestSize(size int) TermSuggestOption {
110+
return func(termSuggest *TermS) {
111+
termSuggest.Size = size
112+
}
113+
}
114+
115+
func WithTermSuggestSort(sort SuggestSort) TermSuggestOption {
116+
return func(termSuggest *TermS) {
117+
termSuggest.Sort = sort
118+
}
119+
}
120+
121+
func WithTermSuggestMode(mode SuggestMode) TermSuggestOption {
122+
return func(termSuggest *TermS) {
123+
termSuggest.SuggestMode = mode
124+
}
125+
}
126+
127+
func Term(name, text, field string, opts ...TermSuggestOption) TermSuggest {
128+
s := TermSuggesterS{
129+
Name: name,
130+
Text: text,
131+
Term: TermS{
132+
Field: field,
133+
},
134+
}
135+
for _, opt := range opts {
136+
opt(&s.Term)
137+
}
138+
return s
139+
}
140+
141+
type TermSuggest interface {
142+
GetName() string
143+
}
144+
145+
// TermSuggester - https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters.html#term-suggester
146+
func TermSuggester(terms ...TermSuggest) Suggester {
147+
v := make(TermsSuggest, 0, len(terms))
148+
for i := range terms {
149+
v = append(v, terms[i])
150+
}
151+
return v
152+
}

objects/search_suggest_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package objects
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func Test_Searhc_Suggest_MarshalJSON(t *testing.T) {
10+
s := Suggesters("test", TermSuggester(
11+
Term("my-suggestion-1", "tring out Elasticsearch", "message"),
12+
Term("my-suggestion-2", "tring out Elasticsearch", "message",
13+
WithTermSuggestMode(SuggestModeAlways),
14+
WithTermSuggestAnalyzer("test"),
15+
WithTermSuggestSize(1),
16+
WithTermSuggestSort(SortScore),
17+
),
18+
))
19+
20+
body, err := s.Ok.MarshalJSON()
21+
require.NoError(t, err)
22+
23+
const expected = `{"suggest":{"my-suggestion-1":{"text":"tring out Elasticsearch","term":{"field":"message"}},"my-suggestion-2":{"text":"tring out Elasticsearch","term":{"field":"message","analyzer":"test","size":1,"sort":"score","suggest_mode":"always"}}}}`
24+
require.Equal(t, expected, string(body))
25+
}

0 commit comments

Comments
 (0)