searchkick 2.2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 85108ff6dc90bd7075f66c5627fc06eba581657f
4
- data.tar.gz: 062420bd6cd4c9601026425d40923cc82e649364
3
+ metadata.gz: e592f63efa26867238f106cdede925736897c39e
4
+ data.tar.gz: b873c66a18f69cffcd9227fe92a1cf314e602090
5
5
  SHA512:
6
- metadata.gz: 680ef536ba5e15456b0df70412eec5e47d13f43424c02e7d039921abf3c83b06fbaefa95d824fa2ae0efeecde8c6488ad56b4aabed442eb6c191a309f2204c6c
7
- data.tar.gz: d118d331ffd37c1fbec228bba2cc043f03730510a0ca45d7bd9afe9c04aa31a8ebeeaba82b57113c070fd7af3b1c8c347f0b22bd8cff43565f9246ed408a0c77
6
+ metadata.gz: 74566048b5471575f1c7f2e269a6fa23fa62dbbd717696a077a26875f43883be128cbbb731578634ec948c51a5e9d336ed3595ea631717ac3056f784c813f19c
7
+ data.tar.gz: 5c1a40b9633f70201a13e003a1852d5a3cfcf0d16d23024cea19ddce523b2f32e5675119e5899b1b4c3e7f057466cd09a80a788a655933923a78172b5b95ebb0
data/.travis.yml CHANGED
@@ -19,7 +19,7 @@ gemfile:
19
19
  - test/gemfiles/mongoid5.gemfile
20
20
  - test/gemfiles/mongoid6.gemfile
21
21
  env:
22
- - ELASTICSEARCH_VERSION=5.2.0
22
+ - ELASTICSEARCH_VERSION=5.3.0
23
23
  jdk: oraclejdk8
24
24
  matrix:
25
25
  include:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 2.2.1
2
+
3
+ - Added `avg`, `cardinality`, `max`, `min`, and `sum` aggregations
4
+ - Added `load: {dumpable: true}` option
5
+ - Added `index_suffix` option
6
+ - Accept string for `exclude` option
7
+
1
8
  ## 2.2.0
2
9
 
