1

一段时间以来,我一直在使用弹性搜索,但遇到了一个障碍,我必须搜索与特定开始日期 (start_at) 匹配的事件。我已将我的字段索引为


mapping do
    indexes :name,    :type => 'string', :analyzer => 'snowball'
    indexes :description, :type => 'string', :analyzer => 'snowball'
    indexes :start_at, :type => 'date'
    indexes :end_at, :type => 'date'
    indexes :tag_list, :type => 'string', :analyzer => 'snowball'
    indexes :lat_lon, :type => 'geo_point'
    indexes :user_details, :type => 'string'    
  end



  def to_indexed_json
    to_hash.merge({
      :user_details => (user ? user.to_index : nil),
      :artist_details => (artists ? artists.each{|artist| artist.to_index }: nil),
      :primary_genre => (genre ? genre.name : nil),
      :lat_lon => [lat, lng].join(',')
    }).to_json
  end

所以当我打


 Tire.search('events') do 
    # ignore search query keywords
    filter range: {start_at: {gte: Date.today, lt: Date.tomorrow}}
 end

什么都不返回,但在单个范围内效果很好。那是


 Tire.search('events') do 
    # ignore search query keywords
    filter range: {start_at: {gte: Date.today}}
 end

我为 Elasticsearch 建立了事件映射索引,以将 start_at 和 end_at 设置为日期,否则它会对这些日期执行术语匹配,但这样的事情不会是答案


Tire.search('events') do
  query do
    string "start_at: #{Date.today}"
 end
end

由于这会执行字符串匹配,因此它会导致所有记录,因为标记器将分解为 2012、05、16,并且由于 2012 和 16 可能在多个区域中匹配,因此它将返回所有匹配项。

我知道我错过了一些非常基本的东西。我将不胜感激这方面的任何帮助。

更新



Event.find_all_by_start_at(Date.tomorrow + 1.day).size
  Event Load (0.7ms)  SELECT `events`.* FROM `events` WHERE `events`.`start_at` = '2012-05-19'
 => 1 

所以我那天有活动。现在,当我使用弹性搜索运行它时


ruby-1.9.2-p180 :024 > Tire.search('events') do
ruby-1.9.2-p180 :025 >     filter :range, :start_at => {gte: Date.tomorrow + 1.days, lt: Date.tomorrow + 2.days}
ruby-1.9.2-p180 :026?>   end

ruby-1.9.2-p180 :029 > x.to_curl
 => "curl -X GET \"http://localhost:9200/events/_search?pretty=true\" -d '{\"filter\":{\"range\":{\"start_at\":{\"gte\":\"2012-05-19\",\"lt\":\"2012-05-20\"}}}}'" 

{"events":{"event":{"properties":{"allow_comments":{"type":"boolean"},"artist_details":{"type":"string"},"artist_id":{"type":"long"},"city":{"type":"string"},"comments_count":{"type":"long"},"confirm":{"type":"boolean"},"created_at":{"type":"date","format":"dateOptionalTime"},"description":{"type":"string","analyzer":"snowball"},"end_at":{"type":"string"},"event_attendees_count":{"type":"long"},"event_content_type":{"type":"string"},"event_file_name":{"type":"string"},"event_file_size":{"type":"long"},"genre_id":{"type":"long"},"hits":{"type":"long"},"id":{"type":"long"},"interview":{"type":"boolean"},"lat":{"type":"double"},"lat_lon":{"type":"geo_point"},"lng":{"type":"double"},"location":{"type":"string"},"name":{"type":"string","analyzer":"snowball"},"online_tix":{"type":"boolean"},"primary_genre":{"type":"string"},"private":{"type":"boolean"},"start_at":{"type":"string"},"state":{"type":"string"},"tag_list":{"type":"string","analyzer":"snowball"},"updated_at":{"type":"date","format":"dateOptionalTime"},"user_details":{"type":"string"},"user_id":{"type":"long"},"venue_id":{"type":"long"},"zip":{"type":"string"}}}}}


4

2 回答 2

2

Elasticsearch 试图灵活地处理映射。同时还要应对底层搜索引擎——Lucene的限制。因此,当现有映射与更新的映射相矛盾时,新映射将被忽略。elasticsearch 的另一个可能在此问题中发挥作用的特性是基于数据的自动映射创建。所以,如果你

  1. 创建新索引
  2. 使用包含弹性搜索无法识别的格式的日期的字符串为字段 start_at 索引记录
  3. 更新了将类型“日期”分配给 start_at 字段的映射

您最终得到了字段 start_at 类型为“字符串”的映射。唯一的解决方法是在添加第一条记录之前删除索引并指定映射。

于 2012-05-21T11:08:15.190 回答
1

您似乎不需要使用搜索查询 - 而是使用过滤器。尝试这样的事情:

filter(:range, date: {
            to: params[:date],
            from: params[:date]
        }) if params[:date].present?

哪里params[:date]应该匹配格式:

>> Time.now.strftime('%F')
=> "2014-03-10"

并且可以是任何东西——既可以是硬类型的,也可以是作为参数传入的。

字段:start_at:end_at应该映射为:type => 'date'(就像你现在一样),不需要更改为字符串或类似的东西。

这种方法适用于 , 的字段的映射,date因为datetime轮胎/弹性搜索似乎没有区别这两种字段类型。

奖励:您可以在这里找到不错的 rails elasticsearch/tire 生产设置示例: https ://gist.github.com/psyxoz/4326881

于 2014-03-10T21:27:51.953 回答