Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

query.go 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // Copyright (c) 2014 Couchbase, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package query
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "io/ioutil"
  19. "log"
  20. "github.com/blevesearch/bleve/index"
  21. "github.com/blevesearch/bleve/mapping"
  22. "github.com/blevesearch/bleve/search"
  23. )
  24. var logger = log.New(ioutil.Discard, "bleve mapping ", log.LstdFlags)
  25. // SetLog sets the logger used for logging
  26. // by default log messages are sent to ioutil.Discard
  27. func SetLog(l *log.Logger) {
  28. logger = l
  29. }
  30. // A Query represents a description of the type
  31. // and parameters for a query into the index.
  32. type Query interface {
  33. Searcher(i index.IndexReader, m mapping.IndexMapping,
  34. options search.SearcherOptions) (search.Searcher, error)
  35. }
  36. // A BoostableQuery represents a Query which can be boosted
  37. // relative to other queries.
  38. type BoostableQuery interface {
  39. Query
  40. SetBoost(b float64)
  41. Boost() float64
  42. }
  43. // A FieldableQuery represents a Query which can be restricted
  44. // to a single field.
  45. type FieldableQuery interface {
  46. Query
  47. SetField(f string)
  48. Field() string
  49. }
  50. // A ValidatableQuery represents a Query which can be validated
  51. // prior to execution.
  52. type ValidatableQuery interface {
  53. Query
  54. Validate() error
  55. }
  56. // ParseQuery deserializes a JSON representation of
  57. // a Query object.
  58. func ParseQuery(input []byte) (Query, error) {
  59. var tmp map[string]interface{}
  60. err := json.Unmarshal(input, &tmp)
  61. if err != nil {
  62. return nil, err
  63. }
  64. _, isMatchQuery := tmp["match"]
  65. _, hasFuzziness := tmp["fuzziness"]
  66. if hasFuzziness && !isMatchQuery {
  67. var rv FuzzyQuery
  68. err := json.Unmarshal(input, &rv)
  69. if err != nil {
  70. return nil, err
  71. }
  72. return &rv, nil
  73. }
  74. _, isTermQuery := tmp["term"]
  75. if isTermQuery {
  76. var rv TermQuery
  77. err := json.Unmarshal(input, &rv)
  78. if err != nil {
  79. return nil, err
  80. }
  81. return &rv, nil
  82. }
  83. if isMatchQuery {
  84. var rv MatchQuery
  85. err := json.Unmarshal(input, &rv)
  86. if err != nil {
  87. return nil, err
  88. }
  89. return &rv, nil
  90. }
  91. _, isMatchPhraseQuery := tmp["match_phrase"]
  92. if isMatchPhraseQuery {
  93. var rv MatchPhraseQuery
  94. err := json.Unmarshal(input, &rv)
  95. if err != nil {
  96. return nil, err
  97. }
  98. return &rv, nil
  99. }
  100. _, hasMust := tmp["must"]
  101. _, hasShould := tmp["should"]
  102. _, hasMustNot := tmp["must_not"]
  103. if hasMust || hasShould || hasMustNot {
  104. var rv BooleanQuery
  105. err := json.Unmarshal(input, &rv)
  106. if err != nil {
  107. return nil, err
  108. }
  109. return &rv, nil
  110. }
  111. _, hasTerms := tmp["terms"]
  112. if hasTerms {
  113. var rv PhraseQuery
  114. err := json.Unmarshal(input, &rv)
  115. if err != nil {
  116. // now try multi-phrase
  117. var rv2 MultiPhraseQuery
  118. err = json.Unmarshal(input, &rv2)
  119. if err != nil {
  120. return nil, err
  121. }
  122. return &rv2, nil
  123. }
  124. return &rv, nil
  125. }
  126. _, hasConjuncts := tmp["conjuncts"]
  127. if hasConjuncts {
  128. var rv ConjunctionQuery
  129. err := json.Unmarshal(input, &rv)
  130. if err != nil {
  131. return nil, err
  132. }
  133. return &rv, nil
  134. }
  135. _, hasDisjuncts := tmp["disjuncts"]
  136. if hasDisjuncts {
  137. var rv DisjunctionQuery
  138. err := json.Unmarshal(input, &rv)
  139. if err != nil {
  140. return nil, err
  141. }
  142. return &rv, nil
  143. }
  144. _, hasSyntaxQuery := tmp["query"]
  145. if hasSyntaxQuery {
  146. var rv QueryStringQuery
  147. err := json.Unmarshal(input, &rv)
  148. if err != nil {
  149. return nil, err
  150. }
  151. return &rv, nil
  152. }
  153. _, hasMin := tmp["min"].(float64)
  154. _, hasMax := tmp["max"].(float64)
  155. if hasMin || hasMax {
  156. var rv NumericRangeQuery
  157. err := json.Unmarshal(input, &rv)
  158. if err != nil {
  159. return nil, err
  160. }
  161. return &rv, nil
  162. }
  163. _, hasMinStr := tmp["min"].(string)
  164. _, hasMaxStr := tmp["max"].(string)
  165. if hasMinStr || hasMaxStr {
  166. var rv TermRangeQuery
  167. err := json.Unmarshal(input, &rv)
  168. if err != nil {
  169. return nil, err
  170. }
  171. return &rv, nil
  172. }
  173. _, hasStart := tmp["start"]
  174. _, hasEnd := tmp["end"]
  175. if hasStart || hasEnd {
  176. var rv DateRangeQuery
  177. err := json.Unmarshal(input, &rv)
  178. if err != nil {
  179. return nil, err
  180. }
  181. return &rv, nil
  182. }
  183. _, hasPrefix := tmp["prefix"]
  184. if hasPrefix {
  185. var rv PrefixQuery
  186. err := json.Unmarshal(input, &rv)
  187. if err != nil {
  188. return nil, err
  189. }
  190. return &rv, nil
  191. }
  192. _, hasRegexp := tmp["regexp"]
  193. if hasRegexp {
  194. var rv RegexpQuery
  195. err := json.Unmarshal(input, &rv)
  196. if err != nil {
  197. return nil, err
  198. }
  199. return &rv, nil
  200. }
  201. _, hasWildcard := tmp["wildcard"]
  202. if hasWildcard {
  203. var rv WildcardQuery
  204. err := json.Unmarshal(input, &rv)
  205. if err != nil {
  206. return nil, err
  207. }
  208. return &rv, nil
  209. }
  210. _, hasMatchAll := tmp["match_all"]
  211. if hasMatchAll {
  212. var rv MatchAllQuery
  213. err := json.Unmarshal(input, &rv)
  214. if err != nil {
  215. return nil, err
  216. }
  217. return &rv, nil
  218. }
  219. _, hasMatchNone := tmp["match_none"]
  220. if hasMatchNone {
  221. var rv MatchNoneQuery
  222. err := json.Unmarshal(input, &rv)
  223. if err != nil {
  224. return nil, err
  225. }
  226. return &rv, nil
  227. }
  228. _, hasDocIds := tmp["ids"]
  229. if hasDocIds {
  230. var rv DocIDQuery
  231. err := json.Unmarshal(input, &rv)
  232. if err != nil {
  233. return nil, err
  234. }
  235. return &rv, nil
  236. }
  237. _, hasBool := tmp["bool"]
  238. if hasBool {
  239. var rv BoolFieldQuery
  240. err := json.Unmarshal(input, &rv)
  241. if err != nil {
  242. return nil, err
  243. }
  244. return &rv, nil
  245. }
  246. _, hasTopLeft := tmp["top_left"]
  247. _, hasBottomRight := tmp["bottom_right"]
  248. if hasTopLeft && hasBottomRight {
  249. var rv GeoBoundingBoxQuery
  250. err := json.Unmarshal(input, &rv)
  251. if err != nil {
  252. return nil, err
  253. }
  254. return &rv, nil
  255. }
  256. _, hasDistance := tmp["distance"]
  257. if hasDistance {
  258. var rv GeoDistanceQuery
  259. err := json.Unmarshal(input, &rv)
  260. if err != nil {
  261. return nil, err
  262. }
  263. return &rv, nil
  264. }
  265. return nil, fmt.Errorf("unknown query type")
  266. }
  267. // expandQuery traverses the input query tree and returns a new tree where
  268. // query string queries have been expanded into base queries. Returned tree may
  269. // reference queries from the input tree or new queries.
  270. func expandQuery(m mapping.IndexMapping, query Query) (Query, error) {
  271. var expand func(query Query) (Query, error)
  272. var expandSlice func(queries []Query) ([]Query, error)
  273. expandSlice = func(queries []Query) ([]Query, error) {
  274. expanded := []Query{}
  275. for _, q := range queries {
  276. exp, err := expand(q)
  277. if err != nil {
  278. return nil, err
  279. }
  280. expanded = append(expanded, exp)
  281. }
  282. return expanded, nil
  283. }
  284. expand = func(query Query) (Query, error) {
  285. switch query.(type) {
  286. case *QueryStringQuery:
  287. q := query.(*QueryStringQuery)
  288. parsed, err := parseQuerySyntax(q.Query)
  289. if err != nil {
  290. return nil, fmt.Errorf("could not parse '%s': %s", q.Query, err)
  291. }
  292. return expand(parsed)
  293. case *ConjunctionQuery:
  294. q := *query.(*ConjunctionQuery)
  295. children, err := expandSlice(q.Conjuncts)
  296. if err != nil {
  297. return nil, err
  298. }
  299. q.Conjuncts = children
  300. return &q, nil
  301. case *DisjunctionQuery:
  302. q := *query.(*DisjunctionQuery)
  303. children, err := expandSlice(q.Disjuncts)
  304. if err != nil {
  305. return nil, err
  306. }
  307. q.Disjuncts = children
  308. return &q, nil
  309. case *BooleanQuery:
  310. q := *query.(*BooleanQuery)
  311. var err error
  312. q.Must, err = expand(q.Must)
  313. if err != nil {
  314. return nil, err
  315. }
  316. q.Should, err = expand(q.Should)
  317. if err != nil {
  318. return nil, err
  319. }
  320. q.MustNot, err = expand(q.MustNot)
  321. if err != nil {
  322. return nil, err
  323. }
  324. return &q, nil
  325. default:
  326. return query, nil
  327. }
  328. }
  329. return expand(query)
  330. }
  331. // DumpQuery returns a string representation of the query tree, where query
  332. // string queries have been expanded into base queries. The output format is
  333. // meant for debugging purpose and may change in the future.
  334. func DumpQuery(m mapping.IndexMapping, query Query) (string, error) {
  335. q, err := expandQuery(m, query)
  336. if err != nil {
  337. return "", err
  338. }
  339. data, err := json.MarshalIndent(q, "", " ")
  340. return string(data), err
  341. }