searchkick 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +23 -0
- data/lib/searchkick/model.rb +3 -1
- data/lib/searchkick/reindex.rb +42 -25
- data/lib/searchkick/search.rb +10 -1
- data/lib/searchkick/version.rb +1 -1
- data/test/sql_test.rb +17 -0
- data/test/test_helper.rb +5 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81763af637b2e95a2eebbcecf303a23274b46221
|
4
|
+
data.tar.gz: dee89361eb8976c550ad20f413fc8ca42c5a696b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdf78091a6aa79ae75eed94e54b0f0e5c53e9515adfd4914e82b92882dfe4308af5d9cd1c4333586244f94eef69ef4c921ff53c77188f47cb1db16a4467b9087
|
7
|
+
data.tar.gz: 18773058d6ba94a0f1b2da546e426884483f45c50428babd4e172178ad0804f219648fe5de97d82c55a723886cef4d9d39b053cedc0b2d5a66d0c1cf58b3edd3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 0.2.5
|
2
|
+
|
3
|
+
- Added geospartial searches
|
4
|
+
- Create alias before importing document if no alias exists
|
5
|
+
- Fixed exception when :per_page option is a string
|
6
|
+
- Check `RAILS_ENV` if `RACK_ENV` is not set
|
7
|
+
|
1
8
|
## 0.2.4
|
2
9
|
|
3
10
|
- Use `to_hash` instead of `as_json` for default `search_data` method
|
data/README.md
CHANGED
@@ -341,6 +341,24 @@ product = Product.first
|
|
341
341
|
product.similar(fields: ["name"])
|
342
342
|
```
|
343
343
|
|
344
|
+
### Geospatial Searches
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
class City < ActiveRecord::Base
|
348
|
+
searchkick locations: ["location"]
|
349
|
+
|
350
|
+
def search_data
|
351
|
+
to_hash.merge location: [latitude.to_f, longitude.to_f]
|
352
|
+
end
|
353
|
+
end
|
354
|
+
```
|
355
|
+
|
356
|
+
Reindex and search with:
|
357
|
+
|
358
|
+
```ruby
|
359
|
+
City.search "san", where: {location: {near: [37, -114], within: "100mi"}} # or 160km
|
360
|
+
```
|
361
|
+
|
344
362
|
## Deployment
|
345
363
|
|
346
364
|
Searchkick uses `ENV["ELASTICSEARCH_URL"]` for the Elasticsearch server. This defaults to `http://localhost:9200`.
|
@@ -468,12 +486,17 @@ class Product < ActiveRecord::Base
|
|
468
486
|
end
|
469
487
|
```
|
470
488
|
|
489
|
+
For convenience, this is set by default in the test environment.
|
490
|
+
|
471
491
|
## Thanks
|
472
492
|
|
473
493
|
Thanks to Karel Minarik for [Tire](https://github.com/karmi/tire), Jaroslav Kalistsuk for [zero downtime reindexing](https://gist.github.com/jarosan/3124884), and Alex Leschenko for [Elasticsearch autocomplete](https://github.com/leschenko/elasticsearch_autocomplete).
|
474
494
|
|
475
495
|
## TODO
|
476
496
|
|
497
|
+
- Analytics for searches and conversions
|
498
|
+
- Generate autocomplete predictions from past search queries
|
499
|
+
- Automatic failover
|
477
500
|
- Make Searchkick work with any language
|
478
501
|
|
479
502
|
## History
|
data/lib/searchkick/model.rb
CHANGED
@@ -3,6 +3,8 @@ module Searchkick
|
|
3
3
|
|
4
4
|
def searchkick(options = {})
|
5
5
|
@searchkick_options = options.dup
|
6
|
+
@searchkick_env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
7
|
+
searchkick_env = @searchkick_env # for class_eval
|
6
8
|
|
7
9
|
class_eval do
|
8
10
|
extend Searchkick::Search
|
@@ -11,7 +13,7 @@ module Searchkick
|
|
11
13
|
include Tire::Model::Search
|
12
14
|
include Tire::Model::Callbacks
|
13
15
|
tire do
|
14
|
-
index_name options[:index_name] || [klass.model_name.plural,
|
16
|
+
index_name options[:index_name] || [klass.model_name.plural, searchkick_env].join("_")
|
15
17
|
end
|
16
18
|
|
17
19
|
def reindex
|
data/lib/searchkick/reindex.rb
CHANGED
@@ -12,41 +12,30 @@ module Searchkick
|
|
12
12
|
success = index.create searchkick_index_options
|
13
13
|
raise index.response.to_s if !success
|
14
14
|
|
15
|
-
# use scope for import
|
16
|
-
scope = respond_to?(:search_import) ? search_import : self
|
17
|
-
if scope.respond_to?(:find_in_batches)
|
18
|
-
scope.find_in_batches do |batch|
|
19
|
-
index.import batch
|
20
|
-
end
|
21
|
-
else
|
22
|
-
# https://github.com/karmi/tire/blob/master/lib/tire/model/import.rb
|
23
|
-
# use cursor for Mongoid
|
24
|
-
items = []
|
25
|
-
scope.all.each do |item|
|
26
|
-
items << item
|
27
|
-
if items.length % 1000 == 0
|
28
|
-
index.import items
|
29
|
-
items = []
|
30
|
-
end
|
31
|
-
end
|
32
|
-
index.import items
|
33
|
-
end
|
34
|
-
|
35
15
|
if a = Tire::Alias.find(alias_name)
|
36
|
-
|
37
|
-
|
16
|
+
searchkick_import(index) # import before swap
|
17
|
+
|
18
|
+
a.indices.each do |i|
|
19
|
+
a.indices.delete i
|
38
20
|
end
|
39
21
|
|
40
22
|
a.indices.add new_index
|
41
23
|
response = a.save
|
42
24
|
|
43
|
-
|
25
|
+
if response.success?
|
26
|
+
clean_indices
|
27
|
+
else
|
28
|
+
raise response.to_s
|
29
|
+
end
|
44
30
|
else
|
45
31
|
tire.index.delete if tire.index.exists?
|
46
32
|
response = Tire::Alias.create(name: alias_name, indices: [new_index])
|
33
|
+
raise response.to_s if !response.success?
|
34
|
+
|
35
|
+
searchkick_import(index) # import after swap
|
47
36
|
end
|
48
37
|
|
49
|
-
|
38
|
+
true
|
50
39
|
end
|
51
40
|
|
52
41
|
# remove old indices that start w/ index_name
|
@@ -65,6 +54,28 @@ module Searchkick
|
|
65
54
|
|
66
55
|
private
|
67
56
|
|
57
|
+
def searchkick_import(index)
|
58
|
+
# use scope for import
|
59
|
+
scope = respond_to?(:search_import) ? search_import : self
|
60
|
+
if scope.respond_to?(:find_in_batches)
|
61
|
+
scope.find_in_batches do |batch|
|
62
|
+
index.import batch
|
63
|
+
end
|
64
|
+
else
|
65
|
+
# https://github.com/karmi/tire/blob/master/lib/tire/model/import.rb
|
66
|
+
# use cursor for Mongoid
|
67
|
+
items = []
|
68
|
+
scope.all.each do |item|
|
69
|
+
items << item
|
70
|
+
if items.length % 1000 == 0
|
71
|
+
index.import items
|
72
|
+
items = []
|
73
|
+
end
|
74
|
+
end
|
75
|
+
index.import items
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
68
79
|
def searchkick_index_options
|
69
80
|
options = @searchkick_options
|
70
81
|
|
@@ -137,7 +148,7 @@ module Searchkick
|
|
137
148
|
}
|
138
149
|
}
|
139
150
|
|
140
|
-
if
|
151
|
+
if @searchkick_env == "test"
|
141
152
|
settings.merge!(number_of_shards: 1, number_of_replicas: 0)
|
142
153
|
end
|
143
154
|
|
@@ -196,6 +207,12 @@ module Searchkick
|
|
196
207
|
mapping[field] = field_mapping
|
197
208
|
end
|
198
209
|
|
210
|
+
(options[:locations] || []).each do |field|
|
211
|
+
mapping[field] = {
|
212
|
+
type: "geo_point"
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
199
216
|
mappings = {
|
200
217
|
document_type.to_sym => {
|
201
218
|
properties: mapping,
|
data/lib/searchkick/search.rb
CHANGED
@@ -26,7 +26,7 @@ module Searchkick
|
|
26
26
|
|
27
27
|
# pagination
|
28
28
|
page = [options[:page].to_i, 1].max
|
29
|
-
per_page = options[:limit] || options[:per_page] || 100000
|
29
|
+
per_page = (options[:limit] || options[:per_page] || 100000).to_i
|
30
30
|
offset = options[:offset] || (page - 1) * per_page
|
31
31
|
index_name = options[:index_name] || tire.index.name
|
32
32
|
|
@@ -168,6 +168,15 @@ module Searchkick
|
|
168
168
|
if value.is_a?(Array) # in query
|
169
169
|
filters << {terms: {field => value}}
|
170
170
|
elsif value.is_a?(Hash)
|
171
|
+
if value[:near]
|
172
|
+
filters << {
|
173
|
+
geo_distance: {
|
174
|
+
field => value.delete(:near),
|
175
|
+
distance: value.delete(:within) || "50mi"
|
176
|
+
}
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
171
180
|
value.each do |op, op_value|
|
172
181
|
if op == :not # not equal
|
173
182
|
if op_value.is_a?(Array)
|
data/lib/searchkick/version.rb
CHANGED
data/test/sql_test.rb
CHANGED
@@ -72,6 +72,23 @@ class TestSql < Minitest::Unit::TestCase
|
|
72
72
|
assert_search "product", ["Product A"], where: {color: ["RED"]}
|
73
73
|
end
|
74
74
|
|
75
|
+
def test_near
|
76
|
+
store [
|
77
|
+
{name: "San Francisco", latitude: 37.7833, longitude: -122.4167},
|
78
|
+
{name: "San Antonio", latitude: 29.4167, longitude: -98.5000}
|
79
|
+
]
|
80
|
+
assert_search "san", ["San Francisco"], where: {location: {near: [37, -122]}}
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_near_within
|
84
|
+
store [
|
85
|
+
{name: "San Francisco", latitude: 37.7833, longitude: -122.4167},
|
86
|
+
{name: "San Antonio", latitude: 29.4167, longitude: -98.5000},
|
87
|
+
{name: "San Marino", latitude: 43.9333, longitude: 12.4667}
|
88
|
+
]
|
89
|
+
assert_search "san", ["San Francisco", "San Antonio"], where: {location: {near: [37, -122], within: "2000mi"}}
|
90
|
+
end
|
91
|
+
|
75
92
|
def test_order_hash
|
76
93
|
store_names ["Product A", "Product B", "Product C", "Product D"]
|
77
94
|
assert_order "product", ["Product D", "Product C", "Product B", "Product A"], order: {name: :desc}
|
data/test/test_helper.rb
CHANGED
@@ -44,6 +44,8 @@ else
|
|
44
44
|
t.boolean :backordered
|
45
45
|
t.integer :orders_count
|
46
46
|
t.string :color
|
47
|
+
t.decimal :latitude, precision: 10, scale: 7
|
48
|
+
t.decimal :longitude, precision: 10, scale: 7
|
47
49
|
t.timestamps
|
48
50
|
end
|
49
51
|
|
@@ -72,12 +74,13 @@ class Product
|
|
72
74
|
autocomplete: [:name],
|
73
75
|
suggest: [:name, :color],
|
74
76
|
conversions: "conversions",
|
75
|
-
personalize: "user_ids"
|
77
|
+
personalize: "user_ids",
|
78
|
+
locations: ["location"]
|
76
79
|
|
77
80
|
attr_accessor :conversions, :user_ids
|
78
81
|
|
79
82
|
def search_data
|
80
|
-
to_hash.merge conversions: conversions, user_ids: user_ids
|
83
|
+
to_hash.merge conversions: conversions, user_ids: user_ids, location: [latitude.to_f, longitude.to_f]
|
81
84
|
end
|
82
85
|
end
|
83
86
|
|
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: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tire
|