高效篩選elasticsearch數組內時間范圍數據
本文介紹如何高效地從Elasticsearch文檔中篩選出change_records數組內,change_time字段值位于特定時間范圍且元素個數達到指定數量的文檔。 我們面臨的挑戰是如何在不引發no field found錯誤的情況下,對數組內元素進行時間范圍篩選和計數。
問題:我們需要查詢change_records數組中,change_time字段值在指定時間范圍(例如,一年)內,元素個數不少于指定數量(例如,10個)的文檔。直接使用腳本查詢會導致字段未找到的錯誤。
解決方案:采用script_score查詢,結合自定義Painless腳本實現高效篩選。此方法避免了在Filter中直接使用腳本帶來的字段訪問問題。
查詢結構:
{ "query": { "script_score": { "query": { "match_all": {} // 可根據實際需求添加其他查詢條件 }, "script": { "source": """ int count = 0; for (Map record : doc['change_records']) { long changeTime = record['change_time']; if (changeTime >= params.start && changeTime <= params.end) { count++; } } return count >= params.n ? 1 : 0; """, "lang": "painless", "params": { "start": 1609459200000, // 2021年1月1日0時0分0秒的毫秒數 "end": 1704067200000, // 2024年1月1日0時0分0秒的毫秒數 "n": 10 // 至少需要10個change_time在指定時間范圍內 } } } } }
代碼解釋:
- script_score:使用腳本評分來篩選文檔。
- query:可以添加其他查詢條件,此處使用match_all匹配所有文檔。
- script:Painless腳本,遍歷change_records數組。
- count:計數器,統計滿足時間范圍條件的元素個數。
- 循環體:獲取每個change_record的change_time,并判斷是否在指定范圍內。
- return:如果count大于等于n,返回1(匹配),否則返回0(不匹配)。
- params:腳本參數,包含時間范圍的起始和結束時間戳(毫秒),以及所需的最小匹配數量n。
此方法通過腳本評分,有效地解決了直接使用腳本查詢時遇到的字段訪問問題,并實現了對數組內元素的時間范圍篩選和計數功能,從而高效地查找滿足條件的文檔。 請確保您的change_records字段映射正確,并且change_time字段為數值類型(例如long)。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END