searchkick_evichat 0.0.2
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 +7 -0
- data/.github/ISSUE_TEMPLATE.md +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +33 -0
- data/CHANGELOG.md +571 -0
- data/CONTRIBUTING.md +51 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +1895 -0
- data/Rakefile +16 -0
- data/benchmark/Gemfile +24 -0
- data/benchmark/index.rb +99 -0
- data/benchmark/search.rb +48 -0
- data/docs/Searchkick-3-Upgrade.md +57 -0
- data/lib/searchkick.rb +255 -0
- data/lib/searchkick/bulk_indexer.rb +171 -0
- data/lib/searchkick/bulk_reindex_job.rb +27 -0
- data/lib/searchkick/hash_wrapper.rb +12 -0
- data/lib/searchkick/index.rb +331 -0
- data/lib/searchkick/index_options.rb +414 -0
- data/lib/searchkick/indexer.rb +28 -0
- data/lib/searchkick/logging.rb +243 -0
- data/lib/searchkick/middleware.rb +12 -0
- data/lib/searchkick/model.rb +105 -0
- data/lib/searchkick/multi_search.rb +41 -0
- data/lib/searchkick/process_batch_job.rb +23 -0
- data/lib/searchkick/process_queue_job.rb +23 -0
- data/lib/searchkick/query.rb +978 -0
- data/lib/searchkick/record_data.rb +128 -0
- data/lib/searchkick/record_indexer.rb +59 -0
- data/lib/searchkick/reindex_queue.rb +38 -0
- data/lib/searchkick/reindex_v2_job.rb +36 -0
- data/lib/searchkick/results.rb +235 -0
- data/lib/searchkick/tasks.rb +29 -0
- data/lib/searchkick/version.rb +3 -0
- data/searchkick.gemspec +30 -0
- data/test/aggs_test.rb +217 -0
- data/test/autocomplete_test.rb +81 -0
- data/test/boost_test.rb +207 -0
- data/test/callbacks_test.rb +59 -0
- data/test/ci/before_install.sh +17 -0
- data/test/errors_test.rb +19 -0
- data/test/gemfiles/activerecord42.gemfile +7 -0
- data/test/gemfiles/activerecord50.gemfile +7 -0
- data/test/gemfiles/activerecord51.gemfile +7 -0
- data/test/gemfiles/apartment.gemfile +8 -0
- data/test/gemfiles/cequel.gemfile +8 -0
- data/test/gemfiles/mongoid5.gemfile +7 -0
- data/test/gemfiles/mongoid6.gemfile +12 -0
- data/test/gemfiles/nobrainer.gemfile +8 -0
- data/test/gemfiles/parallel_tests.gemfile +8 -0
- data/test/geo_shape_test.rb +171 -0
- data/test/highlight_test.rb +94 -0
- data/test/index_test.rb +165 -0
- data/test/inheritance_test.rb +82 -0
- data/test/language_test.rb +79 -0
- data/test/marshal_test.rb +13 -0
- data/test/match_test.rb +293 -0
- data/test/misspellings_test.rb +56 -0
- data/test/model_test.rb +40 -0
- data/test/multi_search_test.rb +37 -0
- data/test/multi_tenancy_test.rb +22 -0
- data/test/order_test.rb +40 -0
- data/test/pagination_test.rb +96 -0
- data/test/partial_reindex_test.rb +65 -0
- data/test/query_test.rb +43 -0
- data/test/reindex_test.rb +87 -0
- data/test/reindex_v2_job_test.rb +27 -0
- data/test/routing_test.rb +23 -0
- data/test/should_index_test.rb +32 -0
- data/test/similar_test.rb +28 -0
- data/test/sql_test.rb +190 -0
- data/test/suggest_test.rb +100 -0
- data/test/support/kaminari.yml +21 -0
- data/test/synonyms_test.rb +69 -0
- data/test/test_helper.rb +593 -0
- data/test/where_test.rb +249 -0
- metadata +250 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
require "rake/testtask"
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require "parallel_tests/tasks"
|
|
6
|
+
require "shellwords"
|
|
7
|
+
rescue LoadError
|
|
8
|
+
# do nothing
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
task default: :test
|
|
12
|
+
Rake::TestTask.new do |t|
|
|
13
|
+
t.libs << "test"
|
|
14
|
+
t.pattern = "test/**/*_test.rb"
|
|
15
|
+
t.warning = false
|
|
16
|
+
end
|
data/benchmark/Gemfile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in searchkick.gemspec
|
|
4
|
+
gemspec path: "../"
|
|
5
|
+
|
|
6
|
+
gem "sqlite3"
|
|
7
|
+
gem "pg"
|
|
8
|
+
gem "activerecord", "~> 5.1.0"
|
|
9
|
+
gem "activerecord-import"
|
|
10
|
+
gem "activejob"
|
|
11
|
+
gem "redis"
|
|
12
|
+
gem "sidekiq"
|
|
13
|
+
|
|
14
|
+
# performance
|
|
15
|
+
gem "typhoeus"
|
|
16
|
+
gem "oj"
|
|
17
|
+
|
|
18
|
+
# profiling
|
|
19
|
+
gem "ruby-prof"
|
|
20
|
+
gem "allocation_stats"
|
|
21
|
+
gem "get_process_mem"
|
|
22
|
+
gem "memory_profiler"
|
|
23
|
+
gem "allocation_tracer"
|
|
24
|
+
gem "benchmark-ips"
|
data/benchmark/index.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
require "bundler/setup"
|
|
2
|
+
Bundler.require(:default)
|
|
3
|
+
require "active_record"
|
|
4
|
+
require "benchmark"
|
|
5
|
+
require "active_support/notifications"
|
|
6
|
+
|
|
7
|
+
ActiveSupport::Notifications.subscribe "request.searchkick" do |*args|
|
|
8
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
9
|
+
puts "Import: #{event.duration.round}ms"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
ActiveJob::Base.queue_adapter = :sidekiq
|
|
13
|
+
|
|
14
|
+
Searchkick.redis = Redis.new
|
|
15
|
+
|
|
16
|
+
ActiveRecord::Base.default_timezone = :utc
|
|
17
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
|
18
|
+
# ActiveRecord::Base.establish_connection adapter: "sqlite3", database: "/tmp/searchkick"
|
|
19
|
+
ActiveRecord::Base.establish_connection "postgresql://localhost/searchkick_demo_development"
|
|
20
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT)
|
|
21
|
+
|
|
22
|
+
ActiveJob::Base.logger = nil
|
|
23
|
+
|
|
24
|
+
class Product < ActiveRecord::Base
|
|
25
|
+
searchkick batch_size: 1000
|
|
26
|
+
|
|
27
|
+
def search_data
|
|
28
|
+
{
|
|
29
|
+
name: name,
|
|
30
|
+
color: color,
|
|
31
|
+
store_id: store_id
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if ENV["SETUP"]
|
|
37
|
+
total_docs = 100000
|
|
38
|
+
|
|
39
|
+
ActiveRecord::Migration.create_table :products, force: :cascade do |t|
|
|
40
|
+
t.string :name
|
|
41
|
+
t.string :color
|
|
42
|
+
t.integer :store_id
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
Product.import ["name", "color", "store_id"], total_docs.times.map { |i| ["Product #{i}", ["red", "blue"].sample, rand(10)] }
|
|
46
|
+
|
|
47
|
+
puts "Imported"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
result = nil
|
|
51
|
+
report = nil
|
|
52
|
+
stats = nil
|
|
53
|
+
|
|
54
|
+
Product.searchkick_index.delete rescue nil
|
|
55
|
+
|
|
56
|
+
GC.start
|
|
57
|
+
GC.disable
|
|
58
|
+
start_mem = GetProcessMem.new.mb
|
|
59
|
+
|
|
60
|
+
time =
|
|
61
|
+
Benchmark.realtime do
|
|
62
|
+
# result = RubyProf.profile do
|
|
63
|
+
# report = MemoryProfiler.report do
|
|
64
|
+
# stats = AllocationStats.trace do
|
|
65
|
+
reindex = Product.reindex #(async: true)
|
|
66
|
+
# p reindex
|
|
67
|
+
# end
|
|
68
|
+
|
|
69
|
+
# 60.times do |i|
|
|
70
|
+
# if reindex.is_a?(Hash)
|
|
71
|
+
# docs = Searchkick::Index.new(reindex[:index_name]).total_docs
|
|
72
|
+
# else
|
|
73
|
+
# docs = Product.searchkick_index.total_docs
|
|
74
|
+
# end
|
|
75
|
+
# puts "#{i}: #{docs}"
|
|
76
|
+
# if docs == total_docs
|
|
77
|
+
# break
|
|
78
|
+
# end
|
|
79
|
+
# p Searchkick.reindex_status(reindex[:index_name]) if reindex.is_a?(Hash)
|
|
80
|
+
# sleep(1)
|
|
81
|
+
# # Product.searchkick_index.refresh
|
|
82
|
+
# end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
puts
|
|
86
|
+
puts "Time: #{time.round(1)}s"
|
|
87
|
+
|
|
88
|
+
if result
|
|
89
|
+
printer = RubyProf::GraphPrinter.new(result)
|
|
90
|
+
printer.print(STDOUT, min_percent: 5)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if report
|
|
94
|
+
puts report.pretty_print
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if stats
|
|
98
|
+
puts result.allocations(alias_paths: true).group_by(:sourcefile, :class).to_text
|
|
99
|
+
end
|
data/benchmark/search.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require "bundler/setup"
|
|
2
|
+
Bundler.require(:default)
|
|
3
|
+
require "active_record"
|
|
4
|
+
require "benchmark/ips"
|
|
5
|
+
|
|
6
|
+
ActiveRecord::Base.default_timezone = :utc
|
|
7
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
|
8
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: "/tmp/searchkick"
|
|
9
|
+
|
|
10
|
+
class Product < ActiveRecord::Base
|
|
11
|
+
searchkick batch_size: 1000
|
|
12
|
+
|
|
13
|
+
def search_data
|
|
14
|
+
{
|
|
15
|
+
name: name,
|
|
16
|
+
color: color,
|
|
17
|
+
store_id: store_id
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if ENV["SETUP"]
|
|
23
|
+
total_docs = 1000000
|
|
24
|
+
|
|
25
|
+
ActiveRecord::Migration.create_table :products, force: :cascade do |t|
|
|
26
|
+
t.string :name
|
|
27
|
+
t.string :color
|
|
28
|
+
t.integer :store_id
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
Product.import ["name", "color", "store_id"], total_docs.times.map { |i| ["Product #{i}", ["red", "blue"].sample, rand(10)] }
|
|
32
|
+
|
|
33
|
+
puts "Imported"
|
|
34
|
+
|
|
35
|
+
Product.reindex
|
|
36
|
+
|
|
37
|
+
puts "Reindexed"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
query = Product.search("product", fields: [:name], where: {color: "red", store_id: 5}, limit: 10000, load: false, execute: false)
|
|
41
|
+
|
|
42
|
+
require "pp"
|
|
43
|
+
pp query.body.as_json
|
|
44
|
+
puts
|
|
45
|
+
|
|
46
|
+
Benchmark.ips do |x|
|
|
47
|
+
x.report { query.dup.execute }
|
|
48
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Searchkick 3 Upgrade
|
|
2
|
+
|
|
3
|
+
## Before You Upgrade
|
|
4
|
+
|
|
5
|
+
Searchkick 3 no longer uses types, since they are deprecated in Elasticsearch 6.
|
|
6
|
+
|
|
7
|
+
If you use inheritance, add to your parent model:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
class Animal < ApplicationRecord
|
|
11
|
+
searchkick inheritance: true
|
|
12
|
+
end
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
And do a full reindex before upgrading.
|
|
16
|
+
|
|
17
|
+
## Upgrading
|
|
18
|
+
|
|
19
|
+
Update your Gemfile:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
gem 'searchkick', '~> 3'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
And run:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
bundle update searchkick
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
We recommend you don’t stem conversions anymore, so conversions for `pepper` don’t affect `peppers`, but if you want to keep the old behavior, use:
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
Searchkick.model_options = {
|
|
35
|
+
stem_conversions: true
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Searchkick 3 disables the `_all` field by default, since Elasticsearch 6 removes the ability to reindex with it. If you’re on Elasticsearch 5 and still need it, add to your model:
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
class Product < ApplicationRecord
|
|
43
|
+
searchkick _all: true
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If you use `record.reindex_async` or `record.reindex(async: true)`, replace it with:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
record.reindex(mode: :async)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If you use `log: true` with `boost_by`, replace it with `modifier: "ln2p"`.
|
|
54
|
+
|
|
55
|
+
If you use the `body` option and have warnings about incompatible options, remove them, as they now throw an `ArgumentError`.
|
|
56
|
+
|
|
57
|
+
Check out the [changelog](https://github.com/ankane/searchkick/blob/master/CHANGELOG.md) for the full list of changes.
|
data/lib/searchkick.rb
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
require "active_model"
|
|
2
|
+
require "active_support/core_ext/hash/deep_merge"
|
|
3
|
+
require "elasticsearch"
|
|
4
|
+
require "hashie"
|
|
5
|
+
|
|
6
|
+
require "searchkick/bulk_indexer"
|
|
7
|
+
require "searchkick/index"
|
|
8
|
+
require "searchkick/indexer"
|
|
9
|
+
require "searchkick/hash_wrapper"
|
|
10
|
+
require "searchkick/middleware"
|
|
11
|
+
require "searchkick/model"
|
|
12
|
+
require "searchkick/multi_search"
|
|
13
|
+
require "searchkick/query"
|
|
14
|
+
require "searchkick/reindex_queue"
|
|
15
|
+
require "searchkick/record_data"
|
|
16
|
+
require "searchkick/record_indexer"
|
|
17
|
+
require "searchkick/results"
|
|
18
|
+
require "searchkick/version"
|
|
19
|
+
|
|
20
|
+
require "searchkick/logging" if defined?(ActiveSupport::Notifications)
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
require "rake"
|
|
24
|
+
rescue LoadError
|
|
25
|
+
# do nothing
|
|
26
|
+
end
|
|
27
|
+
require "searchkick/tasks" if defined?(Rake)
|
|
28
|
+
|
|
29
|
+
begin
|
|
30
|
+
require "rake"
|
|
31
|
+
rescue LoadError
|
|
32
|
+
# do nothing
|
|
33
|
+
end
|
|
34
|
+
require "searchkick/tasks" if defined?(Rake)
|
|
35
|
+
|
|
36
|
+
# background jobs
|
|
37
|
+
begin
|
|
38
|
+
require "active_job"
|
|
39
|
+
rescue LoadError
|
|
40
|
+
# do nothing
|
|
41
|
+
end
|
|
42
|
+
if defined?(ActiveJob)
|
|
43
|
+
require "searchkick/bulk_reindex_job"
|
|
44
|
+
require "searchkick/process_batch_job"
|
|
45
|
+
require "searchkick/process_queue_job"
|
|
46
|
+
require "searchkick/reindex_v2_job"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module Searchkick
|
|
50
|
+
class Error < StandardError; end
|
|
51
|
+
class MissingIndexError < Error; end
|
|
52
|
+
class UnsupportedVersionError < Error; end
|
|
53
|
+
class InvalidQueryError < Elasticsearch::Transport::Transport::Errors::BadRequest; end
|
|
54
|
+
class DangerousOperation < Error; end
|
|
55
|
+
class ImportError < Error; end
|
|
56
|
+
|
|
57
|
+
class << self
|
|
58
|
+
attr_accessor :search_method_name, :wordnet_path, :timeout, :models, :client_options, :redis, :index_prefix, :index_suffix, :queue_name, :model_options
|
|
59
|
+
attr_writer :client, :env, :search_timeout
|
|
60
|
+
attr_reader :aws_credentials
|
|
61
|
+
end
|
|
62
|
+
self.search_method_name = :search
|
|
63
|
+
self.wordnet_path = "/var/lib/wn_s.pl"
|
|
64
|
+
self.timeout = 10
|
|
65
|
+
self.models = []
|
|
66
|
+
self.client_options = {}
|
|
67
|
+
self.queue_name = :searchkick
|
|
68
|
+
self.model_options = {}
|
|
69
|
+
|
|
70
|
+
def self.client
|
|
71
|
+
@client ||= begin
|
|
72
|
+
require "typhoeus/adapters/faraday" if defined?(Typhoeus)
|
|
73
|
+
|
|
74
|
+
Elasticsearch::Client.new({
|
|
75
|
+
url: ENV["ELASTICSEARCH_URL"],
|
|
76
|
+
transport_options: {request: {timeout: timeout}, headers: {content_type: "application/json"}},
|
|
77
|
+
retry_on_failure: 2
|
|
78
|
+
}.deep_merge(client_options)) do |f|
|
|
79
|
+
f.use Searchkick::Middleware
|
|
80
|
+
f.request signer_middleware_key, signer_middleware_aws_params if aws_credentials
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def self.env
|
|
86
|
+
@env ||= ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.search_timeout
|
|
90
|
+
@search_timeout || timeout
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.server_version
|
|
94
|
+
@server_version ||= client.info["version"]["number"]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.server_below?(version)
|
|
98
|
+
Gem::Version.new(server_version.split("-")[0]) < Gem::Version.new(version.split("-")[0])
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.search(term = "*", model: nil, **options, &block)
|
|
102
|
+
options = options.dup
|
|
103
|
+
klass = model
|
|
104
|
+
|
|
105
|
+
# make Searchkick.search(index_name: [Product]) and Product.search equivalent
|
|
106
|
+
unless klass
|
|
107
|
+
index_name = Array(options[:index_name])
|
|
108
|
+
if index_name.size == 1 && index_name.first.respond_to?(:searchkick_index)
|
|
109
|
+
klass = index_name.first
|
|
110
|
+
options.delete(:index_name)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
query = Searchkick::Query.new(klass, term, options)
|
|
115
|
+
block.call(query.body) if block
|
|
116
|
+
if options[:execute] == false
|
|
117
|
+
query
|
|
118
|
+
else
|
|
119
|
+
query.execute
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def self.multi_search(queries)
|
|
124
|
+
Searchkick::MultiSearch.new(queries).perform
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# callbacks
|
|
128
|
+
|
|
129
|
+
def self.enable_callbacks
|
|
130
|
+
self.callbacks_value = nil
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def self.disable_callbacks
|
|
134
|
+
self.callbacks_value = false
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def self.callbacks?(default: true)
|
|
138
|
+
if callbacks_value.nil?
|
|
139
|
+
default
|
|
140
|
+
else
|
|
141
|
+
callbacks_value != false
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def self.callbacks(value)
|
|
146
|
+
if block_given?
|
|
147
|
+
previous_value = callbacks_value
|
|
148
|
+
begin
|
|
149
|
+
self.callbacks_value = value
|
|
150
|
+
result = yield
|
|
151
|
+
indexer.perform if callbacks_value == :bulk
|
|
152
|
+
result
|
|
153
|
+
ensure
|
|
154
|
+
self.callbacks_value = previous_value
|
|
155
|
+
end
|
|
156
|
+
else
|
|
157
|
+
self.callbacks_value = value
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def self.aws_credentials=(creds)
|
|
162
|
+
begin
|
|
163
|
+
require "faraday_middleware/aws_signers_v4"
|
|
164
|
+
rescue LoadError
|
|
165
|
+
require "faraday_middleware/aws_sigv4"
|
|
166
|
+
end
|
|
167
|
+
@aws_credentials = creds
|
|
168
|
+
@client = nil # reset client
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def self.reindex_status(index_name)
|
|
172
|
+
if redis
|
|
173
|
+
batches_left = Searchkick::Index.new(index_name).batches_left
|
|
174
|
+
{
|
|
175
|
+
completed: batches_left == 0,
|
|
176
|
+
batches_left: batches_left
|
|
177
|
+
}
|
|
178
|
+
else
|
|
179
|
+
raise Searchkick::Error, "Redis not configured"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def self.with_redis
|
|
184
|
+
if redis
|
|
185
|
+
if redis.respond_to?(:with)
|
|
186
|
+
redis.with do |r|
|
|
187
|
+
yield r
|
|
188
|
+
end
|
|
189
|
+
else
|
|
190
|
+
yield redis
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# private
|
|
196
|
+
def self.load_records(records, ids)
|
|
197
|
+
records =
|
|
198
|
+
if records.respond_to?(:primary_key)
|
|
199
|
+
# ActiveRecord
|
|
200
|
+
records.where(records.primary_key => ids) if records.primary_key
|
|
201
|
+
elsif records.respond_to?(:queryable)
|
|
202
|
+
# Mongoid 3+
|
|
203
|
+
records.queryable.for_ids(ids)
|
|
204
|
+
elsif records.respond_to?(:unscoped) && :id.respond_to?(:in)
|
|
205
|
+
# Nobrainer
|
|
206
|
+
records.unscoped.where(:id.in => ids)
|
|
207
|
+
elsif records.respond_to?(:key_column_names)
|
|
208
|
+
records.where(records.key_column_names.first => ids)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
raise Searchkick::Error, "Not sure how to load records" if !records
|
|
212
|
+
|
|
213
|
+
records
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# private
|
|
217
|
+
def self.indexer
|
|
218
|
+
Thread.current[:searchkick_indexer] ||= Searchkick::Indexer.new
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# private
|
|
222
|
+
def self.callbacks_value
|
|
223
|
+
Thread.current[:searchkick_callbacks_enabled]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# private
|
|
227
|
+
def self.callbacks_value=(value)
|
|
228
|
+
Thread.current[:searchkick_callbacks_enabled] = value
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# private
|
|
232
|
+
def self.signer_middleware_key
|
|
233
|
+
defined?(FaradayMiddleware::AwsSignersV4) ? :aws_signers_v4 : :aws_sigv4
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# private
|
|
237
|
+
def self.signer_middleware_aws_params
|
|
238
|
+
if signer_middleware_key == :aws_sigv4
|
|
239
|
+
{service: "es", region: "us-east-1"}.merge(aws_credentials)
|
|
240
|
+
else
|
|
241
|
+
{
|
|
242
|
+
credentials: aws_credentials[:credentials] || Aws::Credentials.new(aws_credentials[:access_key_id], aws_credentials[:secret_access_key]),
|
|
243
|
+
service_name: "es",
|
|
244
|
+
region: aws_credentials[:region] || "us-east-1"
|
|
245
|
+
}
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# TODO find better ActiveModel hook
|
|
251
|
+
ActiveModel::Callbacks.include(Searchkick::Model)
|
|
252
|
+
|
|
253
|
+
ActiveSupport.on_load(:active_record) do
|
|
254
|
+
extend Searchkick::Model
|
|
255
|
+
end
|