[英]Elasticsearch - Script Filter over a list of nested objects
我試圖找出如何解決我的ES 5.6索引這兩個問題。
"mappings": {
"my_test": {
"properties": {
"Employee": {
"type": "nested",
"properties": {
"Name": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
},
"Surname": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
}
}
}
}
我需要創建兩個單獨的腳本過濾器:
1 - 過濾員工數組大小== 3的文檔
2 - 過濾文檔,其中數組的第一個元素具有“Name”==“John”
我試圖做一些初步的步驟,但我無法迭代列表。 我總是有一個空指針異常錯誤。
{
"bool": {
"must": {
"nested": {
"path": "Employee",
"query": {
"bool": {
"filter": [
{
"script": {
"script" : """
int array_length = 0;
for(int i = 0; i < params._source['Employee'].length; i++)
{
array_length +=1;
}
if(array_length == 3)
{
return true
} else
{
return false
}
"""
}
}
]
}
}
}
}
}
}
1 - 過濾員工數組大小== 3的文檔
對於第一個問題,最好的做法是添加另一個根級別字段(例如NbEmployees
),其中包含Employee
數組中的項目數,以便您可以使用range
查詢而不是昂貴的script
查詢。
然后,每當您修改Employee
數組時,還會相應地更新該NbEmployees
字段。 效率更高!
2 - 過濾文檔,其中數組的第一個元素具有“Name”==“John”
關於這個,您需要知道嵌套字段是Lucene中的單獨(隱藏)文檔,因此無法在同一查詢中同時訪問所有嵌套文檔。
如果您知道需要在查詢中檢查第一個員工的姓名,只需添加另一個根級別字段FirstEmployeeName
並在該字段上運行查詢。
作為瓦爾注意到,你不能訪問_source
的腳本文件查詢在最近版本的Elasticsearch的。 但是elasticsearch允許您在“得分上下文”中訪問此_source
。
因此,可能的解決方法(但需要注意性能)是在查詢中使用腳本分數和min_score。
您可以通過elasticsearch中嵌套字段值的總和在查詢文檔中查找此堆棧溢出中此行為的示例。
在您的情況下,像這樣的查詢可以完成這項工作:
POST <your_index>/_search
{
"min_score": 0.1,
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"script_score": {
"script": {
"source": """
if (params["_source"]["Employee"].length === params.nbEmployee) {
def firstEmployee = params._source["Employee"].get(0);
if (firstEmployee.Name == params.name) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
""",
"params": {
"nbEmployee": 3,
"name": "John"
}
}
}
}
]
}
}
}
應在參數中設置Employee和first name的數量,以避免腳本重新編譯此腳本的每個用例。
但請記住,Val已經提到過,它可能對您的集群非常沉重。 您應該通過在function_score query
添加過濾器(我的示例中為match_all)來縮小您將應用腳本的文檔集。 在任何情況下,它都不是Elasticsearch應該使用的方式,並且你不能期望在這樣的黑客查詢中表現出色。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.