chewy 0.8.4 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (303) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +56 -0
  4. data/.rubocop_todo.yml +44 -0
  5. data/.travis.yml +36 -67
  6. data/.yardopts +5 -0
  7. data/Appraisals +63 -58
  8. data/CHANGELOG.md +168 -11
  9. data/Gemfile +16 -9
  10. data/Guardfile +5 -5
  11. data/LEGACY_DSL.md +497 -0
  12. data/README.md +403 -470
  13. data/Rakefile +11 -1
  14. data/chewy.gemspec +12 -15
  15. data/gemfiles/rails.4.0.activerecord.gemfile +9 -9
  16. data/gemfiles/rails.4.1.activerecord.gemfile +9 -9
  17. data/gemfiles/rails.4.2.activerecord.gemfile +8 -8
  18. data/gemfiles/rails.4.2.mongoid.5.2.gemfile +16 -0
  19. data/gemfiles/rails.5.0.activerecord.gemfile +16 -0
  20. data/gemfiles/rails.5.0.mongoid.6.1.gemfile +16 -0
  21. data/gemfiles/rails.5.1.activerecord.gemfile +16 -0
  22. data/gemfiles/rails.5.1.mongoid.6.3.gemfile +16 -0
  23. data/gemfiles/rails.5.2.activerecord.gemfile +16 -0
  24. data/gemfiles/sequel.4.45.gemfile +11 -0
  25. data/lib/chewy/backports/deep_dup.rb +1 -1
  26. data/lib/chewy/backports/duplicable.rb +1 -0
  27. data/lib/chewy/config.rb +53 -21
  28. data/lib/chewy/errors.rb +6 -6
  29. data/lib/chewy/fields/base.rb +59 -29
  30. data/lib/chewy/fields/root.rb +49 -14
  31. data/lib/chewy/index/actions.rb +95 -36
  32. data/lib/chewy/index/aliases.rb +2 -1
  33. data/lib/chewy/index/settings.rb +10 -5
  34. data/lib/chewy/index/specification.rb +60 -0
  35. data/lib/chewy/index.rb +239 -138
  36. data/lib/chewy/journal.rb +55 -0
  37. data/lib/chewy/log_subscriber.rb +8 -8
  38. data/lib/chewy/minitest/helpers.rb +77 -0
  39. data/lib/chewy/minitest/search_index_receiver.rb +80 -0
  40. data/lib/chewy/minitest.rb +1 -0
  41. data/lib/chewy/query/compose.rb +18 -19
  42. data/lib/chewy/query/criteria.rb +34 -24
  43. data/lib/chewy/query/filters.rb +28 -11
  44. data/lib/chewy/query/loading.rb +3 -4
  45. data/lib/chewy/query/nodes/and.rb +1 -1
  46. data/lib/chewy/query/nodes/base.rb +1 -1
  47. data/lib/chewy/query/nodes/bool.rb +6 -4
  48. data/lib/chewy/query/nodes/equal.rb +4 -4
  49. data/lib/chewy/query/nodes/exists.rb +1 -1
  50. data/lib/chewy/query/nodes/expr.rb +2 -2
  51. data/lib/chewy/query/nodes/field.rb +35 -31
  52. data/lib/chewy/query/nodes/has_child.rb +1 -0
  53. data/lib/chewy/query/nodes/has_parent.rb +1 -0
  54. data/lib/chewy/query/nodes/has_relation.rb +10 -12
  55. data/lib/chewy/query/nodes/missing.rb +1 -1
  56. data/lib/chewy/query/nodes/not.rb +1 -1
  57. data/lib/chewy/query/nodes/or.rb +1 -1
  58. data/lib/chewy/query/nodes/prefix.rb +3 -2
  59. data/lib/chewy/query/nodes/query.rb +1 -1
  60. data/lib/chewy/query/nodes/range.rb +9 -9
  61. data/lib/chewy/query/nodes/raw.rb +1 -1
  62. data/lib/chewy/query/nodes/regexp.rb +13 -9
  63. data/lib/chewy/query/nodes/script.rb +4 -4
  64. data/lib/chewy/query/pagination.rb +10 -1
  65. data/lib/chewy/query.rb +286 -170
  66. data/lib/chewy/railtie.rb +7 -6
  67. data/lib/chewy/rake_helper.rb +275 -37
  68. data/lib/chewy/repository.rb +2 -2
  69. data/lib/chewy/rspec/update_index.rb +70 -65
  70. data/lib/chewy/rspec.rb +1 -1
  71. data/lib/chewy/runtime/version.rb +4 -4
  72. data/lib/chewy/search/loader.rb +83 -0
  73. data/lib/chewy/{query → search}/pagination/kaminari.rb +13 -5
  74. data/lib/chewy/search/pagination/will_paginate.rb +43 -0
  75. data/lib/chewy/search/parameters/aggs.rb +16 -0
  76. data/lib/chewy/search/parameters/allow_partial_search_results.rb +27 -0
  77. data/lib/chewy/search/parameters/concerns/bool_storage.rb +24 -0
  78. data/lib/chewy/search/parameters/concerns/hash_storage.rb +23 -0
  79. data/lib/chewy/search/parameters/concerns/integer_storage.rb +14 -0
  80. data/lib/chewy/search/parameters/concerns/query_storage.rb +238 -0
  81. data/lib/chewy/search/parameters/concerns/string_array_storage.rb +23 -0
  82. data/lib/chewy/search/parameters/concerns/string_storage.rb +14 -0
  83. data/lib/chewy/search/parameters/docvalue_fields.rb +12 -0
  84. data/lib/chewy/search/parameters/explain.rb +16 -0
  85. data/lib/chewy/search/parameters/filter.rb +47 -0
  86. data/lib/chewy/search/parameters/highlight.rb +16 -0
  87. data/lib/chewy/search/parameters/indices.rb +123 -0
  88. data/lib/chewy/search/parameters/indices_boost.rb +52 -0
  89. data/lib/chewy/search/parameters/limit.rb +17 -0
  90. data/lib/chewy/search/parameters/load.rb +32 -0
  91. data/lib/chewy/search/parameters/min_score.rb +16 -0
  92. data/lib/chewy/search/parameters/none.rb +27 -0
  93. data/lib/chewy/search/parameters/offset.rb +17 -0
  94. data/lib/chewy/search/parameters/order.rb +64 -0
  95. data/lib/chewy/search/parameters/post_filter.rb +19 -0
  96. data/lib/chewy/search/parameters/preference.rb +16 -0
  97. data/lib/chewy/search/parameters/profile.rb +16 -0
  98. data/lib/chewy/search/parameters/query.rb +19 -0
  99. data/lib/chewy/search/parameters/request_cache.rb +27 -0
  100. data/lib/chewy/search/parameters/rescore.rb +29 -0
  101. data/lib/chewy/search/parameters/script_fields.rb +16 -0
  102. data/lib/chewy/search/parameters/search_after.rb +20 -0
  103. data/lib/chewy/search/parameters/search_type.rb +16 -0
  104. data/lib/chewy/search/parameters/source.rb +73 -0
  105. data/lib/chewy/search/parameters/storage.rb +95 -0
  106. data/lib/chewy/search/parameters/stored_fields.rb +63 -0
  107. data/lib/chewy/search/parameters/suggest.rb +16 -0
  108. data/lib/chewy/search/parameters/terminate_after.rb +16 -0
  109. data/lib/chewy/search/parameters/timeout.rb +16 -0
  110. data/lib/chewy/search/parameters/track_scores.rb +16 -0
  111. data/lib/chewy/search/parameters/types.rb +20 -0
  112. data/lib/chewy/search/parameters/version.rb +16 -0
  113. data/lib/chewy/search/parameters.rb +167 -0
  114. data/lib/chewy/search/query_proxy.rb +257 -0
  115. data/lib/chewy/search/request.rb +1045 -0
  116. data/lib/chewy/search/response.rb +119 -0
  117. data/lib/chewy/search/scoping.rb +50 -0
  118. data/lib/chewy/search/scrolling.rb +134 -0
  119. data/lib/chewy/search.rb +81 -26
  120. data/lib/chewy/stash.rb +79 -0
  121. data/lib/chewy/strategy/active_job.rb +1 -0
  122. data/lib/chewy/strategy/atomic.rb +2 -4
  123. data/lib/chewy/strategy/base.rb +4 -4
  124. data/lib/chewy/strategy/bypass.rb +1 -2
  125. data/lib/chewy/strategy/resque.rb +1 -0
  126. data/lib/chewy/strategy/shoryuken.rb +40 -0
  127. data/lib/chewy/strategy/sidekiq.rb +13 -1
  128. data/lib/chewy/strategy/urgent.rb +1 -1
  129. data/lib/chewy/strategy.rb +19 -10
  130. data/lib/chewy/type/actions.rb +26 -2
  131. data/lib/chewy/type/adapter/active_record.rb +50 -24
  132. data/lib/chewy/type/adapter/base.rb +29 -9
  133. data/lib/chewy/type/adapter/mongoid.rb +19 -10
  134. data/lib/chewy/type/adapter/object.rb +195 -31
  135. data/lib/chewy/type/adapter/orm.rb +69 -33
  136. data/lib/chewy/type/adapter/sequel.rb +37 -19
  137. data/lib/chewy/type/crutch.rb +5 -4
  138. data/lib/chewy/type/import/bulk_builder.rb +122 -0
  139. data/lib/chewy/type/import/bulk_request.rb +78 -0
  140. data/lib/chewy/type/import/journal_builder.rb +45 -0
  141. data/lib/chewy/type/import/routine.rb +138 -0
  142. data/lib/chewy/type/import.rb +150 -176
  143. data/lib/chewy/type/mapping.rb +58 -42
  144. data/lib/chewy/type/observe.rb +21 -15
  145. data/lib/chewy/type/syncer.rb +222 -0
  146. data/lib/chewy/type/witchcraft.rb +89 -34
  147. data/lib/chewy/type/wrapper.rb +48 -16
  148. data/lib/chewy/type.rb +77 -49
  149. data/lib/chewy/version.rb +1 -1
  150. data/lib/chewy.rb +95 -52
  151. data/lib/generators/chewy/install_generator.rb +3 -3
  152. data/lib/sequel/plugins/chewy_observe.rb +4 -19
  153. data/lib/tasks/chewy.rake +91 -28
  154. data/spec/chewy/config_spec.rb +130 -12
  155. data/spec/chewy/fields/base_spec.rb +194 -172
  156. data/spec/chewy/fields/root_spec.rb +123 -17
  157. data/spec/chewy/fields/time_fields_spec.rb +10 -9
  158. data/spec/chewy/index/actions_spec.rb +228 -43
  159. data/spec/chewy/index/aliases_spec.rb +2 -2
  160. data/spec/chewy/index/settings_spec.rb +100 -49
  161. data/spec/chewy/index/specification_spec.rb +169 -0
  162. data/spec/chewy/index_spec.rb +159 -63
  163. data/spec/chewy/journal_spec.rb +268 -0
  164. data/spec/chewy/minitest/helpers_spec.rb +90 -0
  165. data/spec/chewy/minitest/search_index_receiver_spec.rb +120 -0
  166. data/spec/chewy/query/criteria_spec.rb +503 -236
  167. data/spec/chewy/query/filters_spec.rb +96 -68
  168. data/spec/chewy/query/loading_spec.rb +80 -42
  169. data/spec/chewy/query/nodes/and_spec.rb +3 -7
  170. data/spec/chewy/query/nodes/bool_spec.rb +5 -13
  171. data/spec/chewy/query/nodes/equal_spec.rb +20 -20
  172. data/spec/chewy/query/nodes/exists_spec.rb +7 -7
  173. data/spec/chewy/query/nodes/has_child_spec.rb +42 -23
  174. data/spec/chewy/query/nodes/has_parent_spec.rb +42 -23
  175. data/spec/chewy/query/nodes/match_all_spec.rb +2 -2
  176. data/spec/chewy/query/nodes/missing_spec.rb +6 -5
  177. data/spec/chewy/query/nodes/not_spec.rb +5 -7
  178. data/spec/chewy/query/nodes/or_spec.rb +3 -7
  179. data/spec/chewy/query/nodes/prefix_spec.rb +6 -6
  180. data/spec/chewy/query/nodes/query_spec.rb +3 -3
  181. data/spec/chewy/query/nodes/range_spec.rb +19 -19
  182. data/spec/chewy/query/nodes/raw_spec.rb +2 -2
  183. data/spec/chewy/query/nodes/regexp_spec.rb +31 -19
  184. data/spec/chewy/query/nodes/script_spec.rb +5 -5
  185. data/spec/chewy/query/pagination/kaminari_spec.rb +3 -55
  186. data/spec/chewy/query/pagination/will_paginate_spec.rb +5 -0
  187. data/spec/chewy/query/pagination_spec.rb +25 -22
  188. data/spec/chewy/query_spec.rb +510 -505
  189. data/spec/chewy/rake_helper_spec.rb +381 -0
  190. data/spec/chewy/repository_spec.rb +8 -8
  191. data/spec/chewy/rspec/update_index_spec.rb +215 -113
  192. data/spec/chewy/runtime_spec.rb +2 -2
  193. data/spec/chewy/search/loader_spec.rb +117 -0
  194. data/spec/chewy/search/pagination/kaminari_examples.rb +71 -0
  195. data/spec/chewy/search/pagination/kaminari_spec.rb +21 -0
  196. data/spec/chewy/search/pagination/will_paginate_examples.rb +63 -0
  197. data/spec/chewy/search/pagination/will_paginate_spec.rb +23 -0
  198. data/spec/chewy/search/parameters/aggs_spec.rb +5 -0
  199. data/spec/chewy/search/parameters/bool_storage_examples.rb +53 -0
  200. data/spec/chewy/search/parameters/docvalue_fields_spec.rb +5 -0
  201. data/spec/chewy/search/parameters/explain_spec.rb +5 -0
  202. data/spec/chewy/search/parameters/filter_spec.rb +5 -0
  203. data/spec/chewy/search/parameters/hash_storage_examples.rb +59 -0
  204. data/spec/chewy/search/parameters/highlight_spec.rb +5 -0
  205. data/spec/chewy/search/parameters/indices_spec.rb +191 -0
  206. data/spec/chewy/search/parameters/integer_storage_examples.rb +32 -0
  207. data/spec/chewy/search/parameters/limit_spec.rb +5 -0
  208. data/spec/chewy/search/parameters/load_spec.rb +60 -0
  209. data/spec/chewy/search/parameters/min_score_spec.rb +32 -0
  210. data/spec/chewy/search/parameters/none_spec.rb +5 -0
  211. data/spec/chewy/search/parameters/offset_spec.rb +5 -0
  212. data/spec/chewy/search/parameters/order_spec.rb +65 -0
  213. data/spec/chewy/search/parameters/post_filter_spec.rb +5 -0
  214. data/spec/chewy/search/parameters/preference_spec.rb +5 -0
  215. data/spec/chewy/search/parameters/profile_spec.rb +5 -0
  216. data/spec/chewy/search/parameters/query_spec.rb +5 -0
  217. data/spec/chewy/search/parameters/query_storage_examples.rb +388 -0
  218. data/spec/chewy/search/parameters/request_cache_spec.rb +67 -0
  219. data/spec/chewy/search/parameters/rescore_spec.rb +62 -0
  220. data/spec/chewy/search/parameters/script_fields_spec.rb +5 -0
  221. data/spec/chewy/search/parameters/search_after_spec.rb +32 -0
  222. data/spec/chewy/search/parameters/search_type_spec.rb +5 -0
  223. data/spec/chewy/search/parameters/source_spec.rb +156 -0
  224. data/spec/chewy/search/parameters/storage_spec.rb +60 -0
  225. data/spec/chewy/search/parameters/stored_fields_spec.rb +126 -0
  226. data/spec/chewy/search/parameters/string_array_storage_examples.rb +63 -0
  227. data/spec/chewy/search/parameters/string_storage_examples.rb +32 -0
  228. data/spec/chewy/search/parameters/suggest_spec.rb +5 -0
  229. data/spec/chewy/search/parameters/terminate_after_spec.rb +5 -0
  230. data/spec/chewy/search/parameters/timeout_spec.rb +5 -0
  231. data/spec/chewy/search/parameters/track_scores_spec.rb +5 -0
  232. data/spec/chewy/search/parameters/types_spec.rb +5 -0
  233. data/spec/chewy/search/parameters/version_spec.rb +5 -0
  234. data/spec/chewy/search/parameters_spec.rb +145 -0
  235. data/spec/chewy/search/query_proxy_spec.rb +68 -0
  236. data/spec/chewy/search/request_spec.rb +685 -0
  237. data/spec/chewy/search/response_spec.rb +192 -0
  238. data/spec/chewy/search/scrolling_spec.rb +169 -0
  239. data/spec/chewy/search_spec.rb +37 -20
  240. data/spec/chewy/stash_spec.rb +95 -0
  241. data/spec/chewy/strategy/active_job_spec.rb +8 -2
  242. data/spec/chewy/strategy/atomic_spec.rb +4 -1
  243. data/spec/chewy/strategy/resque_spec.rb +8 -2
  244. data/spec/chewy/strategy/shoryuken_spec.rb +66 -0
  245. data/spec/chewy/strategy/sidekiq_spec.rb +10 -2
  246. data/spec/chewy/strategy_spec.rb +6 -6
  247. data/spec/chewy/type/actions_spec.rb +29 -10
  248. data/spec/chewy/type/adapter/active_record_spec.rb +357 -139
  249. data/spec/chewy/type/adapter/mongoid_spec.rb +220 -101
  250. data/spec/chewy/type/adapter/object_spec.rb +129 -40
  251. data/spec/chewy/type/adapter/sequel_spec.rb +304 -152
  252. data/spec/chewy/type/import/bulk_builder_spec.rb +279 -0
  253. data/spec/chewy/type/import/bulk_request_spec.rb +102 -0
  254. data/spec/chewy/type/import/journal_builder_spec.rb +95 -0
  255. data/spec/chewy/type/import/routine_spec.rb +110 -0
  256. data/spec/chewy/type/import_spec.rb +360 -244
  257. data/spec/chewy/type/mapping_spec.rb +96 -29
  258. data/spec/chewy/type/observe_spec.rb +25 -15
  259. data/spec/chewy/type/syncer_spec.rb +123 -0
  260. data/spec/chewy/type/witchcraft_spec.rb +122 -44
  261. data/spec/chewy/type/wrapper_spec.rb +63 -23
  262. data/spec/chewy/type_spec.rb +32 -10
  263. data/spec/chewy_spec.rb +82 -12
  264. data/spec/spec_helper.rb +16 -2
  265. data/spec/support/active_record.rb +6 -2
  266. data/spec/support/class_helpers.rb +4 -19
  267. data/spec/support/mongoid.rb +17 -5
  268. data/spec/support/sequel.rb +6 -1
  269. metadata +250 -57
  270. data/gemfiles/rails.3.2.activerecord.gemfile +0 -15
  271. data/gemfiles/rails.3.2.activerecord.kaminari.gemfile +0 -14
  272. data/gemfiles/rails.3.2.activerecord.will_paginate.gemfile +0 -14
  273. data/gemfiles/rails.4.0.activerecord.kaminari.gemfile +0 -14
  274. data/gemfiles/rails.4.0.activerecord.will_paginate.gemfile +0 -14
  275. data/gemfiles/rails.4.0.mongoid.4.0.0.gemfile +0 -15
  276. data/gemfiles/rails.4.0.mongoid.4.0.0.kaminari.gemfile +0 -14
  277. data/gemfiles/rails.4.0.mongoid.4.0.0.will_paginate.gemfile +0 -14
  278. data/gemfiles/rails.4.0.mongoid.5.1.0.gemfile +0 -15
  279. data/gemfiles/rails.4.0.mongoid.5.1.0.kaminari.gemfile +0 -14
  280. data/gemfiles/rails.4.0.mongoid.5.1.0.will_paginate.gemfile +0 -14
  281. data/gemfiles/rails.4.1.activerecord.kaminari.gemfile +0 -14
  282. data/gemfiles/rails.4.1.activerecord.will_paginate.gemfile +0 -14
  283. data/gemfiles/rails.4.1.mongoid.4.0.0.gemfile +0 -15
  284. data/gemfiles/rails.4.1.mongoid.4.0.0.kaminari.gemfile +0 -14
  285. data/gemfiles/rails.4.1.mongoid.4.0.0.will_paginate.gemfile +0 -14
  286. data/gemfiles/rails.4.1.mongoid.5.1.0.gemfile +0 -15
  287. data/gemfiles/rails.4.1.mongoid.5.1.0.kaminari.gemfile +0 -14
  288. data/gemfiles/rails.4.1.mongoid.5.1.0.will_paginate.gemfile +0 -14
  289. data/gemfiles/rails.4.2.activerecord.kaminari.gemfile +0 -15
  290. data/gemfiles/rails.4.2.activerecord.will_paginate.gemfile +0 -15
  291. data/gemfiles/rails.4.2.mongoid.4.0.0.gemfile +0 -15
  292. data/gemfiles/rails.4.2.mongoid.4.0.0.kaminari.gemfile +0 -14
  293. data/gemfiles/rails.4.2.mongoid.4.0.0.will_paginate.gemfile +0 -14
  294. data/gemfiles/rails.4.2.mongoid.5.1.0.gemfile +0 -15
  295. data/gemfiles/rails.4.2.mongoid.5.1.0.kaminari.gemfile +0 -14
  296. data/gemfiles/rails.4.2.mongoid.5.1.0.will_paginate.gemfile +0 -14
  297. data/gemfiles/rails.5.0.0.beta3.activerecord.gemfile +0 -16
  298. data/gemfiles/rails.5.0.0.beta3.activerecord.kaminari.gemfile +0 -16
  299. data/gemfiles/rails.5.0.0.beta3.activerecord.will_paginate.gemfile +0 -15
  300. data/gemfiles/sequel.4.31.gemfile +0 -13
  301. data/lib/chewy/query/pagination/will_paginate.rb +0 -27
  302. data/lib/chewy/query/scoping.rb +0 -20
  303. data/spec/chewy/query/pagination/will_paginage_spec.rb +0 -60
