I'm just moving over from the Tire gem to the official elasticsearch Ruby wrapper and am working on implementing better search functionality.
I have a model InventoryItem
and a model Store
. Store
has_many :inventory_items
. I have a model scope on Store called local
scope :local, lambda{|user| near([user.latitude, user.longitude], user.distance_preference, :order => :distance)}
I want the search to only return results from this scope so I tried: InventoryItem.local(user).search....
but it searches the entire index, not the scope. After doing some research, it looks like filter's are a good way to achieve this, but I'm unsure how to implement. I'm open to other ways of achieving this as well. My ultimate goal is be able to search a subset of the InventoryItem
model based on store location.
Another thing you can do is to send the list of valid ids right to elastic, so it will filter records out by itself and then perform a search on ones that left. We were not doing tests whether it is faster yet, but I think it should, because elastic is a search engine after all.
I'll try to compose an example using you classes + variables and our experience with that:
def search
# retrieve ids you want to perform search within
@store_ids = Store.local(current_user).select(:id).pluck(:id)
# you could also check whether there are any ids available
# if there is none - no need to request elastic to search
@response = InventoryItem.search_by_store_ids('whatever', @store_ids)
end
And a model:
class InventoryItem
# ...
# search elastic only for passed store ids
def self.search_by_store_ids(query, store_ids, options = {})
# use method below
# also you can use it separately when you don't need any id filtering
self.search_all(query, options.deep_merge({
query: {
filtered: {
filter: {
terms: {
store_id: store_ids
}
}
}
}
}))
end
# search elastic for all inventory items
def self.search_all(query, options = {})
self.__elasticsearch__.search(
{
query: {
filtered: {
query: {
# use your fields you want to search, our's was 'text'
match: { text: query },
},
filter: {},
strategy: 'leap_frog_filter_first' # do the filter first
}
}
}.deep_merge(options)
# merge options from self.search_by_store_ids if calling from there
# so the ids filter will be applied
)
end
# ...
end
That way you also have to index store_id
.
You can read more about filters here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With