searchkick 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +5 -0
- data/README.md +21 -15
- data/Rakefile +4 -0
- data/benchmark/Gemfile +19 -0
- data/benchmark/benchmark.rb +63 -0
- data/lib/searchkick/index.rb +29 -20
- data/lib/searchkick/index_options.rb +2 -18
- data/lib/searchkick/results.rb +31 -16
- data/lib/searchkick/version.rb +1 -1
- data/searchkick.gemspec +1 -1
- data/test/aggs_test.rb +16 -13
- data/test/highlight_test.rb +17 -12
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17c7f39c1470d38bc637340ae0031997a0b0134c
|
4
|
+
data.tar.gz: 0167c2d1448536bf5b2b48120f56e992c22aed8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6bf61245813c31fc922a29c5aa4998df13c9c1f51eba6c248ea1bfbba435f048de37a069d23cad6fc041618a235974895cb7466c08ee24cb14eb39296fc908d
|
7
|
+
data.tar.gz: b50909d603658acd1c9562470c2fd1de404cffd2f93a22c1ca926003afaaabcf33ea70a14ba69d96e3b94b50af241b91cbd267492c079416e2b9ae500c6cf32e
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -254,7 +254,7 @@ Available options are:
|
|
254
254
|
### Exact Matches
|
255
255
|
|
256
256
|
```ruby
|
257
|
-
User.search
|
257
|
+
User.search query, fields: [{email: :exact}, :name]
|
258
258
|
```
|
259
259
|
|
260
260
|
### Phrase Matches
|
@@ -431,7 +431,7 @@ Product.reindex(resume: true)
|
|
431
431
|
|
432
432
|
#### No need to reindex
|
433
433
|
|
434
|
-
-
|
434
|
+
- app starts
|
435
435
|
|
436
436
|
### Stay Synced
|
437
437
|
|
@@ -784,8 +784,8 @@ bands = Band.search "cinema", fields: [:name], highlight: true
|
|
784
784
|
View the highlighted fields with:
|
785
785
|
|
786
786
|
```ruby
|
787
|
-
bands.
|
788
|
-
|
787
|
+
bands.each do |band|
|
788
|
+
band.search_highlights[:name] # "Two Door <em>Cinema</em> Club"
|
789
789
|
end
|
790
790
|
```
|
791
791
|
|
@@ -1013,7 +1013,7 @@ heroku run rake searchkick:reindex CLASS=Product
|
|
1013
1013
|
Include `elasticsearch 1.0.15` or greater in your Gemfile.
|
1014
1014
|
|
1015
1015
|
```ruby
|
1016
|
-
gem
|
1016
|
+
gem 'elasticsearch', '>= 1.0.15'
|
1017
1017
|
```
|
1018
1018
|
|
1019
1019
|
Create an initializer `config/initializers/elasticsearch.rb` with:
|
@@ -1088,15 +1088,23 @@ See [Production Rails](https://github.com/ankane/production_rails) for other goo
|
|
1088
1088
|
|
1089
1089
|
## Performance
|
1090
1090
|
|
1091
|
+
### JSON Generation
|
1092
|
+
|
1093
|
+
Significantly increase performance with faster JSON generation. Add [Oj](https://github.com/ohler55/oj) to your Gemfile.
|
1094
|
+
|
1095
|
+
```ruby
|
1096
|
+
gem 'oj'
|
1097
|
+
```
|
1098
|
+
|
1091
1099
|
### Persistent HTTP Connections
|
1092
1100
|
|
1093
|
-
|
1101
|
+
Significantly increase performance with persistent HTTP connections. Add [Typhoeus](https://github.com/typhoeus/typhoeus) to your Gemfile.
|
1094
1102
|
|
1095
1103
|
```ruby
|
1096
1104
|
gem 'typhoeus'
|
1097
1105
|
```
|
1098
1106
|
|
1099
|
-
|
1107
|
+
To reduce log noise, create an initializer with:
|
1100
1108
|
|
1101
1109
|
```ruby
|
1102
1110
|
Ethon.logger = Logger.new("/dev/null")
|
@@ -1126,7 +1134,7 @@ end
|
|
1126
1134
|
|
1127
1135
|
### Routing
|
1128
1136
|
|
1129
|
-
Searchkick supports [Elasticsearch’s routing feature](https://www.elastic.co/blog/customizing-your-document-routing).
|
1137
|
+
Searchkick supports [Elasticsearch’s routing feature](https://www.elastic.co/blog/customizing-your-document-routing), which can significantly speed up searches.
|
1130
1138
|
|
1131
1139
|
```ruby
|
1132
1140
|
class Business < ActiveRecord::Base
|
@@ -1245,24 +1253,22 @@ User.search "san", fields: ["address.city"], where: {"address.zip_code" => 12345
|
|
1245
1253
|
Reindex one record
|
1246
1254
|
|
1247
1255
|
```ruby
|
1248
|
-
product = Product.find
|
1256
|
+
product = Product.find(1)
|
1249
1257
|
product.reindex
|
1250
1258
|
# or to reindex in the background
|
1251
1259
|
product.reindex_async
|
1252
1260
|
```
|
1253
1261
|
|
1254
|
-
Reindex
|
1262
|
+
Reindex multiple records
|
1255
1263
|
|
1256
1264
|
```ruby
|
1257
|
-
|
1265
|
+
Product.where(store_id: 1).reindex
|
1258
1266
|
```
|
1259
1267
|
|
1260
|
-
Reindex
|
1268
|
+
Reindex associations
|
1261
1269
|
|
1262
1270
|
```ruby
|
1263
|
-
|
1264
|
-
Product.searchkick_index.import(batch)
|
1265
|
-
end
|
1271
|
+
store.products.reindex
|
1266
1272
|
```
|
1267
1273
|
|
1268
1274
|
Reindex a subset of attributes (partial reindex)
|
data/Rakefile
CHANGED
data/benchmark/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
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 "activerecord-import"
|
9
|
+
|
10
|
+
# performance
|
11
|
+
gem "typhoeus"
|
12
|
+
gem "oj"
|
13
|
+
|
14
|
+
# profiling
|
15
|
+
gem "ruby-prof"
|
16
|
+
gem "allocation_stats"
|
17
|
+
gem "get_process_mem"
|
18
|
+
gem "memory_profiler"
|
19
|
+
gem "allocation_tracer"
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
Bundler.require(:default)
|
3
|
+
require "active_record"
|
4
|
+
require "benchmark"
|
5
|
+
|
6
|
+
ActiveRecord::Base.default_timezone = :utc
|
7
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
8
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
9
|
+
|
10
|
+
ActiveRecord::Migration.create_table :products do |t|
|
11
|
+
t.string :name
|
12
|
+
t.string :color
|
13
|
+
t.integer :store_id
|
14
|
+
end
|
15
|
+
|
16
|
+
class Product < ActiveRecord::Base
|
17
|
+
searchkick batch_size: 100
|
18
|
+
|
19
|
+
def search_data
|
20
|
+
{
|
21
|
+
name: name,
|
22
|
+
color: color,
|
23
|
+
store_id: store_id
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Product.import ["name", "color", "store_id"], 20000.times.map { |i| ["Product #{i}", ["red", "blue"].sample, rand(10)] }
|
29
|
+
|
30
|
+
puts "Imported"
|
31
|
+
|
32
|
+
result = nil
|
33
|
+
report = nil
|
34
|
+
stats = nil
|
35
|
+
|
36
|
+
# p GetProcessMem.new.mb
|
37
|
+
|
38
|
+
time =
|
39
|
+
Benchmark.realtime do
|
40
|
+
# result = RubyProf.profile do
|
41
|
+
# report = MemoryProfiler.report do
|
42
|
+
# stats = AllocationStats.trace do
|
43
|
+
Product.reindex
|
44
|
+
# end
|
45
|
+
end
|
46
|
+
|
47
|
+
# p GetProcessMem.new.mb
|
48
|
+
|
49
|
+
puts time.round(1)
|
50
|
+
puts Product.searchkick_index.total_docs
|
51
|
+
|
52
|
+
if result
|
53
|
+
printer = RubyProf::GraphPrinter.new(result)
|
54
|
+
printer.print(STDOUT, min_percent: 5)
|
55
|
+
end
|
56
|
+
|
57
|
+
if report
|
58
|
+
puts report.pretty_print
|
59
|
+
end
|
60
|
+
|
61
|
+
if stats
|
62
|
+
puts result.allocations(alias_paths: true).group_by(:sourcefile, :class).to_text
|
63
|
+
end
|
data/lib/searchkick/index.rb
CHANGED
@@ -7,6 +7,7 @@ module Searchkick
|
|
7
7
|
def initialize(name, options = {})
|
8
8
|
@name = name
|
9
9
|
@options = options
|
10
|
+
@klass_document_type = {} # cache
|
10
11
|
end
|
11
12
|
|
12
13
|
def create(body = {})
|
@@ -270,10 +271,12 @@ module Searchkick
|
|
270
271
|
end
|
271
272
|
|
272
273
|
def klass_document_type(klass)
|
273
|
-
|
274
|
-
klass.document_type
|
275
|
-
|
276
|
-
|
274
|
+
@klass_document_type[klass] ||= begin
|
275
|
+
if klass.respond_to?(:document_type)
|
276
|
+
klass.document_type
|
277
|
+
else
|
278
|
+
klass.model_name.to_s.underscore
|
279
|
+
end
|
277
280
|
end
|
278
281
|
end
|
279
282
|
|
@@ -296,42 +299,48 @@ module Searchkick
|
|
296
299
|
id.is_a?(Numeric) ? id : id.to_s
|
297
300
|
end
|
298
301
|
|
302
|
+
EXCLUDED_ATTRIBUTES = ["_id", "_type"]
|
303
|
+
|
299
304
|
def search_data(record, method_name = nil)
|
300
305
|
partial_reindex = !method_name.nil?
|
301
|
-
source = record.send(method_name || :search_data)
|
302
306
|
options = record.class.searchkick_options
|
303
307
|
|
304
|
-
# stringify fields
|
305
308
|
# remove _id since search_id is used instead
|
306
|
-
source =
|
309
|
+
source = record.send(method_name || :search_data).each_with_object({}) { |(k, v), memo| memo[k.to_s] = v; memo }.except(*EXCLUDED_ATTRIBUTES)
|
307
310
|
|
308
311
|
# conversions
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
+
if options[:conversions]
|
313
|
+
Array(options[:conversions]).map(&:to_s).each do |conversions_field|
|
314
|
+
if source[conversions_field]
|
315
|
+
source[conversions_field] = source[conversions_field].map { |k, v| {query: k, count: v} }
|
316
|
+
end
|
312
317
|
end
|
313
318
|
end
|
314
319
|
|
315
320
|
# hack to prevent generator field doesn't exist error
|
316
|
-
|
317
|
-
|
321
|
+
if options[:suggest]
|
322
|
+
options[:suggest].map(&:to_s).each do |field|
|
323
|
+
source[field] = nil if !source[field] && !partial_reindex
|
324
|
+
end
|
318
325
|
end
|
319
326
|
|
320
327
|
# locations
|
321
|
-
|
322
|
-
|
323
|
-
if
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
+
if options[:locations]
|
329
|
+
options[:locations].map(&:to_s).each do |field|
|
330
|
+
if source[field]
|
331
|
+
if !source[field].is_a?(Hash) && (source[field].first.is_a?(Array) || source[field].first.is_a?(Hash))
|
332
|
+
# multiple locations
|
333
|
+
source[field] = source[field].map { |a| location_value(a) }
|
334
|
+
else
|
335
|
+
source[field] = location_value(source[field])
|
336
|
+
end
|
328
337
|
end
|
329
338
|
end
|
330
339
|
end
|
331
340
|
|
332
341
|
cast_big_decimal(source)
|
333
342
|
|
334
|
-
source
|
343
|
+
source
|
335
344
|
end
|
336
345
|
|
337
346
|
def location_value(value)
|
@@ -252,15 +252,7 @@ module Searchkick
|
|
252
252
|
end
|
253
253
|
end
|
254
254
|
|
255
|
-
mapping[field] =
|
256
|
-
if below50
|
257
|
-
{
|
258
|
-
type: "multi_field",
|
259
|
-
fields: fields
|
260
|
-
}
|
261
|
-
elsif fields[field]
|
262
|
-
fields[field].merge(fields: fields.except(field))
|
263
|
-
end
|
255
|
+
mapping[field] = fields[field].merge(fields: fields.except(field))
|
264
256
|
end
|
265
257
|
|
266
258
|
(options[:locations] || []).map(&:to_s).each do |field|
|
@@ -307,15 +299,7 @@ module Searchkick
|
|
307
299
|
end
|
308
300
|
|
309
301
|
# http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
|
310
|
-
multi_field =
|
311
|
-
if below50
|
312
|
-
{
|
313
|
-
type: "multi_field",
|
314
|
-
fields: dynamic_fields
|
315
|
-
}
|
316
|
-
else
|
317
|
-
dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}"))
|
318
|
-
end
|
302
|
+
multi_field = dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}"))
|
319
303
|
|
320
304
|
all_enabled = !options[:searchable] || options[:searchable].to_a.include?("_all")
|
321
305
|
|
data/lib/searchkick/results.rb
CHANGED
@@ -32,7 +32,22 @@ module Searchkick
|
|
32
32
|
|
33
33
|
# sort
|
34
34
|
hits.map do |hit|
|
35
|
-
results[hit["_type"]][hit["_id"].to_s]
|
35
|
+
result = results[hit["_type"]][hit["_id"].to_s]
|
36
|
+
if result
|
37
|
+
unless result.respond_to?(:search_hit)
|
38
|
+
result.define_singleton_method(:search_hit) do
|
39
|
+
hit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if hit["highlight"] && !result.respond_to?(:search_highlights)
|
44
|
+
highlights = Hash[hit["highlight"].map { |k, v| [(options[:json] ? k : k.sub(/\.#{@options[:match_suffix]}\z/, "")).to_sym, v.first] }]
|
45
|
+
result.define_singleton_method(:search_highlights) do
|
46
|
+
highlights
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
result
|
36
51
|
end.compact
|
37
52
|
else
|
38
53
|
hits.map do |hit|
|
@@ -187,21 +202,21 @@ module Searchkick
|
|
187
202
|
end
|
188
203
|
end
|
189
204
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
+
records =
|
206
|
+
if records.respond_to?(:primary_key)
|
207
|
+
# ActiveRecord
|
208
|
+
records.where(records.primary_key => ids) if records.primary_key
|
209
|
+
elsif records.respond_to?(:queryable)
|
210
|
+
# Mongoid 3+
|
211
|
+
records.queryable.for_ids(ids)
|
212
|
+
elsif records.respond_to?(:unscoped) && :id.respond_to?(:in)
|
213
|
+
# Nobrainer
|
214
|
+
records.unscoped.where(:id.in => ids)
|
215
|
+
end
|
216
|
+
|
217
|
+
raise Searchkick::Error, "Not sure how to load records" if !records
|
218
|
+
|
219
|
+
records
|
205
220
|
end
|
206
221
|
|
207
222
|
def base_field(k)
|
data/lib/searchkick/version.rb
CHANGED
data/searchkick.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features|benchmark)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "activemodel", ">= 4.1"
|
data/test/aggs_test.rb
CHANGED
@@ -98,19 +98,22 @@ class AggsTest < Minitest::Test
|
|
98
98
|
|
99
99
|
def test_aggs_group_by_date
|
100
100
|
store [{name: "Old Product", created_at: 3.years.ago}]
|
101
|
-
|
102
|
-
"Product",
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
101
|
+
products =
|
102
|
+
Product.search("Product", {
|
103
|
+
where: {
|
104
|
+
created_at: {lt: Time.now}
|
105
|
+
},
|
106
|
+
aggs: {
|
107
|
+
products_per_year: {
|
108
|
+
date_histogram: {
|
109
|
+
field: :created_at,
|
110
|
+
interval: :year
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
})
|
115
|
+
|
116
|
+
assert_equal 4, products.aggs["products_per_year"]["buckets"].size
|
114
117
|
end
|
115
118
|
|
116
119
|
protected
|
data/test/highlight_test.rb
CHANGED
@@ -3,42 +3,42 @@ require_relative "test_helper"
|
|
3
3
|
class HighlightTest < Minitest::Test
|
4
4
|
def test_basic
|
5
5
|
store_names ["Two Door Cinema Club"]
|
6
|
-
assert_equal "Two Door <em>Cinema</em> Club", Product.search("cinema", fields: [:name], highlight: true).
|
6
|
+
assert_equal "Two Door <em>Cinema</em> Club", Product.search("cinema", fields: [:name], highlight: true).first.search_highlights[:name]
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_tag
|
10
10
|
store_names ["Two Door Cinema Club"]
|
11
|
-
assert_equal "Two Door <strong>Cinema</strong> Club", Product.search("cinema", fields: [:name], highlight: {tag: "<strong>"}).
|
11
|
+
assert_equal "Two Door <strong>Cinema</strong> Club", Product.search("cinema", fields: [:name], highlight: {tag: "<strong>"}).first.search_highlights[:name]
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_multiple_fields
|
15
15
|
store [{name: "Two Door Cinema Club", color: "Cinema Orange"}]
|
16
|
-
|
17
|
-
assert_equal "Two Door <em>Cinema</em> Club",
|
18
|
-
assert_equal "<em>Cinema</em> Orange",
|
16
|
+
highlights = Product.search("cinema", fields: [:name, :color], highlight: true).first.search_highlights
|
17
|
+
assert_equal "Two Door <em>Cinema</em> Club", highlights[:name]
|
18
|
+
assert_equal "<em>Cinema</em> Orange", highlights[:color]
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_fields
|
22
22
|
store [{name: "Two Door Cinema Club", color: "Cinema Orange"}]
|
23
|
-
|
24
|
-
assert_equal "Two Door <em>Cinema</em> Club",
|
25
|
-
assert_nil
|
23
|
+
highlights = Product.search("cinema", fields: [:name, :color], highlight: {fields: [:name]}).first.search_highlights
|
24
|
+
assert_equal "Two Door <em>Cinema</em> Club", highlights[:name]
|
25
|
+
assert_nil highlights[:color]
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_field_options
|
29
29
|
store_names ["Two Door Cinema Club are a Northern Irish indie rock band"]
|
30
30
|
fragment_size = ENV["MATCH"] == "word_start" ? 26 : 20
|
31
|
-
assert_equal "Two Door <em>Cinema</em> Club are", Product.search("cinema", fields: [:name], highlight: {fields: {name: {fragment_size: fragment_size}}}).
|
31
|
+
assert_equal "Two Door <em>Cinema</em> Club are", Product.search("cinema", fields: [:name], highlight: {fields: {name: {fragment_size: fragment_size}}}).first.search_highlights[:name]
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_multiple_words
|
35
35
|
store_names ["Hello World Hello"]
|
36
|
-
assert_equal "<em>Hello</em> World <em>Hello</em>", Product.search("hello", fields: [:name], highlight: true).
|
36
|
+
assert_equal "<em>Hello</em> World <em>Hello</em>", Product.search("hello", fields: [:name], highlight: true).first.search_highlights[:name]
|
37
37
|
end
|
38
38
|
|
39
39
|
def test_encoder
|
40
40
|
store_names ["<b>Hello</b>"]
|
41
|
-
assert_equal "<b><em>Hello</em></b>", Product.search("hello", fields: [:name], highlight: {encoder: "html"}, misspellings: false).
|
41
|
+
assert_equal "<b><em>Hello</em></b>", Product.search("hello", fields: [:name], highlight: {encoder: "html"}, misspellings: false).first.search_highlights[:name]
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_body
|
@@ -58,6 +58,11 @@ class HighlightTest < Minitest::Test
|
|
58
58
|
}
|
59
59
|
}
|
60
60
|
}
|
61
|
-
assert_equal "Two Door <strong>Cinema</strong> Club", Product.search(body: body).
|
61
|
+
assert_equal "Two Door <strong>Cinema</strong> Club", Product.search(body: body).first.search_highlights[:"name.analyzed"]
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_legacy
|
65
|
+
store_names ["Two Door Cinema Club"]
|
66
|
+
assert_equal "Two Door <em>Cinema</em> Club", Product.search("cinema", fields: [:name], highlight: true).with_details.first[1][:highlight][:name]
|
62
67
|
end
|
63
68
|
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.0.
|
4
|
+
version: 2.0.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: 2016-12-
|
11
|
+
date: 2016-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -108,6 +108,8 @@ files:
|
|
108
108
|
- LICENSE.txt
|
109
109
|
- README.md
|
110
110
|
- Rakefile
|
111
|
+
- benchmark/Gemfile
|
112
|
+
- benchmark/benchmark.rb
|
111
113
|
- lib/searchkick.rb
|
112
114
|
- lib/searchkick/index.rb
|
113
115
|
- lib/searchkick/index_options.rb
|
@@ -190,6 +192,8 @@ summary: Searchkick learns what your users are looking for. As more people searc
|
|
190
192
|
it gets smarter and the results get better. It’s friendly for developers - and magical
|
191
193
|
for your users.
|
192
194
|
test_files:
|
195
|
+
- benchmark/Gemfile
|
196
|
+
- benchmark/benchmark.rb
|
193
197
|
- test/aggs_test.rb
|
194
198
|
- test/autocomplete_test.rb
|
195
199
|
- test/boost_test.rb
|