我正在尝试创建一个易于编写的脚本,以通过自定义参数数组过滤嵌套字段的数组,因为我的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
"""
...
不过,我不确定您要做什么。如果满足循环中的条件,它将返回第一个匹配项。因此,它可能直到
perf3
或perf5
才运行。此外,_source.performances
可能未排序,因此相反,它可能会返回perf5
并退出。
关于elasticsearch - 通过自定义参数进行ElasticSearch无痛脚本过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61657584/