-
Notifications
You must be signed in to change notification settings - Fork 104
/
cluster_searchquery.go
176 lines (150 loc) · 4.54 KB
/
cluster_searchquery.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package gocb
import (
"encoding/json"
"time"
cbsearch "github.com/couchbase/gocb/v2/search"
)
// SearchQuery executes the search query on the server.
func (c *Cluster) SearchQuery(indexName string, query cbsearch.Query, opts *SearchOptions) (*SearchResult, error) {
if opts == nil {
opts = &SearchOptions{}
}
provider, err := c.getSearchProvider()
if err != nil {
return nil, &SearchError{
InnerError: wrapError(err, "failed to get search provider"),
Query: query,
}
}
return provider.SearchQuery(indexName, query, opts)
}
// Search executes the search request on the server.
func (c *Cluster) Search(indexName string, request SearchRequest, opts *SearchOptions) (*SearchResult, error) {
if request.VectorSearch == nil && request.SearchQuery == nil {
return nil, makeInvalidArgumentsError("the search request cannot be empty")
}
if opts == nil {
opts = &SearchOptions{}
}
provider, err := c.getSearchProvider()
if err != nil {
return nil, &SearchError{
InnerError: wrapError(err, "failed to get search provider"),
Query: request,
}
}
return provider.Search(nil, indexName, request, opts)
}
func maybeGetSearchOptionQuery(options map[string]interface{}) interface{} {
if value, ok := options["query"]; ok {
return value
}
return ""
}
// SearchMetrics encapsulates various metrics gathered during a search queries execution.
type SearchMetrics struct {
Took time.Duration
TotalRows uint64
MaxScore float64
TotalPartitionCount uint64
SuccessPartitionCount uint64
ErrorPartitionCount uint64
}
func (metrics *SearchMetrics) fromData(data jsonSearchResponse) error {
metrics.TotalRows = data.TotalHits
metrics.MaxScore = data.MaxScore
metrics.Took = time.Duration(data.Took) / time.Nanosecond
metrics.TotalPartitionCount = data.Status.Successful + data.Status.Failed
metrics.SuccessPartitionCount = data.Status.Successful
metrics.ErrorPartitionCount = data.Status.Failed
return nil
}
// SearchMetaData provides access to the meta-data properties of a search query result.
type SearchMetaData struct {
Metrics SearchMetrics
Errors map[string]string
}
func (meta *SearchMetaData) fromData(data jsonSearchResponse) error {
metrics := SearchMetrics{}
if err := metrics.fromData(data); err != nil {
return err
}
meta.Metrics = metrics
meta.Errors = data.Status.Errors
return nil
}
// SearchTermFacetResult holds the results of a term facet in search results.
type SearchTermFacetResult struct {
Term string
Count int
}
// SearchNumericRangeFacetResult holds the results of a numeric facet in search results.
type SearchNumericRangeFacetResult struct {
Name string
Min float64
Max float64
Count int
}
// SearchDateRangeFacetResult holds the results of a date facet in search results.
type SearchDateRangeFacetResult struct {
Name string
Start string
End string
Count int
}
// SearchFacetResult provides access to the result of a faceted query.
type SearchFacetResult struct {
Name string
Field string
Total uint64
Missing uint64
Other uint64
Terms []SearchTermFacetResult
NumericRanges []SearchNumericRangeFacetResult
DateRanges []SearchDateRangeFacetResult
}
func (fr *SearchFacetResult) fromData(data jsonSearchFacet) error {
fr.Name = data.Name
fr.Field = data.Field
fr.Total = data.Total
fr.Missing = data.Missing
fr.Other = data.Other
for _, term := range data.Terms {
fr.Terms = append(fr.Terms, SearchTermFacetResult(term))
}
for _, nr := range data.NumericRanges {
fr.NumericRanges = append(fr.NumericRanges, SearchNumericRangeFacetResult(nr))
}
for _, nr := range data.DateRanges {
fr.DateRanges = append(fr.DateRanges, SearchDateRangeFacetResult(nr))
}
return nil
}
// SearchRowLocation represents the location of a row match
type SearchRowLocation struct {
Position uint32
Start uint32
End uint32
ArrayPositions []uint32
}
func (rl *SearchRowLocation) fromData(data jsonRowLocation) error {
rl.Position = data.Position
rl.Start = data.Start
rl.End = data.End
rl.ArrayPositions = data.ArrayPositions
return nil
}
// SearchRow represents a single hit returned from a search query.
type SearchRow struct {
Index string
ID string
Score float64
Explanation interface{}
Locations map[string]map[string][]SearchRowLocation
Fragments map[string][]string
fieldsBytes []byte
}
// Fields decodes the fields included in a search hit.
func (sr *SearchRow) Fields(valuePtr interface{}) error {
return json.Unmarshal(sr.fieldsBytes, valuePtr)
}