chewy 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (265) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +24 -2
  4. data/.rubocop_todo.yml +2 -2
  5. data/.travis.yml +38 -21
  6. data/.yardopts +5 -0
  7. data/Appraisals +55 -27
  8. data/CHANGELOG.md +57 -12
  9. data/Gemfile +14 -10
  10. data/LEGACY_DSL.md +497 -0
  11. data/README.md +249 -515
  12. data/chewy.gemspec +5 -4
  13. data/gemfiles/rails.4.0.activerecord.gemfile +14 -0
  14. data/gemfiles/rails.4.1.activerecord.gemfile +14 -0
  15. data/gemfiles/rails.4.2.activerecord.gemfile +8 -10
  16. data/gemfiles/rails.4.2.mongoid.5.1.gemfile +9 -10
  17. data/gemfiles/rails.5.0.activerecord.gemfile +8 -10
  18. data/gemfiles/rails.5.0.mongoid.6.0.gemfile +15 -0
  19. data/gemfiles/rails.5.1.activerecord.gemfile +15 -0
  20. data/gemfiles/rails.5.1.mongoid.6.1.gemfile +15 -0
  21. data/gemfiles/sequel.4.45.gemfile +11 -0
  22. data/lib/chewy.rb +77 -43
  23. data/lib/chewy/config.rb +44 -7
  24. data/lib/chewy/errors.rb +2 -2
  25. data/lib/chewy/fields/base.rb +39 -32
  26. data/lib/chewy/fields/root.rb +33 -7
  27. data/lib/chewy/index.rb +237 -149
  28. data/lib/chewy/index/actions.rb +85 -28
  29. data/lib/chewy/index/aliases.rb +2 -1
  30. data/lib/chewy/index/settings.rb +9 -5
  31. data/lib/chewy/index/specification.rb +58 -0
  32. data/lib/chewy/journal.rb +40 -92
  33. data/lib/chewy/query.rb +43 -27
  34. data/lib/chewy/query/compose.rb +13 -13
  35. data/lib/chewy/query/criteria.rb +13 -13
  36. data/lib/chewy/query/filters.rb +1 -1
  37. data/lib/chewy/query/loading.rb +1 -1
  38. data/lib/chewy/query/nodes/and.rb +2 -2
  39. data/lib/chewy/query/nodes/bool.rb +1 -1
  40. data/lib/chewy/query/nodes/equal.rb +2 -2
  41. data/lib/chewy/query/nodes/exists.rb +1 -1
  42. data/lib/chewy/query/nodes/has_relation.rb +2 -2
  43. data/lib/chewy/query/nodes/match_all.rb +1 -1
  44. data/lib/chewy/query/nodes/missing.rb +1 -1
  45. data/lib/chewy/query/nodes/not.rb +2 -2
  46. data/lib/chewy/query/nodes/or.rb +2 -2
  47. data/lib/chewy/query/nodes/prefix.rb +1 -1
  48. data/lib/chewy/query/nodes/query.rb +2 -2
  49. data/lib/chewy/query/nodes/range.rb +4 -4
  50. data/lib/chewy/query/nodes/regexp.rb +4 -4
  51. data/lib/chewy/query/nodes/script.rb +3 -3
  52. data/lib/chewy/query/pagination.rb +10 -1
  53. data/lib/chewy/railtie.rb +1 -0
  54. data/lib/chewy/rake_helper.rb +265 -48
  55. data/lib/chewy/rspec/update_index.rb +30 -22
  56. data/lib/chewy/search.rb +78 -21
  57. data/lib/chewy/search/loader.rb +83 -0
  58. data/lib/chewy/{query → search}/pagination/kaminari.rb +13 -5
  59. data/lib/chewy/search/pagination/will_paginate.rb +41 -0
  60. data/lib/chewy/search/parameters.rb +150 -0
  61. data/lib/chewy/search/parameters/aggs.rb +16 -0
  62. data/lib/chewy/search/parameters/concerns/bool_storage.rb +24 -0
  63. data/lib/chewy/search/parameters/concerns/hash_storage.rb +23 -0
  64. data/lib/chewy/search/parameters/concerns/integer_storage.rb +14 -0
  65. data/lib/chewy/search/parameters/concerns/query_storage.rb +237 -0
  66. data/lib/chewy/search/parameters/concerns/string_array_storage.rb +23 -0
  67. data/lib/chewy/search/parameters/concerns/string_storage.rb +14 -0
  68. data/lib/chewy/search/parameters/docvalue_fields.rb +12 -0
  69. data/lib/chewy/search/parameters/explain.rb +16 -0
  70. data/lib/chewy/search/parameters/filter.rb +47 -0
  71. data/lib/chewy/search/parameters/highlight.rb +16 -0
  72. data/lib/chewy/search/parameters/indices_boost.rb +52 -0
  73. data/lib/chewy/search/parameters/limit.rb +17 -0
  74. data/lib/chewy/search/parameters/load.rb +32 -0
  75. data/lib/chewy/search/parameters/min_score.rb +16 -0
  76. data/lib/chewy/search/parameters/none.rb +27 -0
  77. data/lib/chewy/search/parameters/offset.rb +17 -0
  78. data/lib/chewy/search/parameters/order.rb +64 -0
  79. data/lib/chewy/search/parameters/post_filter.rb +19 -0
  80. data/lib/chewy/search/parameters/preference.rb +16 -0
  81. data/lib/chewy/search/parameters/profile.rb +16 -0
  82. data/lib/chewy/search/parameters/query.rb +19 -0
  83. data/lib/chewy/search/parameters/request_cache.rb +27 -0
  84. data/lib/chewy/search/parameters/rescore.rb +29 -0
  85. data/lib/chewy/search/parameters/script_fields.rb +16 -0
  86. data/lib/chewy/search/parameters/search_after.rb +20 -0
  87. data/lib/chewy/search/parameters/search_type.rb +16 -0
  88. data/lib/chewy/search/parameters/source.rb +73 -0
  89. data/lib/chewy/search/parameters/storage.rb +95 -0
  90. data/lib/chewy/search/parameters/stored_fields.rb +63 -0
  91. data/lib/chewy/search/parameters/suggest.rb +16 -0
  92. data/lib/chewy/search/parameters/terminate_after.rb +16 -0
  93. data/lib/chewy/search/parameters/timeout.rb +16 -0
  94. data/lib/chewy/search/parameters/track_scores.rb +16 -0
  95. data/lib/chewy/search/parameters/types.rb +20 -0
  96. data/lib/chewy/search/parameters/version.rb +16 -0
  97. data/lib/chewy/search/query_proxy.rb +257 -0
  98. data/lib/chewy/search/request.rb +1021 -0
  99. data/lib/chewy/search/response.rb +119 -0
  100. data/lib/chewy/search/scoping.rb +50 -0
  101. data/lib/chewy/search/scrolling.rb +136 -0
  102. data/lib/chewy/stash.rb +70 -0
  103. data/lib/chewy/strategy.rb +10 -3
  104. data/lib/chewy/strategy/active_job.rb +1 -0
  105. data/lib/chewy/strategy/atomic.rb +1 -3
  106. data/lib/chewy/strategy/bypass.rb +1 -1
  107. data/lib/chewy/strategy/resque.rb +1 -0
  108. data/lib/chewy/strategy/shoryuken.rb +40 -0
  109. data/lib/chewy/strategy/sidekiq.rb +13 -3
  110. data/lib/chewy/type.rb +29 -7
  111. data/lib/chewy/type/actions.rb +26 -2
  112. data/lib/chewy/type/adapter/active_record.rb +44 -29
  113. data/lib/chewy/type/adapter/base.rb +27 -7
  114. data/lib/chewy/type/adapter/mongoid.rb +18 -7
  115. data/lib/chewy/type/adapter/object.rb +187 -26
  116. data/lib/chewy/type/adapter/orm.rb +59 -32
  117. data/lib/chewy/type/adapter/sequel.rb +32 -16
  118. data/lib/chewy/type/import.rb +145 -191
  119. data/lib/chewy/type/import/bulk_builder.rb +122 -0
  120. data/lib/chewy/type/import/bulk_request.rb +76 -0
  121. data/lib/chewy/type/import/journal_builder.rb +45 -0
  122. data/lib/chewy/type/import/routine.rb +138 -0
  123. data/lib/chewy/type/mapping.rb +11 -1
  124. data/lib/chewy/type/observe.rb +1 -1
  125. data/lib/chewy/type/syncer.rb +220 -0
  126. data/lib/chewy/type/witchcraft.rb +27 -13
  127. data/lib/chewy/type/wrapper.rb +28 -2
  128. data/lib/chewy/version.rb +1 -1
  129. data/lib/tasks/chewy.rake +84 -26
  130. data/spec/chewy/config_spec.rb +82 -1
  131. data/spec/chewy/fields/base_spec.rb +147 -112
  132. data/spec/chewy/fields/root_spec.rb +75 -18
  133. data/spec/chewy/fields/time_fields_spec.rb +2 -3
  134. data/spec/chewy/index/actions_spec.rb +180 -50
  135. data/spec/chewy/index/aliases_spec.rb +2 -2
  136. data/spec/chewy/index/settings_spec.rb +67 -38
  137. data/spec/chewy/index/specification_spec.rb +160 -0
  138. data/spec/chewy/index_spec.rb +57 -66
  139. data/spec/chewy/journal_spec.rb +149 -54
  140. data/spec/chewy/minitest/helpers_spec.rb +4 -4
  141. data/spec/chewy/minitest/search_index_receiver_spec.rb +1 -1
  142. data/spec/chewy/query/criteria_spec.rb +179 -179
  143. data/spec/chewy/query/filters_spec.rb +15 -15
  144. data/spec/chewy/query/loading_spec.rb +22 -20
  145. data/spec/chewy/query/nodes/and_spec.rb +2 -2
  146. data/spec/chewy/query/nodes/bool_spec.rb +4 -4
  147. data/spec/chewy/query/nodes/equal_spec.rb +19 -19
  148. data/spec/chewy/query/nodes/exists_spec.rb +6 -6
  149. data/spec/chewy/query/nodes/has_child_spec.rb +19 -19
  150. data/spec/chewy/query/nodes/has_parent_spec.rb +19 -19
  151. data/spec/chewy/query/nodes/missing_spec.rb +5 -5
  152. data/spec/chewy/query/nodes/not_spec.rb +3 -2
  153. data/spec/chewy/query/nodes/or_spec.rb +2 -2
  154. data/spec/chewy/query/nodes/prefix_spec.rb +5 -5
  155. data/spec/chewy/query/nodes/query_spec.rb +2 -2
  156. data/spec/chewy/query/nodes/range_spec.rb +18 -18
  157. data/spec/chewy/query/nodes/raw_spec.rb +1 -1
  158. data/spec/chewy/query/nodes/regexp_spec.rb +14 -14
  159. data/spec/chewy/query/nodes/script_spec.rb +4 -4
  160. data/spec/chewy/query/pagination/kaminari_spec.rb +3 -55
  161. data/spec/chewy/query/pagination/will_paginate_spec.rb +5 -0
  162. data/spec/chewy/query/pagination_spec.rb +25 -21
  163. data/spec/chewy/query_spec.rb +501 -560
  164. data/spec/chewy/rake_helper_spec.rb +368 -0
  165. data/spec/chewy/repository_spec.rb +4 -4
  166. data/spec/chewy/rspec/update_index_spec.rb +89 -56
  167. data/spec/chewy/runtime_spec.rb +2 -2
  168. data/spec/chewy/search/loader_spec.rb +117 -0
  169. data/spec/chewy/search/pagination/kaminari_examples.rb +71 -0
  170. data/spec/chewy/search/pagination/kaminari_spec.rb +17 -0
  171. data/spec/chewy/search/pagination/will_paginate_examples.rb +63 -0
  172. data/spec/chewy/search/pagination/will_paginate_spec.rb +17 -0
  173. data/spec/chewy/search/parameters/aggs_spec.rb +5 -0
  174. data/spec/chewy/search/parameters/bool_storage_examples.rb +53 -0
  175. data/spec/chewy/search/parameters/docvalue_fields_spec.rb +5 -0
  176. data/spec/chewy/search/parameters/explain_spec.rb +5 -0
  177. data/spec/chewy/search/parameters/filter_spec.rb +5 -0
  178. data/spec/chewy/search/parameters/hash_storage_examples.rb +59 -0
  179. data/spec/chewy/search/parameters/highlight_spec.rb +5 -0
  180. data/spec/chewy/search/parameters/indices_boost_spec.rb +83 -0
  181. data/spec/chewy/search/parameters/integer_storage_examples.rb +32 -0
  182. data/spec/chewy/search/parameters/limit_spec.rb +5 -0
  183. data/spec/chewy/search/parameters/load_spec.rb +60 -0
  184. data/spec/chewy/search/parameters/min_score_spec.rb +32 -0
  185. data/spec/chewy/search/parameters/none_spec.rb +5 -0
  186. data/spec/chewy/search/parameters/offset_spec.rb +5 -0
  187. data/spec/chewy/search/parameters/order_spec.rb +65 -0
  188. data/spec/chewy/search/parameters/post_filter_spec.rb +5 -0
  189. data/spec/chewy/search/parameters/preference_spec.rb +5 -0
  190. data/spec/chewy/search/parameters/profile_spec.rb +5 -0
  191. data/spec/chewy/search/parameters/query_spec.rb +5 -0
  192. data/spec/chewy/search/parameters/query_storage_examples.rb +388 -0
  193. data/spec/chewy/search/parameters/request_cache_spec.rb +67 -0
  194. data/spec/chewy/search/parameters/rescore_spec.rb +62 -0
  195. data/spec/chewy/search/parameters/script_fields_spec.rb +5 -0
  196. data/spec/chewy/search/parameters/search_after_spec.rb +32 -0
  197. data/spec/chewy/search/parameters/search_type_spec.rb +5 -0
  198. data/spec/chewy/search/parameters/source_spec.rb +156 -0
  199. data/spec/chewy/search/parameters/storage_spec.rb +60 -0
  200. data/spec/chewy/search/parameters/stored_fields_spec.rb +126 -0
  201. data/spec/chewy/search/parameters/string_array_storage_examples.rb +63 -0
  202. data/spec/chewy/search/parameters/string_storage_examples.rb +32 -0
  203. data/spec/chewy/search/parameters/suggest_spec.rb +5 -0
  204. data/spec/chewy/search/parameters/terminate_after_spec.rb +5 -0
  205. data/spec/chewy/search/parameters/timeout_spec.rb +5 -0
  206. data/spec/chewy/search/parameters/track_scores_spec.rb +5 -0
  207. data/spec/chewy/search/parameters/types_spec.rb +5 -0
  208. data/spec/chewy/search/parameters/version_spec.rb +5 -0
  209. data/spec/chewy/search/parameters_spec.rb +130 -0
  210. data/spec/chewy/search/query_proxy_spec.rb +68 -0
  211. data/spec/chewy/search/request_spec.rb +669 -0
  212. data/spec/chewy/search/response_spec.rb +192 -0
  213. data/spec/chewy/search/scrolling_spec.rb +169 -0
  214. data/spec/chewy/search_spec.rb +13 -6
  215. data/spec/chewy/stash_spec.rb +95 -0
  216. data/spec/chewy/strategy/active_job_spec.rb +6 -0
  217. data/spec/chewy/strategy/resque_spec.rb +6 -0
  218. data/spec/chewy/strategy/shoryuken_spec.rb +64 -0
  219. data/spec/chewy/strategy/sidekiq_spec.rb +8 -0
  220. data/spec/chewy/strategy_spec.rb +6 -6
  221. data/spec/chewy/type/actions_spec.rb +29 -10
  222. data/spec/chewy/type/adapter/active_record_spec.rb +203 -91
  223. data/spec/chewy/type/adapter/mongoid_spec.rb +112 -54
  224. data/spec/chewy/type/adapter/object_spec.rb +101 -28
  225. data/spec/chewy/type/adapter/sequel_spec.rb +149 -82
  226. data/spec/chewy/type/import/bulk_builder_spec.rb +279 -0
  227. data/spec/chewy/type/import/bulk_request_spec.rb +102 -0
  228. data/spec/chewy/type/import/journal_builder_spec.rb +95 -0
  229. data/spec/chewy/type/import/routine_spec.rb +110 -0
  230. data/spec/chewy/type/import_spec.rb +350 -271
  231. data/spec/chewy/type/mapping_spec.rb +54 -18
  232. data/spec/chewy/type/observe_spec.rb +5 -1
  233. data/spec/chewy/type/syncer_spec.rb +123 -0
  234. data/spec/chewy/type/witchcraft_spec.rb +45 -29
  235. data/spec/chewy/type/wrapper_spec.rb +63 -23
  236. data/spec/chewy/type_spec.rb +28 -7
  237. data/spec/chewy_spec.rb +75 -7
  238. data/spec/spec_helper.rb +5 -2
  239. data/spec/support/active_record.rb +5 -1
  240. data/spec/support/class_helpers.rb +0 -14
  241. data/spec/support/mongoid.rb +15 -3
  242. data/spec/support/sequel.rb +6 -1
  243. metadata +198 -37
  244. data/gemfiles/rails.3.2.activerecord.gemfile +0 -16
  245. data/gemfiles/rails.3.2.activerecord.kaminari.gemfile +0 -15
  246. data/gemfiles/rails.3.2.activerecord.will_paginate.gemfile +0 -15
  247. data/gemfiles/rails.4.2.activerecord.kaminari.gemfile +0 -16
  248. data/gemfiles/rails.4.2.activerecord.will_paginate.gemfile +0 -16
  249. data/gemfiles/rails.4.2.mongoid.4.0.gemfile +0 -16
  250. data/gemfiles/rails.4.2.mongoid.4.0.kaminari.gemfile +0 -15
  251. data/gemfiles/rails.4.2.mongoid.4.0.will_paginate.gemfile +0 -15
  252. data/gemfiles/rails.4.2.mongoid.5.1.kaminari.gemfile +0 -15
  253. data/gemfiles/rails.4.2.mongoid.5.1.will_paginate.gemfile +0 -15
  254. data/gemfiles/rails.5.0.activerecord.kaminari.gemfile +0 -16
  255. data/gemfiles/rails.5.0.activerecord.will_paginate.gemfile +0 -16
  256. data/gemfiles/sequel.4.38.gemfile +0 -14
  257. data/lib/chewy/journal/apply.rb +0 -31
  258. data/lib/chewy/journal/clean.rb +0 -24
  259. data/lib/chewy/journal/entry.rb +0 -83
  260. data/lib/chewy/journal/query.rb +0 -87
  261. data/lib/chewy/query/pagination/will_paginate.rb +0 -27
  262. data/lib/chewy/query/scoping.rb +0 -20
  263. data/spec/chewy/journal/apply_spec.rb +0 -120
  264. data/spec/chewy/journal/entry_spec.rb +0 -237
  265. data/spec/chewy/query/pagination/will_paginage_spec.rb +0 -59
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de7c5c4e672dfb909540467bf37a13aaa21933c1
4
- data.tar.gz: 1e6a424a74805c9e19495f9c2d33a1e16cd0a843
3
+ metadata.gz: d7aa20726080ec98870f97d0c0ef730a3eb7bc4f
4
+ data.tar.gz: 66b15afd916e7ed479bf7e9bacc3286a9ce9dc25
5
5
  SHA512:
