elasticsearch - 通过自定义参数进行ElasticSearch无痛脚本过滤

标签 elasticsearch nested

我正在尝试创建一个易于编写的脚本,以通过自定义参数数组过滤嵌套字段的数组,因为我的for循环抛出错误。

制图

    {
        "documents": {
            "mappings": {
                "document": {
                    "properties": {
                        "properties": {
                            "type": "nested",
                            "properties": {
                                "key": {
                                    "type": "text",
                                    "fields": {
                                        "keyword": {
                                            "type": "keyword",
                                            "ignore_above": 256
                                        }
                                    }
                                },
                                "value": {
                                    "type": "text",
                                    "fields": {
                                        "keyword": {
                                            "type": "keyword",
                                            "ignore_above": 256
                                        }
                                    }
                                }
                            }
                        },
                        "performances": {
                            "properties": {
                                "key": {
                                    "type": "text",
                                    "fields": {
                                        "keyword": {
                                            "type": "keyword",
                                            "ignore_above": 256
                                        }
                                    }
                                },
                                "value": {
                                    "type": "double"
                                }
                            }
                        },
                        "name": {
                            "type": "text",
                            "fields": {
                                "keyword": {
                                    "type": "keyword",
                                    "ignore_above": 256
                                }
                            }
                        },
                        "id": {
                            "type": "long"
                        }
                    }
                }
            }
        }
    }

_资源
    "_source": {
        "properties": [{
                "value": [
                    "D"
                ],
                "key": "M"
            },
            {
                "value": [
                    "2019-12-31"
                ],
                "key": "DOCUMENT_DATE"
            },
            {
                "isMultiValue": false,
                "value": [
                    "Yes"
                ],
                "key": "ACTIVE_DOCUMENT"
            },
        ],
        "performances": [
            {
                "value": 123,
                "key": "performance1"
            },
            {
                "value": 234,
                "key": "performance3"
            },
            {
                "value": 345,
                "key": "performance5"
            },
            {
                "value": -456,
                "key": "someKey"
            },
            {
                "value": -567,
                "key": "someOtherKey"
            },
        ],
        "name": "documentName43",
        "id": "1234"
    }

