Elasticsearch查询未返回正确的数据

时间:2018-06-08 18:40:21

标签: ruby-on-rails ruby elasticsearch chewy-gem

我正在使用Chewy gem将Elasticsearch集成到我的Rails项目中。 我为名为(Listing)的模型和我使用Chewy es dsl的搜索界面设置了索引。 listings_index.rb class ListingsIndex<嚼::指数   设置分析:{     分析器:{       确切:{         tokenizer:' keyword',         过滤器:['小写']       }     }   }   define_type Listing.available.includes(:listing_images,:user)do     字段:id,类型:'整数'     字段:listing_type,analyzer:' exact'     字段:状态,分析器:'确切'     字段:卧室,类型:'整数'     字段:价格,类型:'整数'     field:tenant_fee,type:' integer'     field:neighborhood_id,type:' integer'     领域:浴室,类型:'浮动'     field:lat,type:' float'     字段:lng,类型:' float'     字段:available_date,类型:'日期'     field:full_address,type:' text'     字段:标题,类型:' text'     字段:user_last_active_at,值: - >(列出){listing.user.last_active_at}用户模型上的#last_active_at属于日期类型     field:street,value: - >(listing){listing.street}     field:listing_images do       字段:图像,类型:'对象'     结束     field:coordinates,type:' geo_point',value: - > {{lat:lat,lon:lng}}   结束 结束 listing_search.rb class ListingSearch   包括ActiveData :: Model   属性:卧室,类型:整数   attribute:listing_type,type:String   attribute:price_min,type:String   attribute:price_max,type:String   attribute:date,type:String   attribute:neighborhoods,type:Array   def指数     ListingsIndex   结束  def搜索    [base_filter,neighborhood_ids_filter,     price_filter,date_filter,bed_filter,apt_type_filter,sorting] .compact.reduce(:merge)  结束  def排序    index.order({user_last_active_at :: desc})  结束  def base_filter     index.filter(术语:{状态:'可用'})。limit(4000)  结束  def apt_type_filter    if!listing_type.blank? &安培;&安培; listing_type =〜/ \ d /      如果listing_type ==' 1'        index.filter(术语:{listing_type:" full"})      结束      如果listing_type ==' 0'        index.filter(术语:{listing_type:" share"})      结束    结束  结束  def bed_filter    除非bedrooms.present?    index.filter(术语:{卧室:bedrooms.to_i})  结束  def date_filter    除非date.present?    parse_date = Chronic.parse(date,{:guess => false})。first    body = {} .tap do | body |      body.merge!(gte:parse_date)如果日期?    结束    index.filter(范围:{available_date:body})如果是body.present?  结束  def price_filter   如果price_min ==' Min $'则返回&安培;&安培; price_max ==' Max $'   如果price_min!=' Min $' &安培;&安培; price_max!=' Max $'     body = {} .tap do | body |       body.merge!(gte:price_min.to_i)if price_min?       body.merge!(lte:price_max.to_i)if price_max?     结束   elsif price_min ==' Min $' &安培;&安培; price_max!=' Max $'     body = {} .tap do | body |       body.merge!(lte:price_max)if price_max?     结束   elsif price_min!=' Min $' &安培;&安培; price_max ==' Max $'     body = {} .tap do | body |       body.merge!(gte:price_min)if price_min?     结束   结束    index.filter(范围:{price:body})如果是body.present?  结束  def neighborhood_ids_filter    index.filter(术语:{neighborhood_id:neighborhoods})如果是邻居?  结束 结束 第一个问题是过滤器apt_type_filter。它没有返回正确的数据。 第二个问题是当我使用排序方法对数据进行排序时,我得到了一个ES BadRequest错误: Elasticsearch :: Transport :: Transport :: Errors :: BadRequest:[400] {" error":{" root_cause":[{" type":&# 34; illegal_argument_exception"," reason":"默认情况下,在文本字段上禁用Fielddata。在[user_last_active_at]上设置fielddata = true,以便通过反转索引来加载内存中的fielddata。请注意,这可能会占用大量内存。或者,也可以使用关键字字段。"}],"输入":" search_phase_execution_exception","原因":"所有分片都失败&#34 ;,"相":"查询""分组":真," failed_shards":[{"碎片" :0,"指数":"目录""节点":" IYxQCcHESTWOaitD9XtDFA""理由":{& #34;键入":" illegal_argument_exception"," reason":"默认情况下,在文本字段中禁用Fielddata。在[user_last_active_at]上设置fielddata = true,以便通过反转索引来加载内存中的fielddata。请注意,这可能会占用大量内存。或者,也可以使用关键字字段。"}}]}," status":400} 这是Chewy的索引Query对象的输出: < ListingsIndex :: Query {:index => [" listing"],:type => [" listing"],:body => {:size => 4000,:query => {:bool => {:filter => [{:bool => {:must => [{:bool => {:must => [{:bool = > {:must => [{:term => {:status =>" available"}},{:terms => {:neighborhood_id => [" 45& #34;]}}]}},{:range => {:price => {:gte => 800,:lte => 3000}}}]}},{:range => { :available_date => {:gte => 2018-02-01 00:00:00 +0100}}}]}},{:term => {:bedrooms => 1}}]}}}} > 任何帮助都会很棒。谢谢。

2 个答案:

答案 0 :(得分:1)

第一部分:
您应该能够从ES客户端获得elasticsearch的查询。这将有助于调试过滤器无法正常工作的原因 关于第二部分,user_last_active_at应该具有哪种类型?你的映射非常好 错误消息显示user_last_active_at在索引中是字符串类型,因此您需要在映射中为该字段启用field_data(查看here

答案 1 :(得分:0)

穆罕默德让我很好地了解了这个问题。为了解决这个问题,我改变了两件事:

首先,我没有向ES表明user_last_active_at应该如何编入索引,所以我指定了要编入索引的字段类型:

field :user_last_active_at, type: 'date', value: ->(listing) { listing.user.last_active_at }

至于listing_type字段,我认为问题在于ES正在对字段值进行标记(将其拆分为单个字符)。相反,我的目标是搜索完整的字段值。使用keyword使其可搜索

field :listing_type, analyzer: 'keyword'