6
- metadata.gz: 9a7b5152aa2def448318b81b1fbac395ad652620c079c8013332e5e44ffebcfb27932688d81b7116f95447e37ebe715630307bf45e010f6964ff12a618a97d97
7
- data.tar.gz: 370c365d9d690e29e5ab7de4ba06f0dff07aa360edbb7f18c982bf2c6f288b1bdd7554bb8bc569993d82553c696e44c3c726ab5c11db278b1d6fcc4c472b4998
6
+ metadata.gz: 5800f28ff7480f5c7052c5860a5b3f3e6547ebee02e88f82d59e4aa2df6764d3330ee5c00ee3b36cff26c74ebec5d3713641868618d465718c6c615bae12ef85
7
+ data.tar.gz: eb17d5fa79ec63472fdb0adac109d8612af6a9693bcda2afe05efe20f32b9d221933403049ba27731a9410752e6c955e522fceab4e7d6c372b38b64f21d87708
data/.gitignore CHANGED
@@ -19,3 +19,4 @@ tmp
19
19
  .rvmrc
20
20
  _site
21
21
  .sass-cache
22
+ file::memory:?cache=shared
@@ -1,7 +1,10 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ Lint/AmbiguousBlockAssociation:
4
+ Enabled: false
5
+
3
6
  Lint/EndAlignment:
