search_queries_multi_match.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Copyright 2012-2015 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. "strings"
  8. )
  9. // The multi_match query builds further on top of the match query by allowing multiple fields to be specified.
  10. // For more details, see:
  11. // http://www.elasticsearch.org/guide/reference/query-dsl/multi-match-query.html
  12. type MultiMatchQuery struct {
  13. Query
  14. text interface{}
  15. fields []string
  16. fieldBoosts map[string]*float32
  17. matchQueryType string // best_fields, most_fields, cross_fields, phrase, phrase_prefix
  18. operator string // and / or
  19. analyzer string
  20. boost *float32
  21. slop *int
  22. fuzziness string
  23. prefixLength *int
  24. maxExpansions *int
  25. minimumShouldMatch string
  26. rewrite string
  27. fuzzyRewrite string
  28. useDisMax *bool
  29. tieBreaker *float32
  30. lenient *bool
  31. cutoffFrequency *float32
  32. zeroTermsQuery string
  33. queryName string
  34. }
  35. func NewMultiMatchQuery(text interface{}, fields ...string) MultiMatchQuery {
  36. q := MultiMatchQuery{
  37. text: text,
  38. fields: make([]string, 0),
  39. fieldBoosts: make(map[string]*float32),
  40. }
  41. q.fields = append(q.fields, fields...)
  42. return q
  43. }
  44. func (q MultiMatchQuery) Field(field string) MultiMatchQuery {
  45. q.fields = append(q.fields, field)
  46. return q
  47. }
  48. func (q MultiMatchQuery) FieldWithBoost(field string, boost float32) MultiMatchQuery {
  49. q.fields = append(q.fields, field)
  50. q.fieldBoosts[field] = &boost
  51. return q
  52. }
  53. // Type can be: "best_fields", "boolean", "most_fields", "cross_fields",
  54. // "phrase", or "phrase_prefix".
  55. func (q MultiMatchQuery) Type(matchQueryType string) MultiMatchQuery {
  56. zero := float32(0.0)
  57. one := float32(1.0)
  58. switch strings.ToLower(matchQueryType) {
  59. default: // best_fields / boolean
  60. q.matchQueryType = "best_fields"
  61. q.tieBreaker = &zero
  62. case "most_fields":
  63. q.matchQueryType = "most_fields"
  64. q.tieBreaker = &one
  65. case "cross_fields":
  66. q.matchQueryType = "cross_fields"
  67. q.tieBreaker = &zero
  68. case "phrase":
  69. q.matchQueryType = "phrase"
  70. q.tieBreaker = &zero
  71. case "phrase_prefix":
  72. q.matchQueryType = "phrase_prefix"
  73. q.tieBreaker = &zero
  74. }
  75. return q
  76. }
  77. func (q MultiMatchQuery) Operator(operator string) MultiMatchQuery {
  78. q.operator = operator
  79. return q
  80. }
  81. func (q MultiMatchQuery) Analyzer(analyzer string) MultiMatchQuery {
  82. q.analyzer = analyzer
  83. return q
  84. }
  85. func (q MultiMatchQuery) Boost(boost float32) MultiMatchQuery {
  86. q.boost = &boost
  87. return q
  88. }
  89. func (q MultiMatchQuery) Slop(slop int) MultiMatchQuery {
  90. q.slop = &slop
  91. return q
  92. }
  93. func (q MultiMatchQuery) Fuzziness(fuzziness string) MultiMatchQuery {
  94. q.fuzziness = fuzziness
  95. return q
  96. }
  97. func (q MultiMatchQuery) PrefixLength(prefixLength int) MultiMatchQuery {
  98. q.prefixLength = &prefixLength
  99. return q
  100. }
  101. func (q MultiMatchQuery) MaxExpansions(maxExpansions int) MultiMatchQuery {
  102. q.maxExpansions = &maxExpansions
  103. return q
  104. }
  105. func (q MultiMatchQuery) MinimumShouldMatch(minimumShouldMatch string) MultiMatchQuery {
  106. q.minimumShouldMatch = minimumShouldMatch
  107. return q
  108. }
  109. func (q MultiMatchQuery) Rewrite(rewrite string) MultiMatchQuery {
  110. q.rewrite = rewrite
  111. return q
  112. }
  113. func (q MultiMatchQuery) FuzzyRewrite(fuzzyRewrite string) MultiMatchQuery {
  114. q.fuzzyRewrite = fuzzyRewrite
  115. return q
  116. }
  117. // Deprecated.
  118. func (q MultiMatchQuery) UseDisMax(useDisMax bool) MultiMatchQuery {
  119. q.useDisMax = &useDisMax
  120. return q
  121. }
  122. func (q MultiMatchQuery) TieBreaker(tieBreaker float32) MultiMatchQuery {
  123. q.tieBreaker = &tieBreaker
  124. return q
  125. }
  126. func (q MultiMatchQuery) Lenient(lenient bool) MultiMatchQuery {
  127. q.lenient = &lenient
  128. return q
  129. }
  130. func (q MultiMatchQuery) CutoffFrequency(cutoff float32) MultiMatchQuery {
  131. q.cutoffFrequency = &cutoff
  132. return q
  133. }
  134. // ZeroTermsQuery can be "all" or "none".
  135. func (q MultiMatchQuery) ZeroTermsQuery(zeroTermsQuery string) MultiMatchQuery {
  136. q.zeroTermsQuery = zeroTermsQuery
  137. return q
  138. }
  139. func (q MultiMatchQuery) QueryName(queryName string) MultiMatchQuery {
  140. q.queryName = queryName
  141. return q
  142. }
  143. func (q MultiMatchQuery) Source() interface{} {
  144. //
  145. // {
  146. // "multi_match" : {
  147. // "query" : "this is a test",
  148. // "fields" : [ "subject", "message" ]
  149. // }
  150. // }
  151. source := make(map[string]interface{})
  152. multiMatch := make(map[string]interface{})
  153. source["multi_match"] = multiMatch
  154. multiMatch["query"] = q.text
  155. if len(q.fields) > 0 {
  156. fields := make([]string, 0)
  157. for _, field := range q.fields {
  158. if boost, found := q.fieldBoosts[field]; found {
  159. if boost != nil {
  160. fields = append(fields, fmt.Sprintf("%s^%f", field, *boost))
  161. } else {
  162. fields = append(fields, field)
  163. }
  164. } else {
  165. fields = append(fields, field)
  166. }
  167. }
  168. multiMatch["fields"] = fields
  169. }
  170. if q.matchQueryType != "" {
  171. multiMatch["type"] = q.matchQueryType
  172. }
  173. if q.operator != "" {
  174. multiMatch["operator"] = q.operator
  175. }
  176. if q.analyzer != "" {
  177. multiMatch["analyzer"] = q.analyzer
  178. }
  179. if q.boost != nil {
  180. multiMatch["boost"] = *q.boost
  181. }
  182. if q.slop != nil {
  183. multiMatch["slop"] = *q.slop
  184. }
  185. if q.fuzziness != "" {
  186. multiMatch["fuzziness"] = q.fuzziness
  187. }
  188. if q.prefixLength != nil {
  189. multiMatch["prefix_length"] = *q.prefixLength
  190. }
  191. if q.maxExpansions != nil {
  192. multiMatch["max_expansions"] = *q.maxExpansions
  193. }
  194. if q.minimumShouldMatch != "" {
  195. multiMatch["minimum_should_match"] = q.minimumShouldMatch
  196. }
  197. if q.rewrite != "" {
  198. multiMatch["rewrite"] = q.rewrite
  199. }
  200. if q.fuzzyRewrite != "" {
  201. multiMatch["fuzzy_rewrite"] = q.fuzzyRewrite
  202. }
  203. if q.useDisMax != nil {
  204. multiMatch["use_dis_max"] = *q.useDisMax
  205. }
  206. if q.tieBreaker != nil {
  207. multiMatch["tie_breaker"] = *q.tieBreaker
  208. }
  209. if q.lenient != nil {
  210. multiMatch["lenient"] = *q.lenient
  211. }
  212. if q.cutoffFrequency != nil {
  213. multiMatch["cutoff_frequency"] = *q.cutoffFrequency
  214. }
  215. if q.zeroTermsQuery != "" {
  216. multiMatch["zero_terms_query"] = q.zeroTermsQuery
  217. }
  218. if q.queryName != "" {
  219. multiMatch["_name"] = q.queryName
  220. }
  221. return source
  222. }