Skip to content

Commit 51b44b6

Browse files
committed
Add missing properties to Count API
The Count service was missing a few properties from the REST API.
1 parent e310ae7 commit 51b44b6

File tree

3 files changed

+270
-59
lines changed

3 files changed

+270
-59
lines changed

client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222

2323
const (
2424
// Version is the current version of Elastic.
25-
Version = "3.0.1"
25+
Version = "3.0.2"
2626

2727
// DefaultUrl is the default endpoint of Elasticsearch on the local machine.
2828
// It is used e.g. when initializing a new Client without a specific URL.

count.go

+228-58
Original file line numberDiff line numberDiff line change
@@ -17,99 +17,259 @@ import (
1717
// number of documents in an index. Use SearchService with
1818
// a SearchType of count for counting with queries etc.
1919
type CountService struct {
20-
client *Client
21-
indices []string
22-
types []string
23-
query Query
24-
pretty bool
25-
}
26-
27-
// CountResult is the result returned from using the Count API
28-
// (http://www.elasticsearch.org/guide/reference/api/count/)
29-
type CountResult struct {
30-
Count int64 `json:"count"`
31-
Shards shardsInfo `json:"_shards,omitempty"`
20+
client *Client
21+
pretty bool
22+
index []string
23+
typ []string
24+
allowNoIndices *bool
25+
analyzeWildcard *bool
26+
analyzer string
27+
defaultOperator string
28+
df string
29+
expandWildcards string
30+
ignoreUnavailable *bool
31+
lenient *bool
32+
lowercaseExpandedTerms *bool
33+
minScore interface{}
34+
preference string
35+
q string
36+
query Query
37+
routing string
38+
bodyJson interface{}
39+
bodyString string
3240
}
3341

42+
// NewCountService creates a new CountService.
3443
func NewCountService(client *Client) *CountService {
35-
builder := &CountService{
44+
return &CountService{
3645
client: client,
3746
}
38-
return builder
3947
}
4048

41-
func (s *CountService) Index(indices ...string) *CountService {
42-
if s.indices == nil {
43-
s.indices = make([]string, 0)
49+
// Index sets the names of the indices to restrict the results.
50+
func (s *CountService) Index(index ...string) *CountService {
51+
if s.index == nil {
52+
s.index = make([]string, 0)
4453
}
45-
s.indices = append(s.indices, indices...)
54+
s.index = append(s.index, index...)
4655
return s
4756
}
4857

49-
func (s *CountService) Type(types ...string) *CountService {
50-
if s.types == nil {
51-
s.types = make([]string, 0)
58+
// Type sets the types to use to restrict the results.
59+
func (s *CountService) Type(typ ...string) *CountService {
60+
if s.typ == nil {
61+
s.typ = make([]string, 0)
5262
}
53-
s.types = append(s.types, types...)
63+
s.typ = append(s.typ, typ...)
64+
return s
65+
}
66+
67+
// AllowNoIndices indicates whether to ignore if a wildcard indices
68+
// expression resolves into no concrete indices. (This includes "_all" string
69+
// or when no indices have been specified).
70+
func (s *CountService) AllowNoIndices(allowNoIndices bool) *CountService {
71+
s.allowNoIndices = &allowNoIndices
72+
return s
73+
}
74+
75+
// AnalyzeWildcard specifies whether wildcard and prefix queries should be
76+
// analyzed (default: false).
77+
func (s *CountService) AnalyzeWildcard(analyzeWildcard bool) *CountService {
78+
s.analyzeWildcard = &analyzeWildcard
79+
return s
80+
}
81+
82+
// Analyzer specifies the analyzer to use for the query string.
83+
func (s *CountService) Analyzer(analyzer string) *CountService {
84+
s.analyzer = analyzer
85+
return s
86+
}
87+
88+
// DefaultOperator specifies the default operator for query string query (AND or OR).
89+
func (s *CountService) DefaultOperator(defaultOperator string) *CountService {
90+
s.defaultOperator = defaultOperator
91+
return s
92+
}
93+
94+
// Df specifies the field to use as default where no field prefix is given
95+
// in the query string.
96+
func (s *CountService) Df(df string) *CountService {
97+
s.df = df
98+
return s
99+
}
100+
101+
// ExpandWildcards indicates whether to expand wildcard expression to
102+
// concrete indices that are open, closed or both.
103+
func (s *CountService) ExpandWildcards(expandWildcards string) *CountService {
104+
s.expandWildcards = expandWildcards
54105
return s
55106
}
56107

108+
// IgnoreUnavailable indicates whether specified concrete indices should be
109+
// ignored when unavailable (missing or closed).
110+
func (s *CountService) IgnoreUnavailable(ignoreUnavailable bool) *CountService {
111+
s.ignoreUnavailable = &ignoreUnavailable
112+
return s
113+
}
114+
115+
// Lenient specifies whether format-based query failures (such as
116+
// providing text to a numeric field) should be ignored.
117+
func (s *CountService) Lenient(lenient bool) *CountService {
118+
s.lenient = &lenient
119+
return s
120+
}
121+
122+
// LowercaseExpandedTerms specifies whether query terms should be lowercased.
123+
func (s *CountService) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *CountService {
124+
s.lowercaseExpandedTerms = &lowercaseExpandedTerms
125+
return s
126+
}
127+
128+
// MinScore indicates to include only documents with a specific `_score`
129+
// value in the result.
130+
func (s *CountService) MinScore(minScore interface{}) *CountService {
131+
s.minScore = minScore
132+
return s
133+
}
134+
135+
// Preference specifies the node or shard the operation should be
136+
// performed on (default: random).
137+
func (s *CountService) Preference(preference string) *CountService {
138+
s.preference = preference
139+
return s
140+
}
141+
142+
// Q in the Lucene query string syntax. You can also use Query to pass
143+
// a Query struct.
144+
func (s *CountService) Q(q string) *CountService {
145+
s.q = q
146+
return s
147+
}
148+
149+
// Query specifies the query to pass. You can also pass a query string with Q.
57150
func (s *CountService) Query(query Query) *CountService {
58151
s.query = query
59152
return s
60153
}
61154

155+
// Routing specifies the routing value.
156+
func (s *CountService) Routing(routing string) *CountService {
157+
s.routing = routing
158+
return s
159+
}
160+
161+
// Pretty indicates that the JSON response be indented and human readable.
62162
func (s *CountService) Pretty(pretty bool) *CountService {
63163
s.pretty = pretty
64164
return s
65165
}
66166

67-
func (s *CountService) Do() (int64, error) {
68-
var err error
167+
// BodyJson specifies the query to restrict the results specified with the
168+
// Query DSL (optional). The interface{} will be serialized to a JSON document,
169+
// so use a map[string]interface{}.
170+
func (s *CountService) BodyJson(body interface{}) *CountService {
171+
s.bodyJson = body
172+
return s
173+
}
69174

70-
// Build url
71-
path := "/"
175+
// Body specifies a query to restrict the results specified with
176+
// the Query DSL (optional).
177+
func (s *CountService) BodyString(body string) *CountService {
178+
s.bodyString = body
179+
return s
180+
}
72181

73-
// Indices part
74-
indexPart := make([]string, 0)
75-
for _, index := range s.indices {
76-
index, err = uritemplates.Expand("{index}", map[string]string{
77-
"index": index,
182+
// buildURL builds the URL for the operation.
183+
func (s *CountService) buildURL() (string, url.Values, error) {
184+
var err error
185+
var path string
186+
187+
if len(s.index) > 0 && len(s.typ) > 0 {
188+
path, err = uritemplates.Expand("/{index}/{type}/_count", map[string]string{
189+
"index": strings.Join(s.index, ","),
190+
"type": strings.Join(s.typ, ","),
78191
})
79-
if err != nil {
80-
return 0, err
81-
}
82-
indexPart = append(indexPart, index)
192+
} else if len(s.index) > 0 {
193+
path, err = uritemplates.Expand("/{index}/_count", map[string]string{
194+
"index": strings.Join(s.index, ","),
195+
})
196+
} else if len(s.typ) > 0 {
197+
path, err = uritemplates.Expand("/_all/{type}/_count", map[string]string{
198+
"type": strings.Join(s.typ, ","),
199+
})
200+
} else {
201+
path = "/_all/_count"
83202
}
84-
if len(indexPart) > 0 {
85-
path += strings.Join(indexPart, ",")
203+
if err != nil {
204+
return "", url.Values{}, err
86205
}
87206

88-
// Types part
89-
typesPart := make([]string, 0)
90-
for _, typ := range s.types {
91-
typ, err = uritemplates.Expand("{type}", map[string]string{
92-
"type": typ,
93-
})
94-
if err != nil {
95-
return 0, err
96-
}
97-
typesPart = append(typesPart, typ)
207+
// Add query string parameters
208+
params := url.Values{}
209+
if s.pretty {
210+
params.Set("pretty", "1")
211+
}
212+
if s.allowNoIndices != nil {
213+
params.Set("allow_no_indices", fmt.Sprintf("%v", *s.allowNoIndices))
214+
}
215+
if s.analyzeWildcard != nil {
216+
params.Set("analyze_wildcard", fmt.Sprintf("%v", *s.analyzeWildcard))
217+
}
218+
if s.analyzer != "" {
219+
params.Set("analyzer", s.analyzer)
220+
}
221+
if s.defaultOperator != "" {
222+
params.Set("default_operator", s.defaultOperator)
98223
}
99-
if len(typesPart) > 0 {
100-
path += "/" + strings.Join(typesPart, ",")
224+
if s.df != "" {
225+
params.Set("df", s.df)
101226
}
227+
if s.expandWildcards != "" {
228+
params.Set("expand_wildcards", s.expandWildcards)
229+
}
230+
if s.ignoreUnavailable != nil {
231+
params.Set("ignore_unavailable", fmt.Sprintf("%v", *s.ignoreUnavailable))
232+
}
233+
if s.lenient != nil {
234+
params.Set("lenient", fmt.Sprintf("%v", *s.lenient))
235+
}
236+
if s.lowercaseExpandedTerms != nil {
237+
params.Set("lowercase_expanded_terms", fmt.Sprintf("%v", *s.lowercaseExpandedTerms))
238+
}
239+
if s.minScore != nil {
240+
params.Set("min_score", fmt.Sprintf("%v", s.minScore))
241+
}
242+
if s.preference != "" {
243+
params.Set("preference", s.preference)
244+
}
245+
if s.q != "" {
246+
params.Set("q", s.q)
247+
}
248+
if s.routing != "" {
249+
params.Set("routing", s.routing)
250+
}
251+
return path, params, nil
252+
}
102253

103-
// Search
104-
path += "/_count"
254+
// Validate checks if the operation is valid.
255+
func (s *CountService) Validate() error {
256+
return nil
257+
}
105258

106-
// Parameters
107-
params := make(url.Values)
108-
if s.pretty {
109-
params.Set("pretty", fmt.Sprintf("%v", s.pretty))
259+
// Do executes the operation.
260+
func (s *CountService) Do() (int64, error) {
261+
// Check pre-conditions
262+
if err := s.Validate(); err != nil {
263+
return 0, err
264+
}
265+
266+
// Get URL for request
267+
path, params, err := s.buildURL()
268+
if err != nil {
269+
return 0, err
110270
}
111271

112-
// Set body if there is a query specified
272+
// Setup HTTP request body
113273
var body interface{}
114274
if s.query != nil {
115275
src, err := s.query.Source()
@@ -119,16 +279,20 @@ func (s *CountService) Do() (int64, error) {
119279
query := make(map[string]interface{})
120280
query["query"] = src
121281
body = query
282+
} else if s.bodyJson != nil {
283+
body = s.bodyJson
284+
} else if s.bodyString != "" {
285+
body = s.bodyString
122286
}
123287

124-
// Get response
288+
// Get HTTP response
125289
res, err := s.client.PerformRequest("POST", path, params, body)
126290
if err != nil {
127291
return 0, err
128292
}
129293

130294
// Return result
131-
ret := new(CountResult)
295+
ret := new(CountResponse)
132296
if err := json.Unmarshal(res.Body, ret); err != nil {
133297
return 0, err
134298
}
@@ -138,3 +302,9 @@ func (s *CountService) Do() (int64, error) {
138302

139303
return int64(0), nil
140304
}
305+
306+
// CountResponse is the response of using the Count API.
307+
type CountResponse struct {
308+
Count int64 `json:"count"`
309+
Shards shardsInfo `json:"_shards,omitempty"`
310+
}

0 commit comments

Comments
 (0)