search_request.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2012-present Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. package elastic
  5. import (
  6. "encoding/json"
  7. "strings"
  8. )
  9. // SearchRequest combines a search request and its
  10. // query details (see SearchSource).
  11. // It is used in combination with MultiSearch.
  12. type SearchRequest struct {
  13. searchType string
  14. indices []string
  15. types []string
  16. routing *string
  17. preference *string
  18. requestCache *bool
  19. ignoreUnavailable *bool
  20. allowNoIndices *bool
  21. expandWildcards string
  22. scroll string
  23. source interface{}
  24. }
  25. // NewSearchRequest creates a new search request.
  26. func NewSearchRequest() *SearchRequest {
  27. return &SearchRequest{}
  28. }
  29. // SearchRequest must be one of dfs_query_then_fetch, query_then_fetch
  30. // or query_and_fetch (deprecated in 5.3).
  31. func (r *SearchRequest) SearchType(searchType string) *SearchRequest {
  32. r.searchType = searchType
  33. return r
  34. }
  35. // SearchTypeDfsQueryThenFetch sets search type to dfs_query_then_fetch.
  36. func (r *SearchRequest) SearchTypeDfsQueryThenFetch() *SearchRequest {
  37. return r.SearchType("dfs_query_then_fetch")
  38. }
  39. // SearchTypeQueryThenFetch sets search type to query_then_fetch.
  40. func (r *SearchRequest) SearchTypeQueryThenFetch() *SearchRequest {
  41. return r.SearchType("query_then_fetch")
  42. }
  43. // SearchTypeQueryAndFetch sets search type to query_and_fetch which
  44. // was deprecated in 5.3.
  45. func (r *SearchRequest) SearchTypeQueryAndFetch() *SearchRequest {
  46. return r.SearchType("query_and_fetch")
  47. }
  48. func (r *SearchRequest) Index(indices ...string) *SearchRequest {
  49. r.indices = append(r.indices, indices...)
  50. return r
  51. }
  52. func (r *SearchRequest) HasIndices() bool {
  53. return len(r.indices) > 0
  54. }
  55. func (r *SearchRequest) Type(types ...string) *SearchRequest {
  56. r.types = append(r.types, types...)
  57. return r
  58. }
  59. func (r *SearchRequest) Routing(routing string) *SearchRequest {
  60. r.routing = &routing
  61. return r
  62. }
  63. func (r *SearchRequest) Routings(routings ...string) *SearchRequest {
  64. if routings != nil {
  65. routings := strings.Join(routings, ",")
  66. r.routing = &routings
  67. } else {
  68. r.routing = nil
  69. }
  70. return r
  71. }
  72. func (r *SearchRequest) Preference(preference string) *SearchRequest {
  73. r.preference = &preference
  74. return r
  75. }
  76. func (r *SearchRequest) RequestCache(requestCache bool) *SearchRequest {
  77. r.requestCache = &requestCache
  78. return r
  79. }
  80. // IgnoreUnavailable indicates whether specified concrete indices should be
  81. // ignored when unavailable (missing or closed).
  82. func (s *SearchRequest) IgnoreUnavailable(ignoreUnavailable bool) *SearchRequest {
  83. s.ignoreUnavailable = &ignoreUnavailable
  84. return s
  85. }
  86. // AllowNoIndices indicates whether to ignore if a wildcard indices
  87. // expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified).
  88. func (s *SearchRequest) AllowNoIndices(allowNoIndices bool) *SearchRequest {
  89. s.allowNoIndices = &allowNoIndices
  90. return s
  91. }
  92. // ExpandWildcards indicates whether to expand wildcard expression to
  93. // concrete indices that are open, closed or both.
  94. func (s *SearchRequest) ExpandWildcards(expandWildcards string) *SearchRequest {
  95. s.expandWildcards = expandWildcards
  96. return s
  97. }
  98. func (r *SearchRequest) Scroll(scroll string) *SearchRequest {
  99. r.scroll = scroll
  100. return r
  101. }
  102. func (r *SearchRequest) SearchSource(searchSource *SearchSource) *SearchRequest {
  103. return r.Source(searchSource)
  104. }
  105. func (r *SearchRequest) Source(source interface{}) *SearchRequest {
  106. r.source = source
  107. return r
  108. }
  109. // header is used e.g. by MultiSearch to get information about the search header
  110. // of one SearchRequest.
  111. // See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-multi-search.html
  112. func (r *SearchRequest) header() interface{} {
  113. h := make(map[string]interface{})
  114. if r.searchType != "" {
  115. h["search_type"] = r.searchType
  116. }
  117. switch len(r.indices) {
  118. case 0:
  119. case 1:
  120. h["index"] = r.indices[0]
  121. default:
  122. h["indices"] = r.indices
  123. }
  124. switch len(r.types) {
  125. case 0:
  126. case 1:
  127. h["type"] = r.types[0]
  128. default:
  129. h["types"] = r.types
  130. }
  131. if r.routing != nil && *r.routing != "" {
  132. h["routing"] = *r.routing
  133. }
  134. if r.preference != nil && *r.preference != "" {
  135. h["preference"] = *r.preference
  136. }
  137. if r.requestCache != nil {
  138. h["request_cache"] = *r.requestCache
  139. }
  140. if r.ignoreUnavailable != nil {
  141. h["ignore_unavailable"] = *r.ignoreUnavailable
  142. }
  143. if r.allowNoIndices != nil {
  144. h["allow_no_indices"] = *r.allowNoIndices
  145. }
  146. if r.expandWildcards != "" {
  147. h["expand_wildcards"] = r.expandWildcards
  148. }
  149. if r.scroll != "" {
  150. h["scroll"] = r.scroll
  151. }
  152. return h
  153. }
  154. // Body allows to access the search body of the request, as generated by the DSL.
  155. // Notice that Body is read-only. You must not change the request body.
  156. //
  157. // Body is used e.g. by MultiSearch to get information about the search body
  158. // of one SearchRequest.
  159. // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-multi-search.html
  160. func (r *SearchRequest) Body() (string, error) {
  161. switch t := r.source.(type) {
  162. default:
  163. body, err := json.Marshal(r.source)
  164. if err != nil {
  165. return "", err
  166. }
  167. return string(body), nil
  168. case *SearchSource:
  169. src, err := t.Source()
  170. if err != nil {
  171. return "", err
  172. }
  173. body, err := json.Marshal(src)
  174. if err != nil {
  175. return "", err
  176. }
  177. return string(body), nil
  178. case json.RawMessage:
  179. return string(t), nil
  180. case *json.RawMessage:
  181. return string(*t), nil
  182. case string:
  183. return t, nil
  184. case *string:
  185. if t != nil {
  186. return *t, nil
  187. }
  188. return "{}", nil
  189. }
  190. }