2012-05-16 89 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