2015-10-04 138 views
1

我剛剛開始使用Elasticsearch,並且希望在映射爲date,格式爲hour_minute的字段上使用基於腳本的排序。每個文檔中可以有多個字段的實例。Elasticsearch日期字段上的基於腳本的排序

之前引入的表達,作爲第一步,我想一個簡單的排序(使用SENSE插件):

POST myIndex/_search 
{ 
    "query": { 
     "match_all": {} 
    }, 
    "sort": { 
     "_script": { 
     "script": "doc[\"someTime\"].value", 
     "lang": "groovy", 
     "type": "date", 
     "order": "asc" 
     } 
    } 
} 

我得到這個錯誤(片段):

SearchPhaseExecutionException[Failed to execute phase [query], all shards failed; 
shardFailures {[tjWL-zV5QXmGjNlXzLvrzw][myIndex][0]: 
SearchParseException[[myIndex][0]: 
query[ConstantScore(*:*)],from[-1],size[-1]: Parse Failure [Failed to parse source… 

如果我發佈上述查詢"type": "number"沒有錯誤,雖然這當然不按日期排序。以下工作正常:

POST myIndex/_search 
{ 
    "query": { 
     "match_all": {} 
    }, 
    "sort": { 
     "someTime": { 
     "order": "asc" 
     } 
    } 
} 

最後,我想使用基於腳本的排序,因爲我將嘗試查詢,篩選或排序使用日期和時間條件,如查詢與今天的日期的引用文件,然後排序他們通過那就是時間後,現在最低的時間等

任何建議,將不勝感激。

回答

3

使用腳本文件的排序是不是真的高性能,特別是如果你的文檔基地,預計隨着時間的推移增長。所以我要爲此提供一個解決方案,然後提出另一種選擇。

爲了使用腳本進行排序,您需要將日期轉換爲毫秒,因此您的排序可以在簡單數字上運行(排序類型只能爲numberstring)。

POST myIndex/_search 
{ 
    "query": { 
     "match_all": {} 
    }, 
    "sort": { 
     "_script": { 
     "script": "doc[\"someTime\"].date.getMillisOfDay()", 
     "lang": "groovy", 
     "type": "number",  <----- make sure this is number 
     "order": "asc" 
     } 
    } 
} 

請注意,這取決於你想要的粒度,你也可以使用getSecondOfDay()getMinuteOfDay()。這樣一來,只要您的查詢和過濾器已選擇正確的文件一天,你的排序腳本將排序基於該天中的毫秒(或幾秒或幾分鐘)的文件數量。

第二個解決方案將意味着還指數,因爲這一天的開始毫秒(或幾秒或幾分鐘)的數量到另一個領域,只是用它來進行排序,這樣你就不需要腳本。最重要的是,無論您在搜索時需要什麼信息,都可以在索引時間知道,而不是實時計算出來。

舉例來說,如果你的someTime字段包含日期2015-10-05T05:34:12.276Z,那麼你會與指數的價值20052276,這是

  • 5小時millisOfDay場* 3600000毫秒
  • 34分鐘* 60000毫秒
  • 12秒* 1000毫秒
  • +276毫秒

然後你就可以使用排序

POST myIndex/_search 
{ 
    "query": { 
     "range": { 
      "someTime": { 
       "gt": "now" 
      } 
     } 
    }, 
    "sort": { 
     "millisOfDay": { 
     "order": "asc" 
     } 
    } 
} 

請注意,我添加了一個查詢僅選擇someTime日期現後的文件,所以您將獲得在未來的所有文件,但排序按升序millisOfDay,這意味着您將首先從now獲得最近的日期。

UPDATE

如果someTime的格式HH:mm,那麼你也可以存儲其millisOfDay值,例如如果someTime = 17:30然後millisOfDay會(17H * 3600000毫秒)+(30分鐘* 60000毫秒)= 6300

那麼,你的查詢需要使用script過濾器進行返工一點點,像這樣:

{ 
    "query": { 
    "filtered": { 
     "filter": { 
     "script": { 
      "script": "doc.millisOfDay.value > new DateTime().millisOfDay" 
     } 
     } 
    } 
    }, 
    "sort": { 
    "millisOfDay": { 
     "order": "asc" 
    } 
    } 
} 
+0

轉換對我來說不起作用,也許是因爲'someTime'的格式是'hour_minute'(例如「17:30」)......我會繼續在這個方向上努力,謝謝。 – michaelbcn