4
- AlignWith: variable
7
+ EnforcedStyleAlignWith: variable
5
8
 
6
9
  Style/AccessModifierIndentation:
7
10
  EnforcedStyle: outdent
@@ -19,7 +22,7 @@ Style/AndOr:
19
22
  EnforcedStyle: conditionals
20
23
 
21
24
  Style/CaseIndentation:
22
- IndentWhenRelativeTo: end
25
+ EnforcedStyle: end
23
26
 
24
27
  Style/DoubleNegation:
25
28
  Enabled: false
@@ -27,8 +30,27 @@ Style/DoubleNegation:
27
30
  Style/IndentArray:
28
31
  EnforcedStyle: consistent
29
32
 
33
+ Style/IndentHash:
34
+ EnforcedStyle: consistent
35
+
36
+ Style/IndentHeredoc:
37
+ Enabled: false
38
+
30
39
  Style/MultilineMethodCallIndentation:
31
40
  EnforcedStyle: indented
32
41
 
33
42
  Style/MultilineOperationIndentation:
34
43
  EnforcedStyle: indented
44
+
45
+ Style/SpaceInsideHashLiteralBraces:
46
+ EnforcedStyle: no_space
47
+
48
+ Metrics/BlockLength:
49
+ Exclude:
50
+ - '**/*_spec.rb'
51
+ - '**/*_examples.rb'
52
+ - '**/*.rake'
53
+
54
+ Metrics/ModuleLength:
55
+ Exclude:
56
+ - '**/*_spec.rb'
@@ -13,7 +13,7 @@ Metrics/AbcSize:
13
13
  # Offense count: 4