该脚本如下所示:
    {
        "query": {
            "bool": {
                "filter": [{
                        "nested": {
                            "path": "properties",
                            "query": {
                                "bool": {
                                    "filter": [{
                                            "match": {
                                                "properties.key.keyword": "ACTIVE_DOCUMENT"
                                            }
                                        },
                                        {
                                            "match": {
                                                "properties.value": "yes"
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    {
                        "match": {
                            "id": "1234"
                        }
                    }
                ]
            }
        },
        "script_fields": {
            "nested_scores": {
                "script": {
                    "lang": "painless",
                    "source": "for (int i = 0; i < params['_source']['performances'].length; ++i) { if(params['_source']['performances'][i]['key'] == params['customFields'][i]) { return params['_source']['performances'][i]['value'];}}return 0;",
                    "params": {
                        "customFields": ["performance1", "performance3", "performance5"]
                    }

                }
            }
        },
        "_source": [
            "id",
            "name",
            "name."
        ]
    }

如果我用一个简单的字符串替换“params ['customFields'] [i]”部分,它的工作就很好,所以我猜我的问题就在附近,但无法确切地知道它是什么。

另一方面,有什么主意如何构造查询,以使无痛脚本的结果返回“_source”内部?

最后,我想做这样的事情:
"source": "for (int i = 0; i < params['_source']['performances'].length; ++i) {
                            for (int t = 0; t < params['customFields'].length; ++t) {
                                if(params['_source']['performances'][i]['key'] == params['customFields'][t]) {
                                    return params['_source']['performances'][i]['value']; 
                                }
                            }
                          }
                          return 0;"

但是首先,我想使其与上面的代码一起使用。

如果那很重要,我就使用ES 6.4,我首先尝试使用“elasticsearch-head” chrome插件运行查询。

但是那里的结果看起来像(为了方便起见,我在上面的示例中将“kennzahlen”等字段更改为“properties”)
{
    "took": 679,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 4,
        "skipped": 0,
        "failed": 1,
        "failures": [{
            "shard": 0,
            "index": "fsl_prd_products",
            "node": "xAUFwT0LRVeAuOktIr9gaA",
            "reason": {
                "type": "script_exception",
                "reason": "runtime error",
                "script_stack": [
                    "java.util.ArrayList.rangeCheck(ArrayList.java:653)",
                    "java.util.ArrayList.get(ArrayList.java:429)",
                    "if (params['_source']['kennzahlen'][i]['key'] == params['customFields'][i]) { ",
                    " ^---- HERE"
                ],
                "script": "for (int i = 0; i < params['_source']['kennzahlen'].length; ++i) { if (!params['_source'].containsKey('kennzahlen')) { return 0; } if (params['_source']['kennzahlen'][i]['key'] == params['customFields'][i]) { return params['_source']['kennzahlen'][i]['value']; } } return 0;",
                "lang": "painless",
                "caused_by": {
                    "type": "index_out_of_bounds_exception",
                    "reason": "Index: 3, Size: 3"
                }
            }
        }]
    },
    "hits": {
        "total": 1,
        "max_score": 0,
        "hits": []
    }
}

最佳答案

script_fields的结果永远不会出现在响应的_source部分中-它们始终是分开的。

让我们使用ES 7.2.0复制您的用例:

设置索引+提取(为简洁起见,没有空格)

PUT docs
{"mappings":{"properties":{"properties":{"type":"nested","properties":{"key":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"value":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}},"performances":{"properties":{"key":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"value":{"type":"double"}}},"name":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"id":{"type":"long"}}}}

POST docs/_doc
{"properties":[{"value":["D"],"key":"M"},{"value":["2019-12-31"],"key":"DOCUMENT_DATE"},{"isMultiValue":false,"value":["Yes"],"key":"ACTIVE_DOCUMENT"}],"performances":[{"value":123,"key":"performance1"},{"value":234,"key":"performance3"},{"value":345,"key":"performance5"},{"value":-456,"key":"someKey"},{"value":-567,"key":"someOtherKey"}],"name":"documentName43","id":"1234"}

然后搜寻
GET docs/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "nested": {
            "path": "properties",
            "query": {
              "bool": {
                "filter": [
                  {
                    "match": {
                      "properties.key.keyword": "ACTIVE_DOCUMENT"
                    }
                  },
                  {
                    "match": {
                      "properties.value": "yes"
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "match": {
            "id": "1234"
          }
        }
      ]
    }
  },
  "script_fields": {
    "nested_scores": {
      "script": {
        "lang": "painless",
        "source": """
          for (int i = 0; i < params['_source']['performances'].length; ++i) { 
            if (params['_source']['performances'][i]['key'] == params['customFields'][i]) { 
              return params['_source']['performances'][i]['value'];
            }

          }
          return 0;
        """,
        "params": {
          "customFields": [
            "performance1",
            "performance3",
            "performance5"
          ]
        }
      }
    }
  },
  "_source": [
    "id",
    "name",
    "name."
  ]
}

系统产量
[
  {
    "_index":"docs",
    "_type":"_doc",
    "_id":"vOhj8HEBG_KW3EFn7wOf",
    "_score":0.0,
    "_source":{
      "name":"documentName43",
      "id":"1234"
    },
    "fields":{
      "nested_scores":[            <-------
        123
      ]
    }
  }
]

如果查询失败,则可能需要尝试一些有效性检查:
...
"source": """
          if (!params['_source'].containsKey('performances')) {
            return 0
          }
          // rest of the script
"""
...

不过,我不确定您要做什么。如果满足循环中的条件,它将返回第一个匹配项。因此,它可能直到perf3perf5才运行。此外,_source.performances可能未排序,因此相反,它可能会返回perf5并退出。

关于elasticsearch - 通过自定义参数进行ElasticSearch无痛脚本过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61657584/

相关文章:

javascript - 自定义元素未设置/获取属性

c++ - 如何使用 json11 库在 json 中添加子/嵌套元素?

python - 追加到 Python 中嵌套字典内的列表

elasticsearch - 如何获取kibana 4.x中字段的总值

Elasticsearch 结果数量随分页变化

elasticsearch - 在Elasticsearch索引中找到所有单词及其频率

bash - Homebrew:如何检查 Homebrew 服务是否已打开

sql - T-SQL 嵌套子查询

ExtJS 4.1 - 在 Model.Save() 响应中返回相关数据

elasticsearch - 使用 Elasticsearch 地理功能查找按时间排序的最常见位置