Skip to content

Commit bfdd224

Browse files
Seitkestolfo
authored andcommitted
[MODEL] Support :scope, :query and :preprocess importing options for Mongoid (#786)
* [MODEL] Support scope, query and preprocess importing options in Mongoid Adapter * test(mongoid-adapter): add testing for importing mongoid model with default scope
1 parent 212b37a commit bfdd224

File tree

3 files changed

+132
-4
lines changed

3 files changed

+132
-4
lines changed

elasticsearch-model/lib/elasticsearch/model/adapters/mongoid.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,17 @@ module Importing
6363
# @see https://github.com/karmi/retire/pull/724
6464
#
6565
def __find_in_batches(options={}, &block)
66-
options[:batch_size] ||= 1_000
66+
batch_size = options[:batch_size] || 1_000
67+
query = options[:query]
68+
named_scope = options[:scope]
69+
preprocess = options[:preprocess]
70+
71+
scope = all
72+
scope = scope.send(named_scope) if named_scope
73+
scope = query.is_a?(Proc) ? scope.class_exec(&query) : scope.where(query) if query
6774

68-
all.no_timeout.each_slice(options[:batch_size]) do |items|
69-
yield items
75+
scope.no_timeout.each_slice(batch_size) do |items|
76+
yield (preprocess ? self.__send__(preprocess, items) : items)
7077
end
7178
end
7279

elasticsearch-model/test/integration/mongoid_basic_test.rb

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,70 @@ def as_indexed_json(options={})
167167
assert response.results.any?, "Search has not returned results: #{response.to_a}"
168168
end
169169
end
170+
171+
context "importing when the model has a default scope" do
172+
class ::MongoidArticleWithDefaultScope
173+
include Mongoid::Document
174+
include Elasticsearch::Model
175+
176+
default_scope -> { where(status: 'active') }
177+
178+
field :id, type: String
179+
field :title, type: String
180+
field :status, type: String, default: 'active'
181+
182+
attr_accessible :title if respond_to? :attr_accessible
183+
attr_accessible :status if respond_to? :attr_accessible
184+
185+
settings index: { number_of_shards: 1, number_of_replicas: 0 } do
186+
mapping do
187+
indexes :title, type: 'text', analyzer: 'snowball'
188+
indexes :status, type: 'text'
189+
indexes :created_at, type: 'date'
190+
end
191+
end
192+
193+
def as_indexed_json(options={})
194+
as_json(except: [:id, :_id])
195+
end
196+
end
197+
198+
setup do
199+
Elasticsearch::Model::Adapter.register \
200+
Elasticsearch::Model::Adapter::Mongoid,
201+
lambda { |klass| !!defined?(::Mongoid::Document) && klass.respond_to?(:ancestors) && klass.ancestors.include?(::Mongoid::Document) }
202+
203+
MongoidArticleWithDefaultScope.__elasticsearch__.create_index! force: true
204+
205+
MongoidArticleWithDefaultScope.delete_all
206+
207+
MongoidArticleWithDefaultScope.create! title: 'Test'
208+
MongoidArticleWithDefaultScope.create! title: 'Testing Coding'
209+
MongoidArticleWithDefaultScope.create! title: 'Coding'
210+
MongoidArticleWithDefaultScope.create! title: 'Test legacy code', status: 'removed'
211+
212+
MongoidArticleWithDefaultScope.__elasticsearch__.refresh_index!
213+
MongoidArticleWithDefaultScope.__elasticsearch__.client.cluster.health wait_for_status: 'yellow'
214+
end
215+
216+
should "import only documents from the default scope" do
217+
assert_equal 3, MongoidArticleWithDefaultScope.count
218+
219+
assert_equal 0, MongoidArticleWithDefaultScope.import
220+
221+
MongoidArticleWithDefaultScope.__elasticsearch__.refresh_index!
222+
assert_equal 3, MongoidArticleWithDefaultScope.search('*').results.total
223+
end
224+
225+
should "import only documents from a specific query combined with the default scope" do
226+
assert_equal 3, MongoidArticleWithDefaultScope.count
227+
228+
assert_equal 0, MongoidArticleWithDefaultScope.import(query: -> { where(title: /^Test/) })
229+
230+
MongoidArticleWithDefaultScope.__elasticsearch__.refresh_index!
231+
assert_equal 2, MongoidArticleWithDefaultScope.search('*').results.total
232+
end
233+
end
170234
end
171235

172236
end

elasticsearch-model/test/unit/adapter_mongoid_test.rb

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,64 @@ def ids
9898
assert_equal @transform.call(model), { index: { _id: "1", data: {} } }
9999
end
100100
end
101-
end
102101

102+
should "limit the relation to a specific scope" do
103+
relation = mock()
104+
relation.stubs(:no_timeout).returns(relation)
105+
relation.expects(:published).returns(relation)
106+
relation.expects(:each_slice).returns([])
107+
DummyClassForMongoid.expects(:all).returns(relation)
108+
109+
DummyClassForMongoid.__send__ :extend, Elasticsearch::Model::Adapter::Mongoid::Importing
110+
DummyClassForMongoid.__find_in_batches(scope: :published) do; end
111+
end
112+
113+
context "when limit the relation with proc" do
114+
setup do
115+
@query = Proc.new { where(color: "red") }
116+
end
117+
should "query with a specific criteria" do
118+
relation = mock()
119+
relation.stubs(:no_timeout).returns(relation)
120+
relation.expects(:class_exec).returns(relation)
121+
relation.expects(:each_slice).returns([])
122+
DummyClassForMongoid.expects(:all).returns(relation)
123+
124+
DummyClassForMongoid.__find_in_batches(query: @query) do; end
125+
end
126+
end
127+
128+
context "when limit the relation with hash" do
129+
setup do
130+
@query = { color: "red" }
131+
end
132+
should "query with a specific criteria" do
133+
relation = mock()
134+
relation.stubs(:no_timeout).returns(relation)
135+
relation.expects(:where).with(@query).returns(relation)
136+
relation.expects(:each_slice).returns([])
137+
DummyClassForMongoid.expects(:all).returns(relation)
138+
139+
DummyClassForMongoid.__find_in_batches(query: @query) do; end
140+
end
141+
end
142+
143+
should "preprocess the batch if option provided" do
144+
class << DummyClassForMongoid
145+
# Updates/transforms the batch while fetching it from the database
146+
# (eg. with information from an external system)
147+
#
148+
def update_batch(batch)
149+
batch.collect { |b| b.to_s + '!' }
150+
end
151+
end
152+
153+
DummyClassForMongoid.expects(:__find_in_batches).returns( [:a, :b] )
154+
155+
DummyClassForMongoid.__find_in_batches(preprocess: :update_batch) do |batch|
156+
assert_same_elements ["a!", "b!"], batch
157+
end
158+
end
159+
end
103160
end
104161
end

0 commit comments

Comments
 (0)