關鍵字:
Elasticsearch,字符串類型的時間,時間比較,RangeQuey
場景:
沒有手動指定es的mapping,借助spring data elastic search的相關注解標識,然后,啟動的時候自動創建索引。其中有的時間被存儲為text了。那么,我們在使用rangeQuery比較的時候,只有gt生效。
解決方案。在查詢的時候, 添加.keyword,示例如下:
boolQueryBuilder.must(new RangeQueryBuilder(CatalogConst.QUERY_PREFIX + "licenseStart.keyword").gte(licenseStartValue).lte(licenseEndValue).format("yyyy-MM-dd HH:mm:ss"));
只要你是5.x以后的版本,上述操作是可以的。先拿去解決問題,然后看下邊的分析:
1.ES5.0及以后的版本取消了string類型,將原先的string類型拆分為text和keyword兩種類型。
兩者的區別在於,text會對字段進行分詞處理,而keyword不會。
當你沒有實踐indexTemplate等形式對你的索引字段手動指定mapping,ES就會使用Dynamic Mapping,通過你傳入的文檔中的字段的值,進行字段的動態映射。例如字段classroom傳入數字26會被映射為long類型。ip的值"192.168.0.1",會被映射為ip類型。然而對於不滿足ip和date格式的普通字符串,會被映射為text類型,但為了保留對這些字段進行精確查詢與聚合的能力,又同時對他們做了keyword類型的映射。作為該字段的fields屬性寫入到_mapping中。所以。"yyyy-MM-dd HH:mm:ss" 類型的時間,會被當做text存儲,又保留了keyword字段屬性。如圖:
2.range 支持text類型排序 用的是TermRangeQuery 使用BytesRef.compareTo(BytesRef)進行比較
number/date 類型 用的是 NumericRangeQuery,也就是按照數值排序。
所以,直接使用text類型的時間字符串無法正確的比較時間早晚,需要使用其keyword字段
