我有一个模型广告系列,可以由类型的用户创建:" NonProfit"和"个人"。
现在,我想搜索由NonProfit或仅限个人或其中任何一个创建的广告系列。
这是我的模特:
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
我的控制器看起来像这样:
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&#39;”时,我的工作正常。我没有成功地让user_type过滤器术语按预期工作。
任何想法,如何让它工作? 谢谢,米罗斯拉夫
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
答案 0 :(得分:1)
您需要为mapping
字段status
和user_type
添加"index" : "not_analyzed"
。由于您未指定任何分析器ES,因此对这些字段使用standard analyzer
。
mappings dynamic: 'false' do
indexes :status, type: 'string', index : 'not_analyzed' <--- here
indexes :user_type, type: 'string', index : 'not_analyzed' <--- here
如果您需要使用term过滤器,则需要确保完全匹配,因为term queries
不执行任何分析。
同样适用于Campaign.search(params[:q], ['NonProfit','Individual']) # to search any of the campaigns
,您需要在搜索多个值时使用terms filter。
编辑 条款查询
条款查询需要值数组
Campaign.search(params[:q], ['NonProfit'])
试试这个
{
"terms": {
"user_type": ['NonProfit']
}
}
我希望这会有所帮助。