14
14
  # Configuration parameters: CountComments.
15
15
  Metrics/ClassLength:
16
- Max: 280
16
+ Max: 300
17
17
 
18
18
  # Offense count: 14
19
19
  Metrics/CyclomaticComplexity:
@@ -33,7 +33,7 @@ Metrics/MethodLength:
33
33
  # Offense count: 1
34
34
  # Configuration parameters: CountComments.
35
35
  Metrics/ModuleLength:
36
- Max: 172
36
+ Max: 180
37
37
 
38
38
  # Offense count: 14
39
39
  Metrics/PerceivedComplexity:
@@ -2,35 +2,52 @@ language: ruby
2
2
  sudo: false
3
3
  services:
4
4
  - mongodb
5
+ jdk:
6
+ - oraclejdk8
5
7
  rvm:
6
- - 2.2.5
7
- - 2.3.1
8
+ - 2.2.7
9
+ - 2.3.4
10
+ - 2.4.1
11
+ env:
12
+ global:
13
+ - TEST_CLUSTER_NODES=1
14
+ matrix:
15
+ - ES_VERSION=2.4.4
16
+ - ES_VERSION=5.4.0
8
17
  gemfile:
18
+ - gemfiles/rails.4.0.activerecord.gemfile
19
+ - gemfiles/rails.4.1.activerecord.gemfile
9
20
  - gemfiles/rails.4.2.activerecord.gemfile
10
- - gemfiles/rails.4.2.activerecord.kaminari.gemfile
11
- - gemfiles/rails.4.2.activerecord.will_paginate.gemfile
12
21
  - gemfiles/rails.5.0.activerecord.gemfile
13
- - gemfiles/rails.5.0.activerecord.kaminari.gemfile
14
- - gemfiles/rails.5.0.activerecord.will_paginate.gemfile
15
- - gemfiles/rails.4.2.mongoid.4.0.gemfile
16
- - gemfiles/rails.4.2.mongoid.4.0.kaminari.gemfile
17
- - gemfiles/rails.4.2.mongoid.4.0.will_paginate.gemfile
22
+ - gemfiles/rails.5.1.activerecord.gemfile
18
23
  - gemfiles/rails.4.2.mongoid.5.1.gemfile
19
- - gemfiles/rails.4.2.mongoid.5.1.kaminari.gemfile
20
- - gemfiles/rails.4.2.mongoid.5.1.will_paginate.gemfile
21
- - gemfiles/sequel.4.38.gemfile
24
+ - gemfiles/rails.5.0.mongoid.6.0.gemfile
25
+ - gemfiles/rails.5.1.mongoid.6.1.gemfile
26
+ - gemfiles/sequel.4.45.gemfile
22
27
  matrix:
23
- include:
24
- - rvm: 2.1
25
- gemfile: gemfiles/rails.3.2.activerecord.gemfile
26
- - rvm: 2.1
27
- gemfile: gemfiles/rails.3.2.activerecord.kaminari.gemfile
28
- - rvm: 2.1
29
- gemfile: gemfiles/rails.3.2.activerecord.will_paginate.gemfile
28
+ exclude:
29
+ - rvm: 2.2.7
30
+ env: ES_VERSION=5.4.0
31
+ - rvm: 2.3.4
32
+ env: ES_VERSION=2.4.4
33
+ - gemfile: gemfiles/rails.4.0.activerecord.gemfile
34
+ env: ES_VERSION=5.4.0
35
+ - gemfile: gemfiles/rails.4.1.activerecord.gemfile
36
+ env: ES_VERSION=5.4.0
37
+ - gemfile: gemfiles/rails.4.2.mongoid.5.1.gemfile
38
+ env: ES_VERSION=5.4.0
39
+ - gemfile: gemfiles/rails.5.1.mongoid.6.0.gemfile
40
+ env: ES_VERSION=5.4.0
41
+ - rvm: 2.4.1
42
+ gemfile: gemfiles/rails.4.0.activerecord.gemfile
43
+ - rvm: 2.4.1
44
+ gemfile: gemfiles/rails.4.1.activerecord.gemfile
30
45
  before_install:
31
- - curl -s https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.5.tar.gz | tar xz -C /tmp
46
+ - curl -s https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.4.4/elasticsearch-2.4.4.tar.gz | tar xz -C /tmp
47
+ - curl -s https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.0.tar.gz | tar xz -C /tmp
32
48
  before_script:
33
- - TEST_CLUSTER_COMMAND="/tmp/elasticsearch-1.7.5/bin/elasticsearch" rake es:start
49
+ - /tmp/elasticsearch-2.4.4/bin/plugin install delete-by-query
50
+ - TEST_CLUSTER_COMMAND=/tmp/elasticsearch-$ES_VERSION/bin/elasticsearch TEST_CLUSTER_LOGS=/tmp/log rake es:start
34
51
  script:
35
52
  - bundle exec rspec
36
53
  - bundle exec rubocop
@@ -0,0 +1,5 @@
1
+ --markup-provider=redcarpet
2
+ --markup=markdown
3
+ -
4
+ README.md
5
+ CHANGELOG.md
data/Appraisals CHANGED
@@ -1,51 +1,79 @@
1
- %w(3.2 4.2 5.0).each do |version|
2
- appraise "rails.#{version}.activerecord" do
3
- gem 'activerecord', "~> #{version}.0"
4
- gem 'activesupport', "~> #{version}.0"
5
- gem 'activejob', "~> #{version}.0" if version >= '4.2'
1
+ # rubocop:disable Style/FileName
2
+
3
+ %w[4.0 4.1 4.2].each do |activesupport|
4
+ appraise "rails.#{activesupport}.activerecord" do
5
+ gem 'activerecord', "~> #{activesupport}.0"
6
+ gem 'activesupport', "~> #{activesupport}.0"
7
+
8
+ gem 'activejob', "~> #{activesupport}.0" if activesupport >= '4.2'
6
9
  gem 'resque', require: false
10
+ gem 'shoryuken', require: false
7
11
  gem 'sidekiq', require: false
8
- end
9
12
 
10
- appraise "rails.#{version}.activerecord.kaminari" do
11
- gem 'activerecord', "~> #{version}.0"
12
- gem 'activesupport', "~> #{version}.0"
13
- gem 'activejob', "~> #{version}.0" if version >= '4.2'
14
- gem 'kaminari', '0.16.3', require: false
15
- end
16
-
17
- appraise "rails.#{version}.activerecord.will_paginate" do
18
- gem 'activerecord', "~> #{version}.0"
19
- gem 'activesupport', "~> #{version}.0"
20
- gem 'activejob', "~> #{version}.0" if version >= '4.2'
13
+ gem 'kaminari', '~> 0.17.0', require: false
21
14
  gem 'will_paginate', require: false
15
+
16
+ gem 'parallel', require: false
22
17
  end
23
18
  end
24
19
 
25
- { '4.0' => '4.2', '5.1' => '4.2' }.each do |(mongoid, activesupport)|
26
- appraise "rails.#{activesupport}.mongoid.#{mongoid}" do
27
- gem 'mongoid', "~> #{mongoid}.0"
20
+ %w[5.0 5.1].each do |activesupport|
21
+ appraise "rails.#{activesupport}.activerecord" do
22
+ gem 'activerecord', "~> #{activesupport}.0"
28
23
  gem 'activesupport', "~> #{activesupport}.0"
24
+
25
+ gem 'activejob', "~> #{activesupport}.0"
29
26
  gem 'resque', require: false