data/lib/chewy/query.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'chewy/query/criteria'
2
2
  require 'chewy/query/filters'
3
- require 'chewy/query/scoping'
4
3
  require 'chewy/query/loading'
5
4
  require 'chewy/query/pagination'
6
5
 
@@ -9,21 +8,31 @@ module Chewy
9
8
  # chainable DSL. Queries are lazy evaluated and might be merged.
10
9
  # The same DSL is used for whole index or individual types query build.
11
10
  #
11
+ # @example
12
12
  # UsersIndex.filter{ age < 42 }.query(text: {name: 'Alex'}).limit(20)
13
13
  # UsersIndex::User.filter{ age < 42 }.query(text: {name: 'Alex'}).limit(20)
14
14
  #
15
15
  class Query
16
16
  include Enumerable
17
- include Scoping
18
17
  include Loading
19
18
  include Pagination
19
+ include Chewy::Search::Scoping
20
+
21
+ DELEGATED_METHODS = %i[
22
+ explain query_mode filter_mode post_filter_mode
23
+ timeout limit offset highlight min_score rescore facets script_score
24
+ boost_factor weight random_score field_value_factor decay aggregations
25
+ suggest none strategy query filter post_filter boost_mode
26
+ score_mode order reorder only types delete_all find total
27
+ total_count total_entries unlimited script_fields track_scores preference
28
+ ].to_set.freeze
20
29
 
