2012-05-16 63 views
1

我一直在使用弹性搜索一段时间,现在我碰到一个包含匹配特定开始日期(start_at)的事件的路障。我索引我的领域ElasticSearch过滤器匹配单个日期

 

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"}}}}} 

 
+0

我不知道,但你可以尝试布尔必须按照你必须匹配整个日期。 – abhas

+1

你可以通过运行curl localhost来验证start_at字段是否真的被索引为Date:9200/events/_mapping? – imotov

+0

@imotov我已经在请求上发布了一个关于to_curl的更新。 – Sid

回答

2

Elasticsearch tries to be flexible in handing mappings. At the same time, it has to deal with limitations of underlying search engine - Lucene. As a result, when existing mapping contradicts the updated mapping, the new mapping is ignored. Another feature of elasticsearch that probably played a role in this issue is automatic mapping creation based on the data. So, if you

  1. Created new index
  2. Indexed a records with the field start_at with a string that contains a date in a format that elasticsearch didn't recognize
  3. Updated mapping assigning type "date" to the start_at field

you ended up with the mapping where the field start_at has type "string". The only way around it is to delete the index and specify the mapping before adding the first record.

+0

感谢所有答案和评论@imotov所以当我做轮胎:import FORCE = true不删除索引并重新索引整个事物,它不应该被修正吗?我的start_at字段最初被映射为字符串,但是我重新编制了整个模型的索引,这不是照顾它吗? – Sid

1

It does not seem you need to use a search query - but a filter. Try something like this:

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

Where params[:date]应符合以下格式:

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

,并可以是任何东西 - 无论是hardtyped或作为参数传入。

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

这种方法适用于date的字段映射,对于datetime也应该是好的,因为Tire/Elasticsearch似乎并没有区别这两种字段类型。

奖励:你可以找到很好的轨道elasticsearch /轮胎生产设置示例这里: https://gist.github.com/psyxoz/4326881