27
+ gem 'shoryuken', require: false
30
28
  gem 'sidekiq', require: false
31
- end
32
29
 
33
- appraise "rails.#{activesupport}.mongoid.#{mongoid}.kaminari" do
34
- gem 'mongoid', "~> #{mongoid}.0"
35
- gem 'activesupport', "~> #{activesupport}.0"
36
- gem 'kaminari', '0.16.3', require: false
30
+ gem 'kaminari-core', '~> 1.0.0', require: false
31
+ gem 'will_paginate', require: false
32
+
33
+ gem 'parallel', require: false
37
34
  end
35
+ end
36
+
37
+ appraise 'rails.4.2.mongoid.5.1' do
38
+ gem 'mongoid', '~> 5.1.0'
39
+ gem 'activesupport', '~> 4.2.0'
40
+
41
+ gem 'activejob', '~> 4.2.0'
42
+ gem 'resque', require: false
43
+ gem 'shoryuken', require: false
44
+ gem 'sidekiq', require: false
45
+
46
+ gem 'kaminari', '~> 0.17.0', require: false
47
+ gem 'will_paginate', require: false
38
48
 
39
- appraise "rails.#{activesupport}.mongoid.#{mongoid}.will_paginate" do
49
+ gem 'parallel', require: false
50
+ end
51
+
52
+ {'5.0' => '6.0', '5.1' => '6.1'}.each do |activesupport, mongoid|
53
+ appraise "rails.#{activesupport}.mongoid.#{mongoid}" do
40
54
  gem 'mongoid', "~> #{mongoid}.0"
41
55
  gem 'activesupport', "~> #{activesupport}.0"
56
+
57
+ gem 'activejob', "~> #{activesupport}.0"
58
+ gem 'resque', require: false
59
+ gem 'shoryuken', require: false
60
+ gem 'sidekiq', require: false
61
+
62
+ gem 'kaminari-core', '~> 1.0.0', require: false
42
63
  gem 'will_paginate', require: false
64
+
65
+ gem 'parallel', require: false
43
66
  end
44
67
  end
45
68
 
46
- %w(4.38).each do |sequel|
69
+ %w[4.45].each do |sequel|
47
70
  appraise "sequel.#{sequel}" do
48
71
  gem 'sequel', "~> #{sequel}.0"
49
72
  gem 'activesupport', '~> 5.0.0'
73
+
74
+ gem 'kaminari-core', '~> 1.0.0', require: false
75
+ gem 'will_paginate', require: false
76
+
77
+ gem 'parallel', require: false
50
78
  end
51
79
  end
@@ -1,5 +1,50 @@
1
1
  # master
2
2
 