21
30
  delegate :each, :count, :size, to: :_collection
22
31
  alias_method :to_ary, :to_a
23
32
 
24
33
  attr_reader :_indexes, :_types, :options, :criteria
25
34
 
26
- def initialize *indexes_or_types_and_options
35
+ def initialize(*indexes_or_types_and_options)
27
36
  @options = indexes_or_types_and_options.extract_options!
28
37
  @_types = indexes_or_types_and_options.select { |klass| klass < Chewy::Type }
29
38
  @_indexes = indexes_or_types_and_options.select { |klass| klass < Chewy::Index }
@@ -31,39 +40,45 @@ module Chewy
31
40
  @criteria = Criteria.new
32
41
  end
33
42
 
43
+ # A compatibility layer with the new request DSL.
44
+ def render
45
+ _request
46
+ end
47
+
34
48
  # Comparation with other query or collection
35
49
  # If other is collection - search request is executed and
36
50
  # result is used for comparation
37
51
  #
52
+ # @example
38
53
  # UsersIndex.filter(term: {name: 'Johny'}) == UsersIndex.filter(term: {name: 'Johny'}) # => true
39
54
  # UsersIndex.filter(term: {name: 'Johny'}) == UsersIndex.filter(term: {name: 'Johny'}).to_a # => true
40
55
  # UsersIndex.filter(term: {name: 'Johny'}) == UsersIndex.filter(term: {name: 'Winnie'}) # => false
41
56
  #
