我正在使用嵌套对象索引一组文档(将它们想象为论坛帖子),该对象是与该帖子相关的用户.我的问题是用户字段可能会更新,但由于帖子没有更改,因此不会重新编制索引,用户嵌套对象也会过时.有没有办法更新嵌套对象而无需再次重新索引整个文档?或者唯一的解决方案是每次用户更改时重新索引用户的所有相关帖子?
Sco*_*ice 23
您可以使用Update API.
curl -XPOST localhost:9200/docs/posts/post/_update -d '{
"script" : "ctx._source.nested_user = updated_nested_user",
"params" : {
"updated_nested_user" : {"field": "updated"}
}
}'
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅此SO答案.
需要注意的是更新脚本支持条件逻辑,如图所示这里.因此,您可以在用户更改时标记论坛帖子,然后迭代帖子以仅更新已更改用户的帖子.
curl -XPOST 'localhost:9200/docs/posts/post/_update' -d '{
"script" : "ctx._source.tags.contains(tag) ? "ctx._source.nested_user = updated_nested_John" : ctx.op = "none"",
"params" : {
"tag": "updated_John_tag",
"updated_nested_John" : {"field": "updated"}
}
}'
Run Code Online (Sandbox Code Playgroud)
更新
也许我的三元运算符示例不完整.问题中没有提到这一点,但假设用户在应用程序的单独部分中更改了他们的信息,那么将这些更改应用到一个脚本中的论坛帖子会很不错.请尝试直接检查用户字段以获取更改,而不是使用标记:
curl -XPOST 'localhost:9200/docs/posts/post/_update' -d '{
"script" : "ctx._source.nested_user.contains(user) ? "ctx._source.nested_user = updated_nested_John" : ctx.op = "none"",
"params" : {
"user": "John",
"updated_nested_John" : {"field": "updated"}
}
}'
Run Code Online (Sandbox Code Playgroud)
如上所述,这可能比重新索引完整帖子的操作更慢.
ram*_*laf 10
遗憾的是,如果不重新索引整个文档,elasticsearch不能仅更新文档的一部分.所以,是的,您需要重新索引整个文档以更改嵌套部分.
如果您没有整个文档可以重新发送它,您可以使用更新API发送需要更改的部分,但要注意存在性能问题.
@Scott Rice回答如何在这种情况下使用部分更新非常有用,而@ramseykhalaf回答则更正确,因为如果不重新编制索引,这是不可能的。如果我们进行部分更新,则无论如何都要对整个文档重新编制索引。
但是取决于对什么是“重新索引”的理解。
如果我们将重新索引定义为“将整个文档重新提交给ES”,则可以调用部分更新解决方案,而无需重新索引。如果我们将重新索引定义为“重新计算数据结构以允许在索引中有效搜索更新的文档”(据我所知,这是更正确的定义),那么它总是会发生。
请注意,部分更新后,文档的整个旧副本将保留在索引中,标记为已删除(直到从头开始下一次完全重新索引或“优化”为止)。
为了避免这种情况,可以使用子代关系代替嵌套对象。可以在不触摸父文档的情况下添加/删除/更新子对象(但是这样做当然要付出代价-在内存中维护子父关系林等)。
| 归档时间: |
|
| 查看次数: |
30882 次 |
| 最近记录: |