从 ElasticSearch 中的数组中删除元素/对象,然后进行匹配查询

问题描述 投票:0回答:4

我在尝试从 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

arrays elasticsearch geolocation match
4个回答
10
投票

在无痛脚本中,

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"
        }
    }
}

4
投票

add()
不同,
remove()
获取 元素的索引并将其删除。

您的

ctx._source.locations
无痛是
ArrayList
。它有
List
remove()
方法:

E 删除(int 索引)

删除列表中指定位置的元素(可选操作)。 ...

请参阅Painless API - 列表了解其他方法。

请参阅此答案获取示例代码。


0
投票
"script" : {
    "lang":"painless",
    "inline":"ctx._source.locations.remove(params.tag)",
    "params":{
      "tag":indexToRemove
    }
}

如果使用

ctx._source.locations.add(elt)
添加元素,使用
ctx._source.locations.remove(indexToRemove)
则可以按数组中元素的索引删除。


0
投票
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"
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.