42
- def == other
43
- super || if other.is_a?(self.class)
44
- other.criteria == criteria
45
- else
46
- to_a == other
47
- end
57
+ def ==(other)
58
+ super || other.is_a?(self.class) ? other.criteria == criteria : other == to_a
48
59
  end
49
60
 
50
- # Adds <tt>explain</tt> parameter to search request.
61
+ # Adds `explain` parameter to search request.
51
62
  #
63
+ # @example
52
64
  # UsersIndex.filter(term: {name: 'Johny'}).explain
53
65
  # UsersIndex.filter(term: {name: 'Johny'}).explain(true)
54
66
  # UsersIndex.filter(term: {name: 'Johny'}).explain(false)
55
67
  #
56
68
  # Calling explain without any arguments sets explanation flag to true.
57
- # With <tt>explain: true</tt>, every result object has <tt>_explanation</tt>
69
+ # With `explain: true`, every result object has `_explanation`
58
70
  # method
59
71
  #
72
+ # @example
60
73
  # UsersIndex::User.filter(term: {name: 'Johny'}).explain.first._explanation # => {...}
61
74
  #
62
- def explain value = nil
75
+ def explain(value = nil)
63
76
  chain { criteria.update_request_options explain: (value.nil? ? true : value) }
64
77
  end
65
78
 
66
- # Adds <tt>script_fields</tt> parameter to search request.
79
+ # Adds `script_fields` parameter to search request.
80
+ #
81
+ # @example
67
82
  # UsersIndex.script_fields(
68
83
  # distance: {
69
84
  # params: {
@@ -73,7 +88,7 @@ module Chewy
73
88
  # script: "doc['coordinates'].distanceInMiles(lat, lon)"
74
89
  # }
75
90
  # )
76
- def script_fields value
91
+ def script_fields(value)
77
92
  chain { criteria.update_script_fields(value) }
78
93
  end
79
94
 
@@ -81,31 +96,28 @@ module Chewy
81
96
  # Not used if only one filter for search is specified.
82
97
  # Possible values:
83
98
  #
84
- # * <tt>:must</tt>
85
- # Default value. Query compiles into a bool <tt>must</tt> query.
86
- #
87
- # Ex:
99
+ # * `:must`
100
+ # Default value. Query compiles into a bool `must` query.
88
101
  #
102
+ # @example
89
103
  # UsersIndex.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}})
90
104
  # # => {body: {
91
105
  # query: {bool: {must: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
92
106
  # }}
93
107
  #
94
- # * <tt>:should</tt>
95
- # Query compiles into a bool <tt>should</tt> query.
96
- #
97
- # Ex:
108
+ # * `:should`
109
+ # Query compiles into a bool `should` query.
98
110
  #
111
+ # @example
99
112
  # UsersIndex.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(:should)
100
113
  # # => {body: {
101
114
  # query: {bool: {should: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
102
115
  # }}
103
116
  #
104
- # * Any acceptable <tt>minimum_should_match</tt> value (1, '2', '75%')
105
- # Query compiles into a bool <tt>should</tt> query with <tt>minimum_should_match</tt> set.
106
- #
107
- # Ex:
117
+ # * Any acceptable `minimum_should_match` value (1, '2', '75%')
118
+ # Query compiles into a bool `should` query with `minimum_should_match` set.
108
119
  #
120
+ # @example
109
121
  # UsersIndex.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode('50%')
110
122
  # # => {body: {
111
123
  # query: {bool: {
@@ -114,21 +126,19 @@ module Chewy
114
126
  # }}
115
127
  # }}
116
128
  #
117
- # * <tt>:dis_max</tt>
118
- # Query compiles into a <tt>dis_max</tt> query.
119
- #
120
- # Ex:
129
+ # * `:dis_max`
130
+ # Query compiles into a `dis_max` query.
121
131
  #
132
+ # @example
122
133
  # UsersIndex.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(:dis_max)
123
134
  # # => {body: {
124
135
  # query: {dis_max: {queries: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
125
136
  # }}
126
137
  #
127
138
  # * Any Float value (0.0, 0.7, 1.0)
128
- # Query compiles into a <tt>dis_max</tt> query with <tt>tie_breaker</tt> option set.
129
- #
130
- # Ex:
139
+ # Query compiles into a `dis_max` query with `tie_breaker` option set.
131
140
  #
141
+ # @example
132
142
  # UsersIndex.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(0.7)
133
143
  # # => {body: {
134
144
  # query: {dis_max: {
@@ -137,13 +147,14 @@ module Chewy
137
147
  # }}
138
148
  # }}
139
149
  #
140
- # Default value for <tt>:query_mode</tt> might be changed
141
- # with <tt>Chewy.query_mode</tt> config option.
150
+ # Default value for `:query_mode` might be changed
151
+ # with `Chewy.query_mode` config option.
142
152
  #
153
+ # @example
143
154
  # Chewy.query_mode = :dis_max
144
155
  # Chewy.query_mode = '50%'
145
156
  #
146
- def query_mode value
157
+ def query_mode(value)
147
158
  chain { criteria.update_options query_mode: value }
148
159
  end
149
160
 
@@ -151,55 +162,50 @@ module Chewy
151
162
  # Not used if only one filter for search is specified.
152
163
  # Possible values:
153
164
  #
154
- # * <tt>:and</tt>
155
- # Default value. Filter compiles into an <tt>and</tt> filter.
156
- #
157
- # Ex:
165
+ # * `:and`
166
+ # Default value. Filter compiles into an `and` filter.
158
167
  #
168
+ # @example
159
169
  # UsersIndex.filter{ name == 'Johny' }.filter{ age <= 42 }
160
170
  # # => {body: {query: {filtered: {
161
171
  # query: {...},
162
172
  # filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}
163
173
  # }}}}
164
174
  #
165
- # * <tt>:or</tt>
166
- # Filter compiles into an <tt>or</tt> filter.
167
- #
168
- # Ex:
175
+ # * `:or`
176
+ # Filter compiles into an `or` filter.
169
177
  #
178
+ # @example
170
179
  # UsersIndex.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:or)
171
180
  # # => {body: {query: {filtered: {
172
181
  # query: {...},
173
182
  # filter: {or: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}
174
183
  # }}}}
175
184
  #
176
- # * <tt>:must</tt>
177
- # Filter compiles into a bool <tt>must</tt> filter.
178
- #
179
- # Ex:
185
+ # * `:must`
186
+ # Filter compiles into a bool `must` filter.
180
187
  #
188
+ # @example
181
189
  # UsersIndex.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:must)
182
190
  # # => {body: {query: {filtered: {
183
191
  # query: {...},
184
192
  # filter: {bool: {must: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
185
193
  # }}}}
186
194
  #
187
- # * <tt>:should</tt>
188
- # Filter compiles into a bool <tt>should</tt> filter.
189
- #
190
- # Ex:
195
+ # * `:should`
196
+ # Filter compiles into a bool `should` filter.
191
197
  #
198
+ # @example
192
199
  # UsersIndex.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:should)
193
200
  # # => {body: {query: {filtered: {
194
201
  # query: {...},
195
202
  # filter: {bool: {should: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
196
203
  # }}}}
197
204
  #
198
- # * Any acceptable <tt>minimum_should_match</tt> value (1, '2', '75%')
199
- # Filter compiles into bool <tt>should</tt> filter with <tt>minimum_should_match</tt> set.
200
- #
201
- # Ex:
205
+ # * Any acceptable `minimum_should_match` value (1, '2', '75%')
206
+ # Filter compiles into bool `should` filter with `minimum_should_match` set.
202
207
  #
208
+ # @example
203
209
  # UsersIndex.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode('50%')
204
210
  # # => {body: {query: {filtered: {
205
211
  # query: {...},
@@ -209,13 +215,14 @@ module Chewy
209
215
  # }}
210
216
  # }}}}
211
217
  #
212
- # Default value for <tt>:filter_mode</tt> might be changed
213
- # with <tt>Chewy.filter_mode</tt> config option.
218
+ # Default value for `:filter_mode` might be changed
219
+ # with `Chewy.filter_mode` config option.
214
220
  #
221
+ # @example
215
222
  # Chewy.filter_mode = :should
216
223
  # Chewy.filter_mode = '50%'
217
224
  #
218
- def filter_mode value
225
+ def filter_mode(value)
219
226
  chain { criteria.update_options filter_mode: value }
220
227
  end
221
228
 
@@ -223,11 +230,12 @@ module Chewy
223
230
  # Note that it fallbacks by default to `Chewy.filter_mode` if
