在Elasticsearch中更新索引文档

21
我正在尝试理解如何在Elasticsearch中更新索引文档。我不明白它是如何工作的。API所提到的ctx是做什么的?假设您有一个嵌套文档的文档,您需要做什么才能更新它?
删除文档并索引“已更新”版本与普通更新之间有什么区别?
2个回答

40

更新请求从Elasticsearch检索源,对其进行修改,并将其重新索引到Elasticsearch。如果您已经拥有文档的副本,则使用更新没有太大意义。通常更快的方法是只索引新版本。但是,如果您没有文档的副本,但知道要对文档进行哪些更改,则使用更新可能更有效率。

例如,如果我没有汽车文档的副本,但想要添加一个新的创建者,可以像这样操作:

curl -XDELETE localhost:9200/test

curl -XPUT localhost:9200/test -d '{
    "settings": {
        "index.number_of_shards": 1,
        "index.number_of_replicas": 0
    },
    "mappings": {
        "car": {
            "properties": {
                "creators" : {
                    "type": "nested",
                    "properties": {
                        "name": {"type":"string"}
                    }
                }
            }
        }
    }
}
'

curl -XPOST localhost:9200/test/car/1 -d '{
    "creators": [{
        "name": "Steve"
    }]
}
'

echo
curl -XPOST localhost:9200/test/car/1/_update -d '{
    "script" : "ctx._source.creators += new_creator",
    "params" : {
        "new_creator" : {"name": "John"}
    }
}'

echo
curl "localhost:9200/test/car/1?pretty=true"
echo

在更新脚本中,ctx是一个特殊的变量,它允许您访问要更新的对象的源。 ctx._source是源的可写版本。 您可以在脚本中修改此文档,修改后的源将作为文档的新版本持久化存储。


10
无需首先删除该文件,您可以直接对其进行索引。如果具有相同ID的文档已存在,则会自动删除并用新版本替换。 - imotov
1
@imotov 很棒的回答!顺便问一下,这个脚本的源语言是Groovy还是MVEL?我想在发布时默认语言是MVEL,现在默认语言是Groovy(如果在ES配置中没有明确更改)。 - Alexey Tigarev
索引已经存在,是否需要再次发送curl -XPUT请求来进行映射? - Emil
@batmaci 删除和创建索引只是为了展示完整的代码片段,以确保其可用。 - imotov
1
@pvgoddijn 嵌套文档从源中提取。您可以更新源的任何部分,这意味着您也可以更新嵌套文档。 - imotov
显示剩余4条评论

0

以下是如何在ElasticSearch 7.3中更新具有嵌套客户文档的文档:

POST /myindex/_doc/mypartid/_update
{
    "script" : {
        "source": "ctx._source.customers.add(params.newcust)",
        "params" : {
            "newcust" : {"customer": "cust3"}
        }
    }
}

结果为:

GET /myindex/_doc/mypartid
{
    "_index": "myindex2",
    "_type": "_doc",
    "_id": "mypartid",
    ...
    "_source": {
        "part": "my part",
        "customers": [
            {"customer": "cust1"},
            {"customer": "cust3"}
        ],
        "machines": [
            {"machine": "mach7"},
            {"machine": "mach2"}
        ]
    }
}

因此,对于ES7+,URL已更改,脚本的执行方式也发生了变化,数组可以执行的操作也有所不同(+=无法使用)。


这只回答了如何添加新的嵌套文档的问题。但是,如何更新给定嵌套文档中的特定字段呢?ES如何在更新查询中识别要更新的嵌套文档? - martin_wun
1
通过一个循环数组并找到正确条目的脚本。也许有一些ArrayList方法可以更好地实现。 - Marc
使用一个循环遍历数组并找到正确的条目的脚本。也许有一些ArrayList方法可以更好地实现。 - Marc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接