3
10
  - Fixed bug with text values longer than 256 characters and `_all` field - see [#850](https://github.com/ankane/searchkick/issues/850)
data/README.md CHANGED
@@ -294,13 +294,17 @@ end
294
294
  ```ruby
295
295
  class Product < ActiveRecord::Base
296
296
  searchkick synonyms: [["scallion", "green onion"], ["qtip", "cotton swab"]]
297
- # or
298
- # searchkick synonyms: -> { CSV.read("/some/path/synonyms.csv") }
299
297
  end
300
298
  ```
301
299
 
302
300
  Call `Product.reindex` after changing synonyms.
303
301
 
302
+ To read synonyms from a file, use:
303
+
304
+ ```ruby
305
+ synonyms: -> { CSV.read("/some/path/synonyms.csv") }
306
+ ```
307
+
304
308
  For directional synonyms, use:
305
309
 
306
310
  ```ruby
@@ -388,7 +392,7 @@ You can map queries and terms to exclude with:
388
392
  ```ruby
389
393
  exclude_queries = {
390
394
  "butter" => ["peanut butter"],
391
- "cream" => ["ice cream"]
395
+ "cream" => ["ice cream", "whipped cream"]
392
396
  }
393
397
 
394
398
  Product.search query, exclude: exclude_queries[query]
@@ -1766,6 +1770,14 @@ product = FactoryGirl.create(:product)
1766
1770
  product.reindex(refresh: true)
1767
1771
  ```
1768
1772
 
1773
+ ### Parallel Tests
1774
+
1775
+ Set:
1776
+
1777
+ ```ruby
1778
+ Searchkick.index_suffix = ENV["TEST_ENV_NUMBER"]
1779
+ ```
1780
+
1769
1781
  ## Multi-Tenancy
1770
1782
 
1771
1783
  Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenancy-with-searchkick/) on the [Apartment](https://github.com/influitive/apartment) gem. Follow a similar pattern if you use another gem.
data/Rakefile CHANGED
@@ -1,6 +1,13 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
+ begin
5
+ require "parallel_tests/tasks"
6
+ require "shellwords"
7
+ rescue LoadError
8
+ # do nothing
9
+ end
10
+
4
11
  task default: :test
5
12
  Rake::TestTask.new do |t|
6
13
  t.libs << "test"
data/lib/searchkick.rb CHANGED
@@ -36,7 +36,7 @@ module Searchkick
36
36
  class ImportError < Error; end
37
37
 
38
38
  class << self
39
- attr_accessor :search_method_name, :wordnet_path, :timeout, :models, :client_options, :redis
39
+ attr_accessor :search_method_name, :wordnet_path, :timeout, :models, :client_options, :redis, :index_suffix
40
40
  attr_writer :client, :env, :search_timeout
41
41
  attr_reader :aws_credentials
42
42
  end
@@ -21,8 +21,8 @@ module Searchkick
21
21
  class_variable_set :@@searchkick_klass, self
22
22
  class_variable_set :@@searchkick_callbacks, callbacks
23
23
  class_variable_set :@@searchkick_index, options[:index_name] ||
24
- (options[:index_prefix].respond_to?(:call) && proc { [options[:index_prefix].call, model_name.plural, Searchkick.env].compact.join("_") }) ||
25
- [options[:index_prefix], model_name.plural, Searchkick.env].compact.join("_")
24
+ (options[:index_prefix].respond_to?(:call) && proc { [options[:index_prefix].call, model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_") }) ||
25
+ [options[:index_prefix], model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_")
26
26
 
27
27
  class << self
28
28
  def searchkick_search(term = "*", **options, &block)
@@ -2,6 +2,8 @@ module Searchkick
2
2
  class Query
3
3
  extend Forwardable
4
4
 
5
+ @@metric_aggs = [:avg, :cardinality, :max, :min, :sum]
6
+
5
7
  attr_reader :klass, :term, :options
6
8
  attr_accessor :body
7
9
 
@@ -328,7 +330,7 @@ module Searchkick
328
330
 
329
331
  if options[:exclude]
330
332
  must_not =
331
- options[:exclude].map do |phrase|
333
+ Array(options[:exclude]).map do |phrase|
332
334
  {
333
335
  match_phrase: {
334
336
  exclude_field => {
@@ -643,6 +645,12 @@ module Searchkick
643
645
  interval: interval
644
646
  }
645
647
  }
648
+ elsif metric = @@metric_aggs.find { |k| agg_options.has_key?(k) }
649
+ payload[:aggs][field] = {
650
+ metric => {
651
+ field: agg_options[metric][:field] || field
652
+ }
653
+ }
646
654
  else
647
655
  payload[:aggs][field] = {
648
656
  terms: {
@@ -33,7 +33,7 @@ module Searchkick
33
33
  # sort
34
34
  hits.map do |hit|
35
35
  result = results[hit["_type"]][hit["_id"].to_s]
36
- if result
36
+ if result && !(options[:load].is_a?(Hash) && options[:load][:dumpable])
37
37
  unless result.respond_to?(:search_hit)
38
38
  result.define_singleton_method(:search_hit) do
39
39
  hit
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "2.2.0"
2
+ VERSION = "2.2.1"
3
3
  end
data/test/aggs_test.rb CHANGED
@@ -116,6 +116,68 @@ class AggsTest < Minitest::Test
116
116
  assert_equal 4, products.aggs["products_per_year"]["buckets"].size
117
117
  end
118
118
 
119
+ def test_aggs_avg
120
+ products =
121
+ Product.search("*", {
122
+ aggs: {
123
+ avg_price: {
124
+ avg: {
125
+ field: :price
126
+ }
127
+ }
128
+ }
129
+ })
130
+ assert_equal 16.5, products.aggs["avg_price"]["value"]
131
+ end
132
+
133
+ def test_aggs_cardinality
134
+ products =
135
+ Product.search("*", {
136
+ aggs: {
137
+ total_stores: {
138
+ cardinality: {
139
+ field: :store_id
140
+ }
141
+ }
142
+ }
143
+ })
144
+ assert_equal 3, products.aggs["total_stores"]["value"]
145
+ end
146
+
147
+ def test_aggs_min_max
148
+ products =
149
+ Product.search("*", {
150
+ aggs: {
151
+ min_price: {
152
+ min: {
153
+ field: :price
154
+ }
155
+ },
156
+ max_price: {
157
+ max: {
158
+ field: :price
159
+ }
160
+ }
161
+ }
162
+ })
163
+ assert_equal 5, products.aggs["min_price"]["value"]
164
+ assert_equal 25, products.aggs["max_price"]["value"]
165
+ end
166
+
167
+ def test_aggs_sum
168
+ products =
169
+ Product.search("*", {
170
+ aggs: {
171
+ sum_price: {
172
+ sum: {
173
+ field: :price
174
+ }
175
+ }
176
+ }
177
+ })
178
+ assert_equal 66, products.aggs["sum_price"]["value"]
179
+ end
180
+
119
181
  protected
120
182
 
121
183
  def buckets_as_hash(agg)
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "sqlite3"
7
+ gem "activerecord", "~> 5.0.0"
8
+ gem "parallel_tests"
data/test/index_test.rb CHANGED
@@ -7,8 +7,9 @@ class IndexTest < Minitest::Test
7
7
  end
8
8
 
9
9
  def test_clean_indices
10
- old_index = Searchkick::Index.new("products_test_20130801000000000")
11
- different_index = Searchkick::Index.new("items_test_20130801000000000")
10
+ suffix = Searchkick.index_suffix ? "_#{Searchkick.index_suffix}" : ""
11
+ old_index = Searchkick::Index.new("products_test#{suffix}_20130801000000000")
12
+ different_index = Searchkick::Index.new("items_test#{suffix}_20130801000000000")
12
13
 
13
14
  old_index.delete if old_index.exists?
14
15
  different_index.delete if different_index.exists?
@@ -25,7 +26,8 @@ class IndexTest < Minitest::Test
25
26
  end
26
27
 
27
28
  def test_clean_indices_old_format
28
- old_index = Searchkick::Index.new("products_test_20130801000000")
29
+ suffix = Searchkick.index_suffix ? "_#{Searchkick.index_suffix}" : ""
30
+ old_index = Searchkick::Index.new("products_test#{suffix}_20130801000000")
29
31
  old_index.create
30
32
 
31
33
  Product.searchkick_index.clean_indices
@@ -0,0 +1,8 @@
1
+ require_relative "test_helper"
2
+
3
+ class MarshalTest < Minitest::Test
4
+ def test_marshal
5
+ store_names ["Product A"]
6
+ assert Marshal.dump(Product.search("*", load: {dumpable: true}).results)
7
+ end
8
+ end
data/test/match_test.rb CHANGED
@@ -186,6 +186,11 @@ class MatchTest < Minitest::Test
186
186
  assert_search "egg", ["eggs"], exclude: ["eggplant"], match: :word_start
187
187
  end
188
188
 
189
+ def test_exclude_string
190
+ store_names ["Butter Tub", "Peanut Butter Tub"]
191
+ assert_search "butter", ["Butter Tub"], exclude: "peanut butter"
192
+ end
193
+
189
194
  # other
190
195
 
191
196
  def test_all
data/test/sql_test.rb CHANGED
@@ -7,6 +7,11 @@ class SqlTest < Minitest::Test
7
7
  assert_search "fresh honey", ["Honey"], operator: "or"
8
8
  end
9
9
 
10
+ def test_operator_scoring
11
+ store_names ["Big Red Circle", "Big Green Circle", "Small Orange Circle"]
12
+ assert_order "big red circle", ["Big Red Circle", "Big Green Circle", "Small Orange Circle"], operator: "or"
13
+ end
14
+
10
15
  def test_fields_operator
11
16
  store [
12
17
  {name: "red", color: "red"},
data/test/test_helper.rb CHANGED
@@ -6,11 +6,16 @@ require "logger"
6
6
  require "active_support/core_ext" if defined?(NoBrainer)
7
7
  require "active_support/notifications"
8
8
 
9
+ Searchkick.index_suffix = ENV["TEST_ENV_NUMBER"]
10
+
9
11
  ENV["RACK_ENV"] = "test"
10
12
 
11
13
  Minitest::Test = Minitest::Unit::TestCase unless defined?(Minitest::Test)
12
14
 
13
- File.delete("elasticsearch.log") if File.exist?("elasticsearch.log")
15
+ if !defined?(ParallelTests) || ParallelTests.first_process?
16
+ File.delete("elasticsearch.log") if File.exist?("elasticsearch.log")
17
+ end
18
+
14
19
  Searchkick.client.transport.logger = Logger.new("elasticsearch.log")
15
20
  Searchkick.search_timeout = 5
16
21
 
@@ -466,7 +471,7 @@ class Animal
466
471
  searchkick \
467
472
  text_start: [:name],
468
473
  suggest: [:name],
469
- index_name: -> { "#{name.tableize}-#{Date.today.year}" },
474
+ index_name: -> { "#{name.tableize}-#{Date.today.year}#{Searchkick.index_suffix}" },
470
475
  callbacks: defined?(ActiveJob) ? :async : true
471
476
  # wordnet: true
472
477
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchkick
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-19 00:00:00.000000000 Z
11
+ date: 2017-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -147,10 +147,12 @@ files:
147
147
  - test/gemfiles/mongoid5.gemfile
148
148
  - test/gemfiles/mongoid6.gemfile
149
149
  - test/gemfiles/nobrainer.gemfile
150
+ - test/gemfiles/parallel_tests.gemfile
150
151
  - test/geo_shape_test.rb
151
152
  - test/highlight_test.rb
152
153
  - test/index_test.rb
153
154
  - test/inheritance_test.rb
155
+ - test/marshal_test.rb
154
156
  - test/match_test.rb
155
157
  - test/misspellings_test.rb
156
158
  - test/model_test.rb
@@ -220,10 +222,12 @@ test_files:
220
222
  - test/gemfiles/mongoid5.gemfile
221
223
  - test/gemfiles/mongoid6.gemfile
222
224
  - test/gemfiles/nobrainer.gemfile
225
+ - test/gemfiles/parallel_tests.gemfile
223
226
  - test/geo_shape_test.rb
224
227
  - test/highlight_test.rb
225
228
  - test/index_test.rb
226
229
  - test/inheritance_test.rb
230
+ - test/marshal_test.rb
227
231
  - test/match_test.rb
228
232
  - test/misspellings_test.rb
229
233
  - test/model_test.rb