224
231
  # `Chewy.post_filter_mode` is nil.
225
232
  #
233
+ # @example
226
234
  # UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:and)
227
235
  # UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:should)
228
236
  # UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode('50%')
229
237
  #
230
- def post_filter_mode value
238
+ def post_filter_mode(value)
231
239
  chain { criteria.update_options post_filter_mode: value }
232
240
  end
233
241
 
@@ -246,6 +254,7 @@ module Chewy
246
254
  # The response to a search request will indicate whether the search timed
247
255
  # out and how many shards responded successfully:
248
256
  #
257
+ # @example
249
258
  # ...
250
259
  # "timed_out": true,
251
260
  # "_shards": {
@@ -263,6 +272,7 @@ module Chewy
263
272
  # responding with an error. The timeout parameter can be used to explicitly
264
273
  # specify how long it waits.
265
274
  #
275
+ # @example
266
276
  # UsersIndex.timeout("5000ms")
267
277
  #
268
278
  # Timeout is not a circuit breaker.
@@ -276,63 +286,78 @@ module Chewy
276
286
  # Use the timeout because it is important to your SLA, not because you want
277
287
  # to abort the execution of long running queries.
278
288
  #
279
- def timeout value
289
+ def timeout(value)
280
290
  chain { criteria.update_request_options timeout: value }
281
291
  end
282
292
 
283
- # Sets elasticsearch <tt>size</tt> search request param
293
+ # Sets elasticsearch `size` search request param
284
294
  # Default value is set in the elasticsearch and is 10.
285
295
  #
296
+ # @example
286
297
  # UsersIndex.filter{ name == 'Johny' }.limit(100)
287
298
  # # => {body: {
288
299
  # query: {...},
289
300
  # size: 100
290
301
  # }}
291
302
  #
292
- def limit value
293
- chain { criteria.update_request_options size: Integer(value) }
303
+ def limit(value = nil, &block)
304
+ chain { criteria.update_request_options size: block || Integer(value) }
294
305
  end
295
306
 
296
- # Sets elasticsearch <tt>from</tt> search request param
307
+ # Sets elasticsearch `from` search request param
297
308
  #
309
+ # @example
298
310
  # UsersIndex.filter{ name == 'Johny' }.offset(300)
299
311
  # # => {body: {
300
312
  # query: {...},
301
313
  # from: 300
302
314
  # }}
303
315
  #
304
- def offset value
305
- chain { criteria.update_request_options from: Integer(value) }
316
+ def offset(value = nil, &block)
317
+ chain { criteria.update_request_options from: block || Integer(value) }
306
318
  end
307
319
 
308
320
  # Elasticsearch highlight query option support
309
321
  #
322
+ # @example
310
323
  # UsersIndex.query(...).highlight(fields: { ... })
311
324
  #
312
- def highlight value
325
+ def highlight(value)
313
326
  chain { criteria.update_request_options highlight: value }
314
327
  end
315
328
 
316
329
  # Elasticsearch rescore query option support
317
330
  #
331
+ # @example
318
332
  # UsersIndex.query(...).rescore(query: { ... })
319
333
  #
320
- def rescore value
334
+ def rescore(value)
321
335
  chain { criteria.update_request_options rescore: value }
322
336
  end
323
337
 
324
338
  # Elasticsearch minscore option support
325
339
  #
326
- # UsersIndex.query(...).min_score(0.5)
340
+ # @example
341
+ # UsersIndex.query(...).min_score(0.5)
327
342
  #
328
- def min_score value
343
+ def min_score(value)
329
344
  chain { criteria.update_request_options min_score: value }
330
345
  end
331
346
 
347
+ # Elasticsearch track_scores option support
348
+ #
349
+ # @example
350
+ # UsersIndex.query(...).track_scores(true)
351
+ #
352
+ def track_scores(value)
353
+ chain { criteria.update_request_options track_scores: value }
354
+ end
355
+
332
356
  # Adds facets section to the search request.
333
357
  # All the chained facets a merged and added to the
334
358
  # search request
335
359
  #
360
+ # @example
336
361
  # UsersIndex.facets(tags: {terms: {field: 'tags'}}).facets(ages: {terms: {field: 'age'}})
337
362
  # # => {body: {
338
363
  # query: {...},
@@ -342,7 +367,7 @@ module Chewy
342
367
  # If called parameterless - returns result facets from ES performing request.
343
368
  # Returns empty hash if no facets was requested or resulted.
344
369
  #
345
- def facets params = nil
370
+ def facets(params = nil)
346
371
  raise RemovedFeature, 'removed in elasticsearch 2.0' if Runtime.version >= '2.0'
347
372
  if params
348
373
  chain { criteria.update_facets params }
@@ -353,8 +378,9 @@ module Chewy
353
378
 
354
379
  # Adds a script function to score the search request. All scores are
355
380
  # added to the search request and combinded according to
356
- # <tt>boost_mode</tt> and <tt>score_mode</tt>
381
+ # `boost_mode` and `score_mode`
357
382
  #
383
+ # @example
358
384
  # UsersIndex.script_score("doc['boost'].value", params: { modifier: 2 })
359
385
  # # => {body:
360
386
  # query: {
@@ -369,17 +395,18 @@ module Chewy
369
395
  # }]
370
396
  # } } }
371
397
  def script_score(script, options = {})
372
- scoring = { script_score: { script: script }.merge(options) }
398
+ scoring = {script_score: {script: script}.merge(options)}
373
399
  chain { criteria.update_scores scoring }
374
400
  end
375
401
 
376
402
  # Adds a boost factor to the search request. All scores are
377
403
  # added to the search request and combinded according to
378
- # <tt>boost_mode</tt> and <tt>score_mode</tt>
404
+ # `boost_mode` and `score_mode`
379
405
  #
380
406
  # This probably only makes sense if you specify a filter
381
407
  # for the boost factor as well
382
408
  #
409
+ # @example
383
410
  # UsersIndex.boost_factor(23, filter: { term: { foo: :bar} })
384
411
  # # => {body:
385
412
  # query: {
@@ -395,15 +422,39 @@ module Chewy
395
422
  chain { criteria.update_scores scoring }
396
423
  end
397
424
 
425
+ # Add a weight scoring function to the search. All scores are
426
+ # added to the search request and combinded according to
427
+ # `boost_mode` and `score_mode`
428
+ #
429
+ # This probably only makes sense if you specify a filter
430
+ # for the weight as well.
431
+ #
432
+ # @example
433
+ # UsersIndex.weight(23, filter: { term: { foo: :bar} })
434
+ # # => {body:
435
+ # query: {
436
+ # function_score: {
437
+ # query: { ...},
438
+ # functions: [{
439
+ # weight: 23,
440
+ # filter: { term: { foo: :bar } }
441
+ # }]
442
+ # } } }
443
+ def weight(factor, options = {})
444
+ scoring = options.merge(weight: factor.to_i)
445
+ chain { criteria.update_scores scoring }
446
+ end
447
+
398
448
  # Adds a random score to the search request. All scores are
399
449
  # added to the search request and combinded according to
400
- # <tt>boost_mode</tt> and <tt>score_mode</tt>
450
+ # `boost_mode` and `score_mode`
401
451
  #
402
452
  # This probably only makes sense if you specify a filter
403
453
  # for the random score as well.
404
454
  #
405
455
  # If you do not pass in a seed value, Time.now will be used
406
456
  #
457
+ # @example
407
458
  # UsersIndex.random_score(23, filter: { foo: :bar})
408
459
  # # => {body:
409
460
  # query: {
@@ -415,17 +466,18 @@ module Chewy
415
466
  # }]
416
467
  # } } }
417
468
  def random_score(seed = Time.now, options = {})
418
- scoring = options.merge(random_score: { seed: seed.to_i })
469
+ scoring = options.merge(random_score: {seed: seed.to_i})
419
470
  chain { criteria.update_scores scoring }
420
471
  end
421
472
 
422
473
  # Add a field value scoring to the search. All scores are
423
474
  # added to the search request and combinded according to
424
- # <tt>boost_mode</tt> and <tt>score_mode</tt>
475
+ # `boost_mode` and `score_mode`
425
476
  #
426
477
  # This function is only available in Elasticsearch 1.2 and
427
478
  # greater
428
479
  #
480
+ # @example
429
481
  # UsersIndex.field_value_factor(
430
482
  # {
431
483
  # field: :boost,
@@ -452,11 +504,12 @@ module Chewy
452
504
 
453
505
  # Add a decay scoring to the search. All scores are