3
+ ## Breaking changes
4
+
5
+ * Changed behavior of `Chewy::Index.index_name`, it doesn't cache the values anymore.
6
+
7
+ * Journal interfaces, related code and rake tasks were completely refactored and are not compatible with the previous version.
8
+
9
+ ## Changes
10
+
11
+ * Parallel import and rake tasks.
12
+
13
+ * `:shoryuken` async strategy (@josephchoe, #532)
14
+
15
+ * Deprecate `Chewy::Index.build_index_name`.
16
+
17
+ * Rename `Chewy::Index.default_prefix` to `Chewy::Index.prefix`. The old one is deprecated.
18
+
19
+ * Add `Chewy::Type.derivable_name` for consistency.
20
+
21
+ * Rename `Chewy::Index.derivable_index_name` to `Chewy::Index.derivable_name`.
22
+ `Chewy::Index.derivable_index_name` and `Chewy::Type.derivable_index_name` are deprecated.
23
+
24
+ * Use normal YAML loading, for the config, we don't need the safe one.
25
+
26
+ * `default_root_options` option (@barthez, #526)
27
+
28
+ * Partial indexing ability: it is possible to update only specified fields.
29
+
30
+ * New cool `rake chewy:deploy` task.
31
+
32
+ * Selective reset (resets only if necessary): `rake chewy:upgrade`.
33
+
34
+ * Consistency checks and synchronization: `rake chewy:sync`.
35
+
36
+ * Brand new request DSL. Supports ElasticSearch 2 and 5, better usability, architecture and docs.
37
+
38
+ * Add Kaminari 1.0 support.
39
+
40
+ * `skip_index_creation_on_import` option (@sergey-kintsel, #483)
41
+
42
+ * Ability to use procs for settings (@parallel588, #481)
43
+
44
+ * Bulk indexing optimizations with new additional options (@eproulx-petalmd, #467)
45
+
46
+ * Configurable sidekiq options (@averell23, #438)
47
+
3
48
  # Version 0.9.0
4
49
 
5
50
  ## Changes
@@ -14,7 +59,7 @@
14
59
 
15
60
  * Minitest helpers (@robacarp, #396)
16
61
 
17
- * `Chewy::Query#unlimited` to fetch all the records (@sergey-kintsel, #393)
62
+ * `Chewy::Query#unlimited` to fetch all the documents (@sergey-kintsel, #393)
18
63
 
19
64
  * `Chewy::Query#exists?` (@sergey-kintsel, #386)
20
65
 
@@ -84,6 +129,12 @@
84
129
 
85
130
  # Version 0.8.3
86
131
 
132
+ ## Breaking changes:
133
+
134
+ * `Chewy.atomic` and `Chewy.urgent_update=` methods was removed from the codebase, use `Chewy.strategy` block instead.
135
+
136
+ * `delete_from_index?` hook is removed from the codebase.
137
+
87
138
  ## Changes
88
139
 
89
140
  * Sequel support completely reworked to use common ORM implementations + better sequel specs covarage.
@@ -100,12 +151,6 @@
100
151
 
101
152
  * Correct custom assets path silencer (@davekaro)
102
153
 
103
- ## Incompatible changes:
104
-
105
- * `Chewy.atomic` and `Chewy.urgent_update=` methods was removed from the codebase, use `Chewy.strategy` block instead.
106
-
107
- * `delete_from_index?` hook is removed from the codebase.
108
-
109
154
  # Version 0.8.2
110
155
 
111
156
  ## Changes
@@ -141,7 +186,7 @@
141
186
 
142
187
  # Version 0.8.0
143
188
 
144
- ## Incompatible changes:
189
+ ## Breaking changes:
145
190
 
146
191
  * `:atomic` and `:urgent` strategies are using `import!` method raising exceptions
147
192
 
@@ -167,7 +212,7 @@
167
212
 
168
213
  # Version 0.7.0
169
214
 
170
- ## Incompatible changes:
215
+ ## Breaking changes:
171
216
 
172
217
  * `Chewy.use_after_commit_callbacks = false` returns previous RDBMS behavior
173
218
  in tests
@@ -296,7 +341,7 @@
296
341
 
297
342
  * `min_score` query option support (@jshirley)
298
343
 
299
- * `Chewy::Query#find` method for finding records by id
344
+ * `Chewy::Query#find` method for finding documents by id
300
345
 
301
346
  # Version 0.6.0
302
347
 
@@ -316,7 +361,7 @@
316
361
 
317
362
  # Version 0.5.2
318
363
 
319
- ## Incompatible changes:
364
+ ## Breaking changes:
320
365
 
321
366
  * `Chewy::Type::Base` removed in favour of using `Chewy::Type` as a base class for all types
322
367
 
@@ -356,7 +401,7 @@
356
401
 
357
402
  # Version 0.5.0
358
403
 
359
- ## Incompatible changes:
404
+ ## Breaking changes:
360
405
 
361
406
  * 404 exception (IndexMissingException) while query is swallowed and treated like an empty result set.
362
407
 
data/Gemfile CHANGED
@@ -6,15 +6,19 @@ gem 'activerecord'
6
6
  # gem 'mongoid'
7
7
  # gem 'sequel'
8
8
 
9
- # gem 'kaminari', require: false
10
- # gem 'will_paginate', require: false
9
+ gem 'activejob', require: false
10
+ gem 'resque', require: false
11
+ gem 'shoryuken', require: false
12
+ gem 'sidekiq', require: false
11
13
 
12
- # gem 'resque', require: false
13
- # gem 'sidekiq', require: false
14
- # gem 'activejob', require: false
14
+ gem 'kaminari-core', require: false
15
+ gem 'will_paginate', require: false
15
16
 
16
- group :test do
17
- gem 'guard'
18
- gem 'guard-rspec'
19
- gem 'listen', '~> 3.0.0'
20
- end
17
+ gem 'parallel', require: false
18
+ gem 'ruby-progressbar', require: false
19
+
20
+ gem 'guard'
21
+ gem 'guard-rspec'
22
+
23
+ gem 'redcarpet'
24
+ gem 'yard'
@@ -0,0 +1,497 @@
1
+ # Previous DSL readme.
2
+
3
+ See `Chewy::Query` for details.
4
+
5
+ * [Index querying](#index-querying)
6
+ * [Additional query action.](#additional-query-action)
7
+ * [Filters query DSL](#filters-query-dsl)
8
+ * [Faceting](#faceting)
9
+ * [Aggregations](#aggregations)
10
+ * [Script fields](#script-fields)
11
+ * [Script scoring](#script-scoring)
12
+ * [Boost Factor](#boost-factor)
13
+ * [Objects loading](#objects-loading)
14
+
15
+ ## Index querying
16
+
17
+ ```ruby
18
+ scope = UsersIndex.query(term: {name: 'foo'})
19
+ .filter(range: {rating: {gte: 100}})
20
+ .order(created: :desc)
21
+ .limit(20).offset(100)
22
+
23
+ scope.to_a # => will produce array of UserIndex::User or other types instances
24
+ scope.map { |user| user.email }
25
+ scope.total_count # => will return total objects count
26
+
27
+ scope.per(10).page(3) # supports kaminari pagination
28
+ scope.explain.map { |user| user._explanation }
29
+ scope.only(:id, :email) # returns ids and emails only
30
+
31
+ scope.merge(other_scope) # queries could be merged
32
+ ```
33
+
34
+ Also, queries can be performed on a type individually:
35
+
36
+ ```ruby
37
+ UsersIndex::User.filter(term: {name: 'foo'}) # will return UserIndex::User collection only
38
+ ```
39
+
40
+ If you are performing more than one `filter` or `query` in the chain, all the filters and queries will be concatenated in the way specified by
41
+ `filter_mode` and `query_mode` respectively.
42
+
43
+ The default `filter_mode` is `:and` and the default `query_mode` is `bool`.
44
+
45
+ Available filter modes are: `:and`, `:or`, `:must`, `:should` and any minimum_should_match-acceptable value
46
+
47
+ Available query modes are: `:must`, `:should`, `:dis_max`, any minimum_should_match-acceptable value or float value for dis_max query with tie_breaker specified.
48
+
49
+ ```ruby
50
+ UsersIndex::User.filter{ name == 'Fred' }.filter{ age < 42 } # will be wrapped with `and` filter
51
+ UsersIndex::User.filter{ name == 'Fred' }.filter{ age < 42 }.filter_mode(:should) # will be wrapped with bool `should` filter
52
+ UsersIndex::User.filter{ name == 'Fred' }.filter{ age < 42 }.filter_mode('75%') # will be wrapped with bool `should` filter with `minimum_should_match: '75%'`
53
+ ```
54
+
55
+ See [query.rb](lib/chewy/query.rb) for more details.
56
+
57
+ ## Additional query action.
58
+
59
+ You may also perform additional actions on the query scope, such as deleting of all the scope documents:
60
+
61
+ ```ruby
62
+ UsersIndex.delete_all
63
+ UsersIndex::User.delete_all
64
+ UsersIndex.filter{ age < 42 }.delete_all
65
+ UsersIndex::User.filter{ age < 42 }.delete_all
66
+ ```
67
+
68
+ ## Filters query DSL
69
+
70
+ There is a test version of the filter-creating DSL:
71
+
72
+ ```ruby
73
+ UsersIndex.filter{ name == 'Fred' } # will produce `term` filter.
74
+ UsersIndex.filter{ age <= 42 } # will produce `range` filter.
75
+ ```
76
+
77
+ The basis of the DSL is the expression. There are 2 types of expressions:
78
+
79
+ * Simple function
80
+
81
+ ```ruby
82
+ UsersIndex.filter{ s('doc["num"] > 1') } # script expression
83
+ UsersIndex.filter{ q(query_string: {query: 'lazy fox'}) } # query expression
84
+ ```
85
+
86
+ * Field-dependent composite expression
87
+ Consists of the field name (with or without dot notation), a value, and an action operator between them. The field name might take additional options for passing to the resulting expression.
88
+
89
+ ```ruby
90
+ UsersIndex.filter{ name == 'Name' } # simple field term filter
91
+ UsersIndex.filter{ name(:bool) == ['Name1', 'Name2'] } # terms query with `execution: :bool` option passed
92
+ UsersIndex.filter{ answers.title =~ /regexp/ } # regexp filter for `answers.title` field
93
+ ```
94
+
95
+ You can combine expressions as you wish with the help of combination operators.
96
+
97
+ ```ruby
98
+ UsersIndex.filter{ (name == 'Name') & (email == 'Email') } # combination produces `and` filter
99
+ UsersIndex.filter{
100
+ must(
101
+ should(name =~ 'Fr').should_not(name == 'Fred') & (age == 42), email =~ /gmail\.com/
102
+ ) | ((roles.admin == true) & name?)
103
+ } # many of the combination possibilities
104
+ ```
105
+
106
+ There is also a special syntax for cache enabling:
107
+
108
+ ```ruby
109
+ UsersIndex.filter{ ~name == 'Name' } # you can apply tilde to the field name
110
+ UsersIndex.filter{ ~(name == 'Name') } # or to the whole expression
111
+
112
+ # if you are applying cache to the one part of range filter
113
+ # the whole filter will be cached:
114
+ UsersIndex.filter{ ~(age > 42) & (age <= 50) }
115
+
116
+ # You can pass cache options as a field option also.
117
+ UsersIndex.filter{ name(cache: true) == 'Name' }
118
+ UsersIndex.filter{ name(cache: false) == 'Name' }
119
+
120
+ # With regexp filter you can pass _cache_key
121
+ UsersIndex.filter{ name(cache: 'name_regexp') =~ /Name/ }
122
+ # Or not
123
+ UsersIndex.filter{ name(cache: true) =~ /Name/ }
124
+ ```
125
+
126
+ Compliance cheatsheet for filters and DSL expressions:
127
+
128
+ * Term filter
129
+
130
+ ```json
131
+ {"term": {"name": "Fred"}}
132
+ {"not": {"term": {"name": "Johny"}}}
133
+ ```
134
+
135
+ ```ruby
136
+ UsersIndex.filter{ name == 'Fred' }
137
+ UsersIndex.filter{ name != 'Johny' }
138
+ ```
139
+
140
+ * Terms filter
141
+
142
+ ```json
143
+ {"terms": {"name": ["Fred", "Johny"]}}
144
+ {"not": {"terms": {"name": ["Fred", "Johny"]}}}
145
+
146
+ {"terms": {"name": ["Fred", "Johny"], "execution": "or"}}
147
+
148
+ {"terms": {"name": ["Fred", "Johny"], "execution": "and"}}
149
+
150
+ {"terms": {"name": ["Fred", "Johny"], "execution": "bool"}}
151
+
152
+ {"terms": {"name": ["Fred", "Johny"], "execution": "fielddata"}}
153
+ ```
154
+
155
+ ```ruby
156
+ UsersIndex.filter{ name == ['Fred', 'Johny'] }
157
+ UsersIndex.filter{ name != ['Fred', 'Johny'] }
158
+
159
+ UsersIndex.filter{ name(:|) == ['Fred', 'Johny'] }
160
+ UsersIndex.filter{ name(:or) == ['Fred', 'Johny'] }
161
+ UsersIndex.filter{ name(execution: :or) == ['Fred', 'Johny'] }
162
+
163
+ UsersIndex.filter{ name(:&) == ['Fred', 'Johny'] }
164
+ UsersIndex.filter{ name(:and) == ['Fred', 'Johny'] }
165
+ UsersIndex.filter{ name(execution: :and) == ['Fred', 'Johny'] }
166
+
167
+ UsersIndex.filter{ name(:b) == ['Fred', 'Johny'] }
168
+ UsersIndex.filter{ name(:bool) == ['Fred', 'Johny'] }
169
+ UsersIndex.filter{ name(execution: :bool) == ['Fred', 'Johny'] }
170
+
171
+ UsersIndex.filter{ name(:f) == ['Fred', 'Johny'] }
172
+ UsersIndex.filter{ name(:fielddata) == ['Fred', 'Johny'] }
173
+ UsersIndex.filter{ name(execution: :fielddata) == ['Fred', 'Johny'] }
174
+ ```
175
+
176
+ * Regexp filter (== and =~ are equivalent)
177
+
178
+ ```json
179
+ {"regexp": {"name.first": "s.*y"}}
180
+
181
+ {"not": {"regexp": {"name.first": "s.*y"}}}
182
+
183
+ {"regexp": {"name.first": {"value": "s.*y", "flags": "ANYSTRING|INTERSECTION"}}}
184
+ ```
185
+
186
+ ```ruby
187
+ UsersIndex.filter{ name.first == /s.*y/ }
188
+ UsersIndex.filter{ name.first =~ /s.*y/ }
189
+
190
+ UsersIndex.filter{ name.first != /s.*y/ }
191
+ UsersIndex.filter{ name.first !~ /s.*y/ }
192
+
193
+ UsersIndex.filter{ name.first(:anystring, :intersection) == /s.*y/ }
194
+ UsersIndex.filter{ name.first(flags: [:anystring, :intersection]) == /s.*y/ }
195
+ ```
196
+
197
+ * Prefix filter
198
+
199
+ ```json
200
+ {"prefix": {"name": "Fre"}}
201
+ {"not": {"prefix": {"name": "Joh"}}}
202
+ ```
203
+
204
+ ```ruby
205
+ UsersIndex.filter{ name =~ re' }
206
+ UsersIndex.filter{ name !~ 'Joh' }
207
+ ```
208
+
209
+ * Exists filter
210
+
211
+ ```json
212
+ {"exists": {"field": "name"}}
213
+ ```
214
+
215
+ ```ruby
216
+ UsersIndex.filter{ name? }
217
+ UsersIndex.filter{ !!name }
218
+ UsersIndex.filter{ !!name? }
219
+ UsersIndex.filter{ name != nil }
220
+ UsersIndex.filter{ !(name == nil) }
221
+ ```
222
+
223
+ * Missing filter
224
+
225
+ ```json
226
+ {"missing": {"field": "name", "existence": true, "null_value": false}}
227
+ {"missing": {"field": "name", "existence": true, "null_value": true}}
228
+ {"missing": {"field": "name", "existence": false, "null_value": true}}
229
+ ```
230
+
231
+ ```ruby
232
+ UsersIndex.filter{ !name }
233
+ UsersIndex.filter{ !name? }
234
+ UsersIndex.filter{ name == nil }
235
+ ```
236
+
237
+ * Range
238
+
239
+ ```json
240
+ {"range": {"age": {"gt": 42}}}
241
+ {"range": {"age": {"gte": 42}}}
242
+ {"range": {"age": {"lt": 42}}}
243
+ {"range": {"age": {"lte": 42}}}
244
+
245
+ {"range": {"age": {"gt": 40, "lt": 50}}}
246
+ {"range": {"age": {"gte": 40, "lte": 50}}}
247
+
248
+ {"range": {"age": {"gt": 40, "lte": 50}}}
249
+ {"range": {"age": {"gte": 40, "lt": 50}}}
250
+ ```
251
+
252
+ ```ruby
253
+ UsersIndex.filter{ age > 42 }
254
+ UsersIndex.filter{ age >= 42 }
255
+ UsersIndex.filter{ age < 42 }
256
+ UsersIndex.filter{ age <= 42 }
257
+
258
+ UsersIndex.filter{ age == (40..50) }
259
+ UsersIndex.filter{ (age > 40) & (age < 50) }
260
+ UsersIndex.filter{ age == [40..50] }
261
+ UsersIndex.filter{ (age >= 40) & (age <= 50) }
262
+
263
+ UsersIndex.filter{ (age > 40) & (age <= 50) }
264
+ UsersIndex.filter{ (age >= 40) & (age < 50) }
265
+ ```
266
+
267
+ * Bool filter
268
+
269
+ ```json
270
+ {"bool": {
271
+ "must": [{"term": {"name": "Name"}}],
272
+ "should": [{"term": {"age": 42}}, {"term": {"age": 45}}]
273
+ }}
274
+ ```
275
+
276
+ ```ruby
277
+ UsersIndex.filter{ must(name == 'Name').should(age == 42, age == 45) }
278
+ ```
279
+
280
+ * And filter
281
+
282
+ ```json
283
+ {"and": [{"term": {"name": "Name"}}, {"range": {"age": {"lt": 42}}}]}
284
+ ```
285
+
286
+ ```ruby
287
+ UsersIndex.filter{ (name == 'Name') & (age < 42) }
288
+ ```
289
+
290
+ * Or filter
291
+
292
+ ```json
293
+ {"or": [{"term": {"name": "Name"}}, {"range": {"age": {"lt": 42}}}]}
294
+ ```
295
+
296
+ ```ruby
297
+ UsersIndex.filter{ (name == 'Name') | (age < 42) }
298
+ ```
299
+
300
+ ```json
301
+ {"not": {"term": {"name": "Name"}}}
302
+ {"not": {"range": {"age": {"lt": 42}}}}
303
+ ```
304
+
305
+ ```ruby
306
+ UsersIndex.filter{ !(name == 'Name') } # or UsersIndex.filter{ name != 'Name' }
307
+ UsersIndex.filter{ !(age < 42) }
308
+ ```
309
+
310
+ * Match all filter
311
+
312
+ ```json
313
+ {"match_all": {}}
314
+ ```
315
+
316
+ ```ruby
317
+ UsersIndex.filter{ match_all }
318
+ ```
319
+
320
+ * Has child filter
321
+
322
+ ```json
323
+ {"has_child": {"type": "blog_tag", "query": {"term": {"tag": "something"}}}
324
+ {"has_child": {"type": "comment", "filter": {"term": {"user": "john"}}}
325
+ ```
326
+
327
+ ```ruby
328
+ UsersIndex.filter{ has_child(:blog_tag).query(term: {tag: 'something'}) }
329
+ UsersIndex.filter{ has_child(:comment).filter{ user == 'john' } }
330
+ ```
331
+
332
+ * Has parent filter
333
+
334
+ ```json
335
+ {"has_parent": {"type": "blog", "query": {"term": {"tag": "something"}}}}
336
+ {"has_parent": {"type": "blog", "filter": {"term": {"text": "bonsai three"}}}}
337
+ ```
338
+
339
+ ```ruby
340
+ UsersIndex.filter{ has_parent(:blog).query(term: {tag: 'something'}) }
341
+ UsersIndex.filter{ has_parent(:blog).filter{ text == 'bonsai three' } }
342
+ ```
343
+
344
+ See [filters.rb](lib/chewy/query/filters.rb) for more details.
345
+
346
+ ## Faceting
347
+
348
+ Facets are an optional sidechannel you can request from Elasticsearch describing certain fields of the resulting collection. The most common use for facets is to allow the user to continue filtering specifically within the subset, as opposed to the global index.
349
+
350
+ For instance, let's request the `country` field as a facet along with our users collection. We can do this with the #facets method like so:
351
+
352
+ ```ruby
353
+ UsersIndex.filter{ [...] }.facets({countries: {terms: {field: 'country'}}})
354
+ ```
355
+
356
+ Let's look at what we asked from Elasticsearch. The facets setter method accepts a hash. You can choose custom/semantic key names for this hash for your own convenience (in this case I used the plural version of the actual field), in our case `countries`. The following nested hash tells ES to grab and aggregate values (terms) from the `country` field on our indexed records.
357
+
358
+ The response will include the `:facets` sidechannel:
359
+
360
+ ```
361
+ < { ... ,"facets":{"countries":{"_type":"terms","missing":?,"total":?,"other":?,"terms":[{"term":"USA","count":?},{"term":"Brazil","count":?}, ...}}
362
+ ```
363
+
364
+ ## Aggregations
365
+
366
+ Aggregations are part of the optional sidechannel that can be requested with a query.
367
+
368
+ You interact with aggregations using the composable #aggregations method (or its alias #aggs)
369
+
370
+ Let's look at an example.
371
+
372
+ ```ruby
373
+ class UsersIndex < Chewy::Index
374
+ define_type User do
375
+ field :name
376
+ field :rating
377
+ end
378
+ end
379
+
380
+ all_johns = UsersIndex::User.filter { name == 'john' }.aggs({ avg_rating: { avg: { field: 'rating' } } })
381
+
382
+ avg_johns_rating = all_johns.aggs
383
+ # => {"avg_rating"=>{"value"=>3.5}}
384
+ ```
385
+
386
+ It is convenient to name aggregations that you intend to reuse regularly. This is achieve with the .aggregation method,
387
+ which is also available under the .agg alias method.
388
+
389
+ Here's the same example from before
390
+
391
+ ```ruby
392
+ class UsersIndex < Chewy::Index
393
+ define_type User do
394
+ field :name
395
+ field :rating, type: "long"
396
+ agg :avg_rating do
397
+ { avg: { field: 'rating' } }
398
+ end
399
+ end
400
+ end
401
+
402
+ all_johns = UsersIndex::User.filter { name == 'john' }.aggs(:avg_rating)
403
+
404
+ avg_johns_rating = all_johns.aggs
405
+ # => {"avg_rating"=>{"value"=>3.5}}
406
+ ```
407
+
408
+ It is possible to run into collisions between named aggregations. This occurs when there is more than one aggregation
409
+ with the same name. To explicitly reference an aggregation you provide a string to the #aggs method of the form:
410
+ `index_name#document_type.aggregation_name`
411
+
412
+ Consider this example where there are two separate aggregations named `avg_rating`
413
+
414
+ ```ruby
415
+ class UsersIndex < Chewy::Index
416
+ define_type User do
417
+ field :name
418
+ field :rating, type: "long"
419
+ agg :avg_rating do
420
+ { avg: { field: 'rating' } }
421
+ end
422
+ end
423
+ define_type Post do
424
+ field :title
425
+ field :body
426
+ field :comments do
427
+ field :message
428
+ field :rating, type: "long"
429
+ end
430
+ agg :avg_rating do
431
+ { avg: { field: 'comments.rating' } }
432
+ end
433
+ end
434
+ end
435
+
436
+ all_docs = UsersIndex.filter {match_all}.aggs("users#user.avg_rating")
437
+ all_docs.aggs
438
+ # => {"users#user.avg_rating"=>{"value"=>3.5}}
439
+ ```
440
+
441
+ ## Script fields
442
+
443
+ Script fields allow you to execute Elasticsearch's scripting languages such as groovy and javascript. More about supported languages and what scripting is [here](https://www.elastic.co/guide/en/elasticsearch/reference/0.90/modules-scripting.html). This feature allows you to calculate the distance between geo points, for example. This is how to use the DSL:
444
+
445
+ ```ruby
446
+ UsersIndex.script_fields(
447
+ distance: {
448
+ params: {
449
+ lat: 37.569976,
450
+ lon: -122.351591
451
+ },
452
+ script: "doc['coordinates'].distanceInMiles(lat, lon)"
453
+ }
454
+ )
455
+ ```
456
+ Here, `coordinates` is a field with type `geo_point`. There will be a `distance` field for the index's model in the search result.
457
+
458
+ ## Script scoring
459
+
460
+ Script scoring is used to score the search results. All scores are added to the search request and combined according to boost mode and score mode. This can be useful if, for example, a score function is computationally expensive and it is sufficient to compute the score on a filtered set of documents. For example, you might want to multiply the score by another numeric field in the doc:
461
+
462
+ ```ruby
463
+ UsersIndex.script_score("_score * doc['my_numeric_field'].value")
464
+ ```
465
+
466
+ ## Boost Factor
467
+
468
+ Boost factors are a way to add a boost to a query where documents match the filter. If you have some users who are experts and some who are regular users, you might want to give the experts a higher score and boost to the top of the search results. You can accomplish this by using the #boost_factor method and adding a boost score of 5 for an expert user:
469
+
470
+ ```ruby
471
+ UsersIndex.boost_factor(5, filter: {term: {type: 'Expert'}})
472
+ ```
473
+
474
+ ## Objects loading
475
+
476
+ It is possible to load source objects from the database for every search result:
477
+
478
+ ```ruby
479
+ scope = UsersIndex.filter(range: {rating: {gte: 100}})
480
+
481
+ scope.load # => scope is marked to return User instances array
482
+ scope.load.query(...) # => since objects are loaded lazily you can complete scope
483
+ scope.load(user: { scope: ->{ includes(:country) }}) # you can also pass loading scopes for each
484
+ # possibly returned type
485
+ scope.load(user: { scope: User.includes(:country) }) # the second scope passing way.
486
+ scope.load(scope: ->{ includes(:country) }) # and more common scope applied to every loaded object type.
487
+
488
+ scope.only(:id).load # it is optimal to request ids only if you are not planning to use type objects
489
+ ```
490
+
491
+ The `preload` method takes the same options as `load` and ORM/ODM objects will be loaded, but the scope will still return an array of Chewy wrappers. To access real objects use the `_object` wrapper method:
492
+
493
+ ```ruby
494
+ UsersIndex.filter(range: {rating: {gte: 100}}).preload(...).query(...).map(&:_object)
495
+ ```
496
+
497
+ See [loading.rb](lib/chewy/query/loading.rb) for more details.