Rails弹性搜索 - 命名范围搜索 [英] Rails elasticsearch - named scope search
问题描述
我有一个模型 InventoryItem
和一个模型 Store
。 存储
has_many :inventory_items
。我在商店上有一个模型范围叫做 local
scope:local,拉姆达{|用户| near([user.latitude,user.longitude],user.distance_preference,:order =>:distance)}
我希望搜索只返回此范围的结果,所以我尝试: InventoryItem.local(user).search ....
,但它搜索整个索引而不是范围。做一些研究后,看起来像过滤器是实现这一点的好方法,但我不确定如何实现。我开放其他方式实现这一点。我的最终目标是能够根据商店位置搜索 InventoryItem
模型的子集。
您可以做的另一件事是将有效ID的列表发送给弹性,所以它会自动过滤记录,然后对剩下的记录进行搜索。我们没有做测试是否更快,但我认为应该是因为弹性是一个搜索引擎。
我将尝试使用你的类+变量和我们的经验:
def search
#检索ids你想在
@store_ids = Store.local(current_user).select(:id).pluck(:id)
#你还可以检查是否有可用的ids可用
#如果没有 - 否需要弹性来搜索
@response = InventoryItem.search_by_store_ids('whatever',@store_ids)
end
和一个模型:
class InventoryItem
#...
#搜索弹性只对于通过的商店ids
def self.search_by_store_ids(query,store_ids,options = {})
#使用方法以下
#也可以单独使用它你不需要任何id过滤
self.search_all(查询,选项.deep_merge({
查询:{
过滤:{
过滤器:{
条款:{
store_id:store_ids
}
}
}
}
}))
end
#搜索所有库存项目的弹性
def self.search_all(query,options = { }
self .__ elasticsearch __。search(
{
查询:{
过滤:{
查询:{
#使用您要搜索的字段,我们的是'text'
匹配:{text:query},
},
过滤器:{},
策略:'leap_frog_filter_first'#先做过滤器
}
}
} .deep_merge(options)
#从private.search_by_store_ids的合并选项,如果从那里调用
#,则将应用ids过滤器
)
end
#...
end
还要索引 store_id
。
您可以阅读有关过滤器的更多信息这里。
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.
这篇关于Rails弹性搜索 - 命名范围搜索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!