454
506
  # added to the search request and combinded according to
455
- # <tt>boost_mode</tt> and <tt>score_mode</tt>
507
+ # `boost_mode` and `score_mode`
456
508
  #
457
509
  # The parameters have default values, but those may not
458
510
  # be very useful for most applications.
459
511
  #
512
+ # @example
460
513
  # UsersIndex.decay(
461
514
  # :gauss,
462
515
  # :field,
@@ -489,8 +542,19 @@ module Chewy
489
542
  chain { criteria.update_scores scoring }
490
543
  end
491
544
 
492
- # Sets elasticsearch <tt>aggregations</tt> search request param
545
+ # Sets `preference` for request.
546
+ # For instance, one can use `preference=_primary` to execute only on the primary shards.
547
+ #
548
+ # @example
549
+ # scope = UsersIndex.preference(:_primary)
493
550
  #
551
+ def preference(value)
552
+ chain { criteria.update_search_options preference: value }
553
+ end
554
+
555
+ # Sets elasticsearch `aggregations` search request param
556
+ #
557
+ # @example
494
558
  # UsersIndex.filter{ name == 'Johny' }.aggregations(category_id: {terms: {field: 'category_ids'}})
495
559
  # # => {body: {
496
560
  # query: {...},
@@ -501,18 +565,18 @@ module Chewy
501
565
  # }
502
566
  # }}
503
567
  #
504
- def aggregations params = nil
568
+ def aggregations(params = nil)
505
569
  @_named_aggs ||= _build_named_aggs
506
570
  @_fully_qualified_named_aggs ||= _build_fqn_aggs
507
571
  if params
508
- params = { params => @_named_aggs[params] } if params.is_a?(Symbol)
509
- params = { params => _get_fully_qualified_named_agg(params) } if params.is_a?(String) && params =~ /\A\S+#\S+\.\S+\z/
572
+ params = {params => @_named_aggs[params]} if params.is_a?(Symbol)
573
+ params = {params => _get_fully_qualified_named_agg(params)} if params.is_a?(String) && params =~ /\A\S+#\S+\.\S+\z/
510
574
  chain { criteria.update_aggregations params }
511
575
  else
512
576
  _response['aggregations'] || {}
513
577
  end
514
578
  end
515
- alias :aggs :aggregations
579
+ alias_method :aggs, :aggregations
516
580
 
517
581
  # In this simplest of implementations each named aggregation must be uniquely named
518
582
  def _build_named_aggs
@@ -549,8 +613,9 @@ module Chewy
549
613
  @_fully_qualified_named_aggs[idx][type][agg_name]
550
614
  end
551
615
 
552
- # Sets elasticsearch <tt>suggest</tt> search request param
616
+ # Sets elasticsearch `suggest` search request param
553
617
  #
618
+ # @example
554
619
  # UsersIndex.suggest(name: {text: 'Joh', term: {field: 'name'}})
555
620
  # # => {body: {
556
621
  # query: {...},
@@ -562,7 +627,7 @@ module Chewy
562
627
  # }
563
628
  # }}
564
629
  #
565
- def suggest params = nil
630
+ def suggest(params = nil)
566
631
  if params
567
632
  chain { criteria.update_suggest params }
568
633
  else
@@ -570,10 +635,11 @@ module Chewy
570
635
  end
571
636
  end
572
637
 
573
- # Marks the criteria as having zero records. This scope always returns empty array
638
+ # Marks the criteria as having zero documents. This scope always returns empty array
574
639
  # without touching the elasticsearch server.
575
640
  # All the chained calls of methods don't affect the result
576
641
  #
642
+ # @example
577
643
  # UsersIndex.none.to_a
578
644
  # # => []
579
645
  # UsersIndex.query(text: {name: 'Johny'}).none.to_a
@@ -587,6 +653,7 @@ module Chewy
587
653
 
588
654
  # Setups strategy for top-level filtered query
589
655
  #
656
+ # @example
590
657
  # UsersIndex.filter { name == 'Johny'}.strategy(:leap_frog)
591
658
  # # => {body: {
592
659
  # query: { filtered: {
@@ -595,18 +662,19 @@ module Chewy
595
662
  # } }
596
663
  # }}
597
664
  #
598
- def strategy value = nil
665
+ def strategy(value = nil)
599
666
  chain { criteria.update_options strategy: value }
600
667
  end
601
668
 
602
669
  # Adds one or more query to the search request
603
670
  # Internally queries are stored as an array
604
671
  # While the full query compilation this array compiles
605
- # according to <tt>:query_mode</tt> option value
672
+ # according to `:query_mode` option value
606
673
  #
607
- # By default it joines inside <tt>must</tt> query
608
- # See <tt>#query_mode</tt> chainable method for more info.
674
+ # By default it joines inside `must` query
675
+ # See `#query_mode` chainable method for more info.
609
676
  #
677
+ # @example
610
678
  # UsersIndex.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}})
611
679
  # UsersIndex::User.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}})
612
680
  # # => {body: {
@@ -616,26 +684,28 @@ module Chewy
616
684
  # If only one query was specified, it will become a result
617
685
  # query as is, without joining.
618
686
  #
687
+ # @example
619
688
  # UsersIndex.query(text: {name: 'Johny'})
620
689
  # # => {body: {
621
690
  # query: {text: {name: 'Johny'}}
622
691
  # }}
623
692
  #
624
- def query params
693
+ def query(params)
625
694
  chain { criteria.update_queries params }
626
695
  end
627
696
 
628
697
  # Adds one or more filter to the search request
629
698
  # Internally filters are stored as an array
630
699
  # While the full query compilation this array compiles
631
- # according to <tt>:filter_mode</tt> option value
700
+ # according to `:filter_mode` option value
632
701
  #
633
- # By default it joins inside <tt>and</tt> filter
634
- # See <tt>#filter_mode</tt> chainable method for more info.
702
+ # By default it joins inside `and` filter
703
+ # See `#filter_mode` chainable method for more info.
635
704
  #
636
705
  # Also this method supports block DSL.
637
- # See <tt>Chewy::Query::Filters</tt> for more info.
706
+ # See `Chewy::Query::Filters` for more info.
638
707
  #
708
+ # @example
639
709
  # UsersIndex.filter(term: {name: 'Johny'}).filter(range: {age: {lte: 42}})
640
710
  # UsersIndex::User.filter(term: {name: 'Johny'}).filter(range: {age: {lte: 42}})
641
711
  # UsersIndex.filter{ name == 'Johny' }.filter{ age <= 42 }
@@ -647,13 +717,14 @@ module Chewy
647
717
  # If only one filter was specified, it will become a result
648
718
  # filter as is, without joining.
649
719
  #
720
+ # @example
650
721
  # UsersIndex.filter(term: {name: 'Johny'})
651
722
  # # => {body: {query: {filtered: {
652
723
  # query: {...},
653
724
  # filter: {term: {name: 'Johny'}}
654
725
  # }}}}
655
726
  #
656
- def filter params = nil, &block
727
+ def filter(params = nil, &block)
657
728
  params = Filters.new(&block).__render__ if block
658
729
  chain { criteria.update_filters params }
659
730
  end
@@ -661,14 +732,15 @@ module Chewy
661
732
  # Adds one or more post_filter to the search request
662
733
  # Internally post_filters are stored as an array
663
734
  # While the full query compilation this array compiles
664
- # according to <tt>:post_filter_mode</tt> option value
735
+ # according to `:post_filter_mode` option value
665
736
  #
666
- # By default it joins inside <tt>and</tt> filter
667
- # See <tt>#post_filter_mode</tt> chainable method for more info.
737
+ # By default it joins inside `and` filter
738
+ # See `#post_filter_mode` chainable method for more info.
668
739
  #
669
740
  # Also this method supports block DSL.
670
- # See <tt>Chewy::Query::Filters</tt> for more info.
741
+ # See `Chewy::Query::Filters` for more info.
671
742
  #
743
+ # @example
672
744
  # UsersIndex.post_filter(term: {name: 'Johny'}).post_filter(range: {age: {lte: 42}})
673
745
  # UsersIndex::User.post_filter(term: {name: 'Johny'}).post_filter(range: {age: {lte: 42}})
674
746
  # UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }
@@ -679,12 +751,13 @@ module Chewy
679
751
  # If only one post_filter was specified, it will become a result
680
752
  # post_filter as is, without joining.
681
753
  #
754
+ # @example
682
755
  # UsersIndex.post_filter(term: {name: 'Johny'})
