我在尝试从 elasticsearch 中的数组中删除元素/对象时遇到问题。
这是索引的映射:
{
"example1": {
"mappings": {
"doc": {
"properties": {
"locations": {
"type": "geo_point"
},
"postDate": {
"type": "date"
},
"status": {
"type": "long"
},
"user": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
这是一个示例文档。
{
"_index": "example1",
"_type": "doc",
"_id": "8036",
"_score": 1,
"_source": {
"user": "kimchy8036",
"postDate": "2009-11-15T13:12:00",
"locations": [
[
72.79887719999999,
21.193036000000003
],
[
-1.8262150000000001,
51.178881999999994
]
]
}
}
使用下面的查询,我可以添加多个位置。
POST /example1/_update_by_query
{
"query": {
"match": {
"_id": "3"
}
},
"script": {
"lang": "painless",
"inline": "ctx._source.locations.add(params.newsupp)",
"params": {
"newsupp": [
-74.00,
41.12121
]
}
}
}
但我无法从位置删除数组对象。我已尝试下面的查询,但它不起作用。
POST example1/doc/3/_update
{
"script": {
"lang": "painless",
"inline": "ctx._source.locations.remove(params.tag)",
"params": {
"tag": [
-74.00,
41.12121
]
}
}
}
请让我知道我在这里做错了什么。我使用的是弹性版本5.5.2
在无痛脚本中,
Array.remove()
方法按索引删除,而不是按值删除。
这是一个在 Elasticsearch 脚本中按值删除数组元素的工作示例:
POST objects/_update_by_query
{
"query": {
... // use regular ES query to remove only in relevant documents
},
"script": {
"source": """
if (ctx._source[params.array_attribute] != null) {
for (int i=ctx._source[params.array_attribute].length-1; i>=0; i--) {
if (ctx._source[params.array_attribute][i] == params.value_to_remove) {
ctx._source[params.array_attribute].remove(i);
}
}
}
""",
"params": {
"array_attribute": "<NAME_OF_ARRAY_PROPERTY_TO_REMOVE_VALUE_IN>",
"value_to_remove": "<VALUE_TO_REMOVE_FROM_ARRAY>",
}
}
}
如果您的脚本仅从一个特定数组属性中删除值,您可能希望简化脚本。例如,从文档的
"green"
数组中删除 .color_list
:
_doc/001 = {
"color_list": ["red", "blue", "green"]
}
删除脚本
"green"
:
POST objects/_update_by_query
{
"query": {
... // use regular ES query to remove only in relevant documents
},
"script": {
"source": """
for (int i=ctx._source.color_list.length-1; i>=0; i--) {
if (ctx._source.color_list[i] == params.color_to_remove) {
ctx._source.color_list.remove(i);
}
}
""",
"params": {
"color_to_remove": "green"
}
}
}
与
add()
不同,remove()
获取 元素的索引并将其删除。
您的
ctx._source.locations
无痛是 ArrayList
。它有List
的remove()
方法:
E 删除(int 索引)
删除列表中指定位置的元素(可选操作)。 ...
请参阅Painless API - 列表了解其他方法。
请参阅此答案获取示例代码。
"script" : {
"lang":"painless",
"inline":"ctx._source.locations.remove(params.tag)",
"params":{
"tag":indexToRemove
}
}
如果使用
ctx._source.locations.add(elt)
添加元素,使用 ctx._source.locations.remove(indexToRemove)
则可以按数组中元素的索引删除。
POST /your_index/_update_by_query
{
"script": {
"source": "ctx._source.your_array.removeIf(item -> item == params.value)",
"lang": "painless",
"params": {
"value": "value_to_remove"
}
},
"query": {
"term": {
"your_array": "value_to_remove"
}
}
}