Test
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

search_queries_query_string.go 11KB

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