683
756
  # # => {body: {
684
757
  # post_filter: {term: {name: 'Johny'}}
685
758
  # }}
686
759
  #
687
- def post_filter params = nil, &block
760
+ def post_filter(params = nil, &block)
688
761
  params = Filters.new(&block).__render__ if block
689
762
  chain { criteria.update_post_filters params }
690
763
  end
@@ -693,11 +766,10 @@ module Chewy
693
766
  # Not used if no score functions are specified
694
767
  # Possible values:
695
768
  #
696
- # * <tt>:multiply</tt>
769
+ # * `:multiply`
697
770
  # Default value. Query score and function result are multiplied.
698
771
  #
699
- # Ex:
700
- #
772
+ # @example
701
773
  # UsersIndex.boost_mode('multiply').script_score('doc['boost'].value')
702
774
  # # => {body: {query: function_score: {
703
775
  # query: {...},
@@ -705,24 +777,24 @@ module Chewy
705
777
  # functions: [ ... ]
706
778
  # }}}
707
779
  #
708
- # * <tt>:replace</tt>
780
+ # * `:replace`
709
781
  # Only function result is used, query score is ignored.
710
782
  #
711
- # * <tt>:sum</tt>
783
+ # * `:sum`
712
784
  # Query score and function score are added.
713
785
  #
714
- # * <tt>:avg</tt>
786
+ # * `:avg`
715
787
  # Average of query and function score.
716
788
  #
717
- # * <tt>:max</tt>
789
+ # * `:max`
718
790
  # Max of query and function score.
719
791
  #
720
- # * <tt>:min</tt>
792
+ # * `:min`
721
793
  # Min of query and function score.
722
794
  #
723
- # Default value for <tt>:boost_mode</tt> might be changed
724
- # with <tt>Chewy.score_mode</tt> config option.
725
- def boost_mode value
795
+ # Default value for `:boost_mode` might be changed
796
+ # with `Chewy.score_mode` config option.
797
+ def boost_mode(value)
726
798
  chain { criteria.update_options boost_mode: value }
727
799
  end
728
800
 
@@ -730,11 +802,10 @@ module Chewy
730
802
  # Not used if no score functions are specified.
731
803
  # Possible values:
732
804
  #
733
- # * <tt>:multiply</tt>
805
+ # * `:multiply`
734
806
  # Default value. Scores are multiplied.
735
807
  #
736
- # Ex:
737
- #
808
+ # @example
738
809
  # UsersIndex.score_mode('multiply').script_score('doc['boost'].value')
739
810
  # # => {body: {query: function_score: {
740
811
  # query: {...},
@@ -742,82 +813,88 @@ module Chewy
742
813
  # functions: [ ... ]
743
814
  # }}}
744
815
  #
745
- # * <tt>:sum</tt>
816
+ # * `:sum`
746
817
  # Scores are summed.
747
818
  #
748
- # * <tt>:avg</tt>
819
+ # * `:avg`
749
820
  # Scores are averaged.
750
821
  #
751
- # * <tt>:first</tt>
822
+ # * `:first`
752
823
  # The first function that has a matching filter is applied.
753
824
  #
754
- # * <tt>:max</tt>
825
+ # * `:max`
755
826
  # Maximum score is used.
756
827
  #
757
- # * <tt>:min</tt>
828
+ # * `:min`
758
829
  # Minimum score is used
759
830
  #
760
- # Default value for <tt>:score_mode</tt> might be changed
761
- # with <tt>Chewy.score_mode</tt> config option.
831
+ # Default value for `:score_mode` might be changed
832
+ # with `Chewy.score_mode` config option.
762
833
  #
834
+ # @example
763
835
  # Chewy.score_mode = :first
764
836
  #
765
- def score_mode value
837
+ def score_mode(value)
766
838
  chain { criteria.update_options score_mode: value }
767
839
  end
768
840
 
769
841
  # Sets search request sorting
770
842
  #
843
+ # @example
771
844
  # UsersIndex.order(:first_name, :last_name).order(age: :desc).order(price: {order: :asc, mode: :avg})
772
845
  # # => {body: {
773
846
  # query: {...},
774
847
  # sort: ['first_name', 'last_name', {age: 'desc'}, {price: {order: 'asc', mode: 'avg'}}]
775
848
  # }}
776
849
  #
777
- def order *params
850
+ def order(*params)
778
851
  chain { criteria.update_sort params }
779
852
  end
780
853
 
781
854
  # Cleans up previous search sorting and sets the new one
782
855
  #
856
+ # @example
783
857
  # UsersIndex.order(:first_name, :last_name).order(age: :desc).reorder(price: {order: :asc, mode: :avg})
784
858
  # # => {body: {
785
859
  # query: {...},
786
860
  # sort: [{price: {order: 'asc', mode: 'avg'}}]
787
861
  # }}
788
862
  #
789
- def reorder *params
863
+ def reorder(*params)
790
864
  chain { criteria.update_sort params, purge: true }
791
865
  end
792
866
 
793
867
  # Sets search request field list
794
868
  #
869
+ # @example
795
870
  # UsersIndex.only(:first_name, :last_name).only(:age)
796
871
  # # => {body: {
797
872
  # query: {...},
798
873
  # fields: ['first_name', 'last_name', 'age']
799
874
  # }}
800
875
  #
801
- def only *params
876
+ def only(*params)
802
877
  chain { criteria.update_fields params }
803
878
  end
804
879
 
805
880
  # Cleans up previous search field list and sets the new one
806
881
  #
882
+ # @example
807
883
  # UsersIndex.only(:first_name, :last_name).only!(:age)
808
884
  # # => {body: {
809
885
  # query: {...},
810
886
  # fields: ['age']
811
887
  # }}
812
888
  #
813
- def only! *params
889
+ def only!(*params)
814
890
  chain { criteria.update_fields params, purge: true }
815
891
  end
816
892
 
817
893
  # Specify types participating in the search result
818
- # Works via <tt>types</tt> filter. Always merged with another filters
819
- # with the <tt>and</tt> filter.
894
+ # Works via `types` filter. Always merged with another filters
895
+ # with the `and` filter.
820
896
  #
897
+ # @example
821
898
  # UsersIndex.types(:admin, :manager).filters{ name == 'Johny' }.filters{ age <= 42 }
822
899
  # # => {body: {query: {filtered: {
823
900
  # query: {...},
@@ -846,72 +923,88 @@ module Chewy
846
923
  # ]}
847
924
  # }}}}
848
925
  #
849
- def types *params
926
+ def types(*params)
850
927
  chain { criteria.update_types params }
851
928
  end
852
929
 
853
- # Acts the same way as <tt>types</tt>, but cleans up previously set types
930
+ # Acts the same way as `types`, but cleans up previously set types
854
931
  #
932
+ # @example
855
933
  # UsersIndex.types(:admin).types!(:manager)
856
934
  # # => {body: {query: {filtered: {
857
935
  # query: {...},
858
936
  # filter: {type: {value: 'manager'}}
859
937
  # }}}}
860
938
  #
861
- def types! *params
939
+ def types!(*params)
862
940
  chain { criteria.update_types params, purge: true }
863
941
  end
864
942
 
865
- # Sets <tt>search_type</tt> for request.
866
- # For instance, one can use <tt>search_type=count</tt> to fetch only total count of records or to fetch only aggregations without fetching records.
943
+ # Sets `search_type` for request.
944
+ # For instance, one can use `search_type=count` to fetch only total count of documents or to fetch only aggregations without fetching documents.
867
945
  #
946
+ # @example
868
947
  # scope = UsersIndex.search_type(:count)
869
- # scope.count == 0 # no records actually fetched
948
+ # scope.count == 0 # no documents actually fetched
870
949
  # scope.total == 10 # but we know a total count of them
871
950
  #
872
951
  # scope = UsersIndex.aggs(max_age: { max: { field: 'age' } }).search_type(:count)
873
952
  # max_age = scope.aggs['max_age']['value']
874
953
  #
875
- def search_type val
876
- chain { options.merge!(search_type: val) }
954
+ def search_type(value)
955
+ chain { criteria.update_search_options search_type: value }
877
956
  end
878
957
 
879
958
  # Merges two queries.
880
959
  # Merges all the values in criteria with the same rules as values added manually.
881
960
  #
961
+ # @example
882
962
  # scope1 = UsersIndex.filter{ name == 'Johny' }
883
963
  # scope2 = UsersIndex.filter{ age <= 42 }
