我有一个模型Campaign,可以由类型为“NonProfit”和“Individual”的用户创建。
现在,我要搜索仅由非营利组织或个人,或由其中任何一个创建的广告系列。
这是我的模型:
class Campaign < ActiveRecord::Base
after_commit lambda { __elasticsearch__.index_document }, on: :create
after_commit lambda { __elasticsearch__.update_document }, on: :update
belongs_to :user
enum status: { waiting: 0, approved: 1, disapproved: 2, expired: 3, canceled: 4, draft: 5, published: 6}
def user_type
self.user.rolable_type
end
def as_json(options={})
super(:only => [:id, :status, :title, :description],
:methods => [:user_type])
end
settings index: {
number_of_shards: 1,
analysis: {
filter: {
trigrams_filter: {
type: 'ngram',
min_gram: 2,
max_gram: 10
},
content_filter: {
type: 'ngram',
min_gram: 4,
max_gram: 20
}
},
analyzer: {
index_trigrams_analyzer: {
type: 'custom',
tokenizer: 'standard',
filter: ['lowercase', 'trigrams_filter', 'asciifolding']
},
search_trigrams_analyzer: {
type: 'custom',
tokenizer: 'whitespace',
filter: ['lowercase']
},
english: {
tokenizer: 'standard',
filter: ['standard', 'lowercase', 'content_filter']
},
czech: {
tokenizer: 'standard',
filter: ['standard','lowercase','content_filter', 'asciifolding']
}
}
}
} do
mappings dynamic: 'false' do
indexes :status, type: 'string'
indexes :user_type, type: 'string'
indexes :en_title, index_analyzer: 'english', search_analyzer: 'english'
indexes :ma_title, index_analyzer: 'czech', search_analyzer: 'czech'
indexes :cs_title, index_analyzer: 'czech', search_analyzer: 'czech'
indexes :en_description, index_analyzer: 'english', search_analyzer: 'english'
indexes :ma_description, index_analyzer: 'czech', search_analyzer: 'czech'
indexes :cs_description, index_analyzer: 'czech', search_analyzer: 'czech'
end
end
def as_indexed_json(options={})
{ id: id,
status: status,
user_type: user_type,
ma_title: ma_title,
cs_title: cs_title,
en_title: en_title,
ma_description: ma_description,
cs_description: cs_description,
en_description: en_description
}
end
def self.search(query, user_type)
__elasticsearch__.search(
{
query: {
filtered: {
query: {
multi_match: {
query: query,
fields: ['ma_title^10', 'cs_title^10', 'en_title^10', 'ma_description', 'cs_description', 'en_description']
}
},
filter: {
term: {
status: "published"
},
term: {
user_type: user_type
}
}
}
}
}
)
end
end
我的 Controller 看起来像这样:Campaign.search(params[:q], 'NonProfit') # to search only NonProfit campaigns
Campaign.search(params[:q], 'Individual') # to search only Individual campaigns
Campaign.search(params[:q], ['NonProfit','Individual']) # to search any of the campaigns
但是我总是得到0个结果。删除过滤条件“user_type”时,我的工作效果很好。我无法使user_type过滤器术语按预期工作。任何想法,如何使其工作?
谢谢,Miroslav
UPDATE 1(过滤器user_type仍然不起作用-0个结果):
def as_json(options={})
super(:only => [:id, :status, :title, :description],
:methods => [:user_type]
# :include => {
# :employers => {:only => [:title]},
# :roles => {:only => [:name]}
# }
)
end
settings index: {
number_of_shards: 1,
analysis: {
filter: {
trigrams_filter: {
type: 'ngram',
min_gram: 2,
max_gram: 10
},
content_filter: {
type: 'ngram',
min_gram: 4,
max_gram: 20
}
},
analyzer: {
index_trigrams_analyzer: {
type: 'custom',
tokenizer: 'standard',
filter: ['lowercase', 'trigrams_filter', 'asciifolding']
},
search_trigrams_analyzer: {
type: 'custom',
tokenizer: 'whitespace',
filter: ['lowercase']
},
english: {
tokenizer: 'standard',
filter: ['standard', 'lowercase', 'content_filter']
},
czech: {
tokenizer: 'standard',
filter: ['standard','lowercase','content_filter', 'asciifolding']
}
}
}
} do
mappings dynamic: 'false' do
indexes :status, type: 'string', index: 'not_analyzed'
indexes :user_type, type: 'string', index: 'not_analyzed'
indexes :en_title, index_analyzer: 'english', search_analyzer: 'english'
indexes :ma_title, index_analyzer: 'czech', search_analyzer: 'czech'
indexes :cs_title, index_analyzer: 'czech', search_analyzer: 'czech'
indexes :en_description, index_analyzer: 'english', search_analyzer: 'english'
indexes :ma_description, index_analyzer: 'czech', search_analyzer: 'czech'
indexes :cs_description, index_analyzer: 'czech', search_analyzer: 'czech'
end
end
def as_indexed_json(options={})
{ id: id,
status: status,
ma_title: ma_title,
cs_title: cs_title,
en_title: en_title,
ma_description: ma_description,
cs_description: cs_description,
en_description: en_description,
:methods => [:user_type]
}
end
def self.search(query, user_type)
__elasticsearch__.search(
{
query: {
filtered: {
query: {
multi_match: {
query: query,
fields: ['ma_title^10', 'cs_title^10', 'en_title^10', 'ma_description', 'cs_description', 'en_description']
}
},
filter: {
bool: {
must: [
{
term: {
status: "published"
}
},
{
terms: {
user_type: user_type
}
}
]
}
}
}
}
}
)
end
最佳答案
您需要将 "index" : "not_analyzed"
和mapping
字段添加到status
中。由于您未指定任何分析器,因此ES在这些字段中使用 user_type
。
mappings dynamic: 'false' do
indexes :status, type: 'string', index : 'not_analyzed' <--- here
indexes :user_type, type: 'string', index : 'not_analyzed' <--- here
如果需要使用term过滤器,则需要确保与完全匹配,因为
standard analyzer
不执行任何分析。同样对于
term queries
,您在搜索多个值时也需要使用terms filter。编辑 条款查询
字词查询期望值数组
Campaign.search(params[:q], ['NonProfit'])
试试这个
{
"terms": {
"user_type": ['NonProfit']
}
}
我希望这有帮助。
关于ruby-on-rails - Rails Elasticsearch-多个过滤条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33960546/