search_queries_query_string.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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. "fmt"
  7. )
  8. // QueryStringQuery uses the query parser in order to parse its content.
  9. //
  10. // For more details, see
  11. // https://www.elastic.co/guide/en/elasticsearch/reference/5.6/query-dsl-query-string-query.html
  12. type QueryStringQuery struct {
  13. queryString string
  14. defaultField string
  15. defaultOperator string
  16. analyzer string
  17. quoteAnalyzer string
  18. quoteFieldSuffix string
  19. autoGeneratePhraseQueries *bool
  20. allowLeadingWildcard *bool
  21. lowercaseExpandedTerms *bool
  22. enablePositionIncrements *bool
  23. analyzeWildcard *bool
  24. locale string // Deprecated: Decision is now made by the analyzer.
  25. boost *float64
  26. fuzziness string
  27. fuzzyPrefixLength *int
  28. fuzzyMaxExpansions *int
  29. fuzzyRewrite string
  30. phraseSlop *int
  31. fields []string
  32. fieldBoosts map[string]*float64
  33. useDisMax *bool
  34. tieBreaker *float64
  35. rewrite string
  36. minimumShouldMatch string
  37. lenient *bool
  38. queryName string
  39. timeZone string
  40. maxDeterminizedStates *int
  41. escape *bool
  42. splitOnWhitespace *bool
  43. useAllFields *bool
  44. }
  45. // NewQueryStringQuery creates and initializes a new QueryStringQuery.
  46. func NewQueryStringQuery(queryString string) *QueryStringQuery {
  47. return &QueryStringQuery{
  48. queryString: queryString,
  49. fields: make([]string, 0),
  50. fieldBoosts: make(map[string]*float64),
  51. }
  52. }
  53. // DefaultField specifies the field to run against when no prefix field
  54. // is specified. Only relevant when not explicitly adding fields the query
  55. // string will run against.
  56. func (q *QueryStringQuery) DefaultField(defaultField string) *QueryStringQuery {
  57. q.defaultField = defaultField
  58. return q
  59. }
  60. // Field adds a field to run the query string against.
  61. func (q *QueryStringQuery) Field(field string) *QueryStringQuery {
  62. q.fields = append(q.fields, field)
  63. return q
  64. }
  65. // AllFields tells the query string query to use all fields explicitly,
  66. // even if _all is enabled. If the "default_field" parameter or "fields"
  67. // are specified, they will be ignored.
  68. func (q *QueryStringQuery) AllFields(useAllFields bool) *QueryStringQuery {
  69. q.useAllFields = &useAllFields
  70. return q
  71. }
  72. // FieldWithBoost adds a field to run the query string against with a specific boost.
  73. func (q *QueryStringQuery) FieldWithBoost(field string, boost float64) *QueryStringQuery {
  74. q.fields = append(q.fields, field)
  75. q.fieldBoosts[field] = &boost
  76. return q
  77. }
  78. // UseDisMax specifies whether to combine queries using dis max or boolean
  79. // query when more zhan one field is used with the query string. Defaults
  80. // to dismax (true).
  81. func (q *QueryStringQuery) UseDisMax(useDisMax bool) *QueryStringQuery {
  82. q.useDisMax = &useDisMax
  83. return q
  84. }
  85. // TieBreaker is used when more than one field is used with the query string,
  86. // and combined queries are using dismax.
  87. func (q *QueryStringQuery) TieBreaker(tieBreaker float64) *QueryStringQuery {
  88. q.tieBreaker = &tieBreaker
  89. return q
  90. }
  91. // DefaultOperator sets the boolean operator of the query parser used to
  92. // parse the query string.
  93. //
  94. // In default mode (OR) terms without any modifiers
  95. // are considered optional, e.g. "capital of Hungary" is equal to
  96. // "capital OR of OR Hungary".
  97. //
  98. // In AND mode, terms are considered to be in conjunction. The above mentioned
  99. // query is then parsed as "capital AND of AND Hungary".
  100. func (q *QueryStringQuery) DefaultOperator(operator string) *QueryStringQuery {
  101. q.defaultOperator = operator
  102. return q
  103. }
  104. // Analyzer is an optional analyzer used to analyze the query string.
  105. // Note, if a field has search analyzer defined for it, then it will be used
  106. // automatically. Defaults to the smart search analyzer.
  107. func (q *QueryStringQuery) Analyzer(analyzer string) *QueryStringQuery {
  108. q.analyzer = analyzer
  109. return q
  110. }
  111. // QuoteAnalyzer is an optional analyzer to be used to analyze the query string
  112. // for phrase searches. Note, if a field has search analyzer defined for it,
  113. // then it will be used automatically. Defaults to the smart search analyzer.
  114. func (q *QueryStringQuery) QuoteAnalyzer(quoteAnalyzer string) *QueryStringQuery {
  115. q.quoteAnalyzer = quoteAnalyzer
  116. return q
  117. }
  118. // AutoGeneratePhraseQueries indicates whether or not phrase queries will
  119. // be automatically generated when the analyzer returns more then one term
  120. // from whitespace delimited text. Set to false if phrase queries should only
  121. // be generated when surrounded by double quotes.
  122. func (q *QueryStringQuery) AutoGeneratePhraseQueries(autoGeneratePhraseQueries bool) *QueryStringQuery {
  123. q.autoGeneratePhraseQueries = &autoGeneratePhraseQueries
  124. return q
  125. }
  126. // MaxDeterminizedState protects against too-difficult regular expression queries.
  127. func (q *QueryStringQuery) MaxDeterminizedState(maxDeterminizedStates int) *QueryStringQuery {
  128. q.maxDeterminizedStates = &maxDeterminizedStates
  129. return q
  130. }
  131. // AllowLeadingWildcard specifies whether leading wildcards should be allowed
  132. // or not (defaults to true).
  133. func (q *QueryStringQuery) AllowLeadingWildcard(allowLeadingWildcard bool) *QueryStringQuery {
  134. q.allowLeadingWildcard = &allowLeadingWildcard
  135. return q
  136. }
  137. // LowercaseExpandedTerms indicates whether terms of wildcard, prefix, fuzzy
  138. // and range queries are automatically lower-cased or not. Default is true.
  139. func (q *QueryStringQuery) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *QueryStringQuery {
  140. q.lowercaseExpandedTerms = &lowercaseExpandedTerms
  141. return q
  142. }
  143. // EnablePositionIncrements indicates whether to enable position increments
  144. // in result query. Defaults to true.
  145. //
  146. // When set, result phrase and multi-phrase queries will be aware of position
  147. // increments. Useful when e.g. a StopFilter increases the position increment
  148. // of the token that follows an omitted token.
  149. func (q *QueryStringQuery) EnablePositionIncrements(enablePositionIncrements bool) *QueryStringQuery {
  150. q.enablePositionIncrements = &enablePositionIncrements
  151. return q
  152. }
  153. // Fuzziness sets the edit distance for fuzzy queries. Default is "AUTO".
  154. func (q *QueryStringQuery) Fuzziness(fuzziness string) *QueryStringQuery {
  155. q.fuzziness = fuzziness
  156. return q
  157. }
  158. // FuzzyPrefixLength sets the minimum prefix length for fuzzy queries.
  159. // Default is 1.
  160. func (q *QueryStringQuery) FuzzyPrefixLength(fuzzyPrefixLength int) *QueryStringQuery {
  161. q.fuzzyPrefixLength = &fuzzyPrefixLength
  162. return q
  163. }
  164. func (q *QueryStringQuery) FuzzyMaxExpansions(fuzzyMaxExpansions int) *QueryStringQuery {
  165. q.fuzzyMaxExpansions = &fuzzyMaxExpansions
  166. return q
  167. }
  168. func (q *QueryStringQuery) FuzzyRewrite(fuzzyRewrite string) *QueryStringQuery {
  169. q.fuzzyRewrite = fuzzyRewrite
  170. return q
  171. }
  172. // PhraseSlop sets the default slop for phrases. If zero, then exact matches
  173. // are required. Default value is zero.
  174. func (q *QueryStringQuery) PhraseSlop(phraseSlop int) *QueryStringQuery {
  175. q.phraseSlop = &phraseSlop
  176. return q
  177. }
  178. // AnalyzeWildcard indicates whether to enabled analysis on wildcard and prefix queries.
  179. func (q *QueryStringQuery) AnalyzeWildcard(analyzeWildcard bool) *QueryStringQuery {
  180. q.analyzeWildcard = &analyzeWildcard
  181. return q
  182. }
  183. func (q *QueryStringQuery) Rewrite(rewrite string) *QueryStringQuery {
  184. q.rewrite = rewrite
  185. return q
  186. }
  187. func (q *QueryStringQuery) MinimumShouldMatch(minimumShouldMatch string) *QueryStringQuery {
  188. q.minimumShouldMatch = minimumShouldMatch
  189. return q
  190. }
  191. // Boost sets the boost for this query.
  192. func (q *QueryStringQuery) Boost(boost float64) *QueryStringQuery {
  193. q.boost = &boost
  194. return q
  195. }
  196. // QuoteFieldSuffix is an optional field name suffix to automatically
  197. // try and add to the field searched when using quoted text.
  198. func (q *QueryStringQuery) QuoteFieldSuffix(quoteFieldSuffix string) *QueryStringQuery {
  199. q.quoteFieldSuffix = quoteFieldSuffix
  200. return q
  201. }
  202. // Lenient indicates whether the query string parser should be lenient
  203. // when parsing field values. It defaults to the index setting and if not
  204. // set, defaults to false.
  205. func (q *QueryStringQuery) Lenient(lenient bool) *QueryStringQuery {
  206. q.lenient = &lenient
  207. return q
  208. }
  209. // QueryName sets the query name for the filter that can be used when
  210. // searching for matched_filters per hit.
  211. func (q *QueryStringQuery) QueryName(queryName string) *QueryStringQuery {
  212. q.queryName = queryName
  213. return q
  214. }
  215. // Locale specifies the locale to be used for string conversions.
  216. //
  217. // Deprecated: Decision is now made by the analyzer.
  218. func (q *QueryStringQuery) Locale(locale string) *QueryStringQuery {
  219. q.locale = locale
  220. return q
  221. }
  222. // TimeZone can be used to automatically adjust to/from fields using a
  223. // timezone. Only used with date fields, of course.
  224. func (q *QueryStringQuery) TimeZone(timeZone string) *QueryStringQuery {
  225. q.timeZone = timeZone
  226. return q
  227. }
  228. // Escape performs escaping of the query string.
  229. func (q *QueryStringQuery) Escape(escape bool) *QueryStringQuery {
  230. q.escape = &escape
  231. return q
  232. }
  233. // SplitOnWhitespace indicates whether query text should be split on whitespace
  234. // prior to analysis.
  235. func (q *QueryStringQuery) SplitOnWhitespace(splitOnWhitespace bool) *QueryStringQuery {
  236. q.splitOnWhitespace = &splitOnWhitespace
  237. return q
  238. }
  239. // Source returns JSON for the query.
  240. func (q *QueryStringQuery) Source() (interface{}, error) {
  241. source := make(map[string]interface{})
  242. query := make(map[string]interface{})
  243. source["query_string"] = query
  244. query["query"] = q.queryString
  245. if q.defaultField != "" {
  246. query["default_field"] = q.defaultField
  247. }
  248. if len(q.fields) > 0 {
  249. var fields []string
  250. for _, field := range q.fields {
  251. if boost, found := q.fieldBoosts[field]; found {
  252. if boost != nil {
  253. fields = append(fields, fmt.Sprintf("%s^%f", field, *boost))
  254. } else {
  255. fields = append(fields, field)
  256. }
  257. } else {
  258. fields = append(fields, field)
  259. }
  260. }
  261. query["fields"] = fields
  262. }
  263. if q.tieBreaker != nil {
  264. query["tie_breaker"] = *q.tieBreaker
  265. }
  266. if q.useDisMax != nil {
  267. query["use_dis_max"] = *q.useDisMax
  268. }
  269. if q.defaultOperator != "" {
  270. query["default_operator"] = q.defaultOperator
  271. }
  272. if q.analyzer != "" {
  273. query["analyzer"] = q.analyzer
  274. }
  275. if q.quoteAnalyzer != "" {
  276. query["quote_analyzer"] = q.quoteAnalyzer
  277. }
  278. if q.autoGeneratePhraseQueries != nil {
  279. query["auto_generate_phrase_queries"] = *q.autoGeneratePhraseQueries
  280. }
  281. if q.maxDeterminizedStates != nil {
  282. query["max_determinized_states"] = *q.maxDeterminizedStates
  283. }
  284. if q.allowLeadingWildcard != nil {
  285. query["allow_leading_wildcard"] = *q.allowLeadingWildcard
  286. }
  287. if q.lowercaseExpandedTerms != nil {
  288. query["lowercase_expanded_terms"] = *q.lowercaseExpandedTerms
  289. }
  290. if q.enablePositionIncrements != nil {
  291. query["enable_position_increments"] = *q.enablePositionIncrements
  292. }
  293. if q.fuzziness != "" {
  294. query["fuzziness"] = q.fuzziness
  295. }
  296. if q.boost != nil {
  297. query["boost"] = *q.boost
  298. }
  299. if q.fuzzyPrefixLength != nil {
  300. query["fuzzy_prefix_length"] = *q.fuzzyPrefixLength
  301. }
  302. if q.fuzzyMaxExpansions != nil {
  303. query["fuzzy_max_expansions"] = *q.fuzzyMaxExpansions
  304. }
  305. if q.fuzzyRewrite != "" {
  306. query["fuzzy_rewrite"] = q.fuzzyRewrite
  307. }
  308. if q.phraseSlop != nil {
  309. query["phrase_slop"] = *q.phraseSlop
  310. }
  311. if q.analyzeWildcard != nil {
  312. query["analyze_wildcard"] = *q.analyzeWildcard
  313. }
  314. if q.rewrite != "" {
  315. query["rewrite"] = q.rewrite
  316. }
  317. if q.minimumShouldMatch != "" {
  318. query["minimum_should_match"] = q.minimumShouldMatch
  319. }
  320. if q.quoteFieldSuffix != "" {
  321. query["quote_field_suffix"] = q.quoteFieldSuffix
  322. }
  323. if q.lenient != nil {
  324. query["lenient"] = *q.lenient
  325. }
  326. if q.queryName != "" {
  327. query["_name"] = q.queryName
  328. }
  329. if q.locale != "" {
  330. query["locale"] = q.locale
  331. }
  332. if q.timeZone != "" {
  333. query["time_zone"] = q.timeZone
  334. }
  335. if q.escape != nil {
  336. query["escape"] = *q.escape
  337. }
  338. if q.splitOnWhitespace != nil {
  339. query["split_on_whitespace"] = *q.splitOnWhitespace
  340. }
  341. if q.useAllFields != nil {
  342. query["all_fields"] = *q.useAllFields
  343. }
  344. return source, nil
  345. }