884
964
  # scope3 = UsersIndex.filter{ name == 'Johny' }.filter{ age <= 42 }
885
965
  #
886
966
  # scope1.merge(scope2) == scope3 # => true
887
967
  #
888
- def merge other
968
+ def merge(other)
889
969
  chain { criteria.merge!(other.criteria) }
890
970
  end
891
971
 
892
- # Deletes all records matching a query.
972
+ # Deletes all documents matching a query.
893
973
  #
974
+ # @example
894
975
  # UsersIndex.delete_all
895
976
  # UsersIndex.filter{ age <= 42 }.delete_all
896
977
  # UsersIndex::User.delete_all
897
978
  # UsersIndex::User.filter{ age <= 42 }.delete_all
898
979
  #
899
980
  def delete_all
900
- if Runtime.version > '2.0'
901
- plugins = Chewy.client.nodes.info(plugins: true)["nodes"].values.map { |item| item["plugins"] }.flatten
902
- raise PluginMissing, "install delete-by-query plugin" unless plugins.find { |item| item["name"] == 'delete-by-query' }
981
+ if Runtime.version >= '2.0'
982
+ plugins = Chewy.client.nodes.info(plugins: true)['nodes'].values.map { |item| item['plugins'] }.flatten
983
+ raise PluginMissing, 'install delete-by-query plugin' unless plugins.find { |item| item['name'] == 'delete-by-query' }
903
984
  end
985
+
904
986
  request = chain { criteria.update_options simple: true }.send(:_request)
987
+
905
988
  ActiveSupport::Notifications.instrument 'delete_query.chewy',
906
989
  request: request, indexes: _indexes, types: _types,
907
990
  index: _indexes.one? ? _indexes.first : _indexes,
908
991
  type: _types.one? ? _types.first : _types do
909
- Chewy.client.delete_by_query(request)
910
- end
992
+ if Runtime.version >= '2.0'
993
+ path = Elasticsearch::API::Utils.__pathify(
994
+ Elasticsearch::API::Utils.__listify(request[:index]),
995
+ Elasticsearch::API::Utils.__listify(request[:type]),
996
+ '/_query'
997
+ )
998
+ Chewy.client.perform_request(Elasticsearch::API::HTTP_DELETE, path, {}, request[:body]).body
999
+ else
1000
+ Chewy.client.delete_by_query(request)
1001
+ end
1002
+ end
911
1003
  end
912
1004
 
913
- # Find all records matching a query.
1005
+ # Find all documents matching a query.
914
1006
  #
1007
+ # @example
915
1008
  # UsersIndex.find(42)
916
1009
  # UsersIndex.filter{ age <= 42 }.find(42)
917
1010
  # UsersIndex::User.find(42)
@@ -920,19 +1013,41 @@ module Chewy
920
1013
  # In all the previous examples find will return a single object.
921
1014
  # To get a collection - pass an array of ids.
922
1015
  #
1016
+ # @example
923
1017
  # UsersIndex::User.find(42, 7, 3) # array of objects with ids in [42, 7, 3]
924
1018
  # UsersIndex::User.find([8, 13]) # array of objects with ids in [8, 13]
925
1019
  # UsersIndex::User.find([42]) # array of the object with id == 42
926
1020
  #
927
- def find *ids
1021
+ def find(*ids)
928
1022
  results = chain { criteria.update_options simple: true }.filter { _id == ids.flatten }.to_a
929
1023
 
930
- raise Chewy::DocumentNotFound.new("Could not find documents for ids #{ids.flatten}") if results.empty?
1024
+ raise Chewy::DocumentNotFound, "Could not find documents for ids #{ids.flatten}" if results.empty?
931
1025
  ids.one? && !ids.first.is_a?(Array) ? results.first : results
932
1026
  end
933
1027
 
1028
+ # Returns true if there are at least one document that matches the query
1029
+ #
1030
+ # @example
1031
+ # PlacesIndex.query(...).filter(...).exists?
1032
+ #
1033
+ def exists?
1034
+ search_type(:count).total > 0
1035
+ end
1036
+
1037
+ # Sets limit to be equal to total documents count
1038
+ #
1039
+ # @example
1040
+ # PlacesIndex.query(...).filter(...).unlimited
1041
+ #
1042
+
1043
+ def unlimited
1044
+ count_query = search_type(:count)
1045
+ offset(0).limit { count_query.total }
1046
+ end
1047
+
934
1048
  # Returns request total time elapsed as reported by elasticsearch
935
1049
  #
1050
+ # @example
936
1051
  # UsersIndex.query(...).filter(...).took
937
1052
  #
938
1053
  def took
@@ -947,6 +1062,7 @@ module Chewy
947
1062
  # important to you than complete results, you can specify a timeout as 10 or
948
1063
  # "10ms" (10 milliseconds), or "1s" (1 second). See #timeout method.
949
1064
  #
1065
+ # @example
950
1066
  # UsersIndex.query(...).filter(...).timed_out
951
1067
  #
952
1068
  def timed_out
@@ -955,14 +1071,14 @@ module Chewy
955
1071
 
956
1072
  protected
957
1073
 
958
- def initialize_clone other
959
- @criteria = other.criteria.clone
1074
+ def initialize_clone(origin)
1075
+ @criteria = origin.criteria.clone
960
1076
  reset
961
1077
  end
962
1078
 
963
1079
  private
964
1080
 
965
- def chain &block
1081
+ def chain(&block)
966
1082
  clone.tap { |q| q.instance_exec(&block) }
967
1083
  end
968
1084
 
@@ -973,8 +1089,8 @@ module Chewy
973
1089
  def _request
974
1090
  @_request ||= begin
975
1091
  request = criteria.request_body
976
- request.merge!(index: _indexes.map(&:index_name), type: _types.map(&:type_name))
977
- request.merge!(search_type: options[:search_type]) if options[:search_type]
1092
+ request[:index] = _indexes_hash.keys
1093
+ request[:type] = _types.map(&:type_name)
978
1094
  request
979
1095
  end
980
1096
  end
@@ -984,37 +1100,37 @@ module Chewy
984
1100
  request: _request, indexes: _indexes, types: _types,
985
1101
  index: _indexes.one? ? _indexes.first : _indexes,
986
1102
  type: _types.one? ? _types.first : _types do
987
- begin
988
- Chewy.client.search(_request)
989
- rescue Elasticsearch::Transport::Transport::Errors::NotFound => e
990
- raise e if e.message !~ /IndexMissingException/ && e.message !~ /index_not_found_exception/
991
- {}
992
- end
1103
+ begin
1104
+ Chewy.client.search(_request)
1105
+ rescue Elasticsearch::Transport::Transport::Errors::NotFound => e
1106
+ raise e if e.message !~ /IndexMissingException/ && e.message !~ /index_not_found_exception/
1107
+ {}
1108
+ end
993
1109
  end
994
1110
  end
995
1111
 
996
1112
  def _results
997
1113
  @_results ||= (criteria.none? || _response == {} ? [] : _response['hits']['hits']).map do |hit|
998
- attributes = (hit['_source'] || {})
999
- .reverse_merge(id: hit['_id'])
1000
- .merge!(_score: hit['_score'])
1001
- .merge!(_explanation: hit['_explanation'])
1002
-
1003
- wrapper = _derive_index(hit['_index']).type_hash[hit['_type']].new attributes
1004
- wrapper._data = hit
1005
- wrapper
1114
+ _derive_type(hit['_index'], hit['_type']).build(hit)
1006
1115
  end
1007
1116
  end
1008
1117
 
1009
1118
  def _collection
1010
1119
  @_collection ||= begin
1011
1120
  _load_objects! if criteria.options[:preload]
1012
- criteria.options[:preload] && criteria.options[:loaded_objects] ?
1013
- _results.map(&:_object) : _results
1121
+ if criteria.options[:preload] && criteria.options[:loaded_objects]
1122
+ _results.map(&:_object)
1123
+ else
1124
+ _results
1125
+ end
1014
1126
  end
1015
1127
  end
1016
1128
 
1017
- def _derive_index index_name
1129
+ def _derive_type(index, type)
1130
+ (@types_cache ||= {})[[index, type]] ||= _derive_index(index).type(type)
1131
+ end
1132
+
1133
+ def _derive_index(index_name)
1018
1134
  (@derive_index ||= {})[index_name] ||= _indexes_hash[index_name] ||
1019
1135
  _indexes_hash[_indexes_hash.keys.sort_by(&:length).reverse.detect { |name| index_name.start_with?(name) }]
1020
1136
  end