【问题标题】:Use UpdateByQueryAsync to make a partial update in Elasticsearch using NEST使用 UpdateByQueryAsync 在 Elasticsearch 中使用 NEST 进行部分更新
【发布时间】:2021-10-17 17:25:26
【问题描述】:

我的数据库中有两个具有子/父关系的表,并创建了一个 Elasticsearch 索引,其中包含来自这两个表的记录的组合列表。父记录的Children 字段中可以有多个记录。如果我有两个表的两个索引并且想要部分更新每个索引,我会使用 NEST 使用这个命令:

await elasticClient.UpdateAsync<object>(id, u =>
                u.Index(indexName).Doc(updatedFieldsCollection)
            );

但问题是我的索引不是一个简单的索引,每个父级的所有子记录都在其children 字段中,这是一个列表,所以当我的子表中的记录被更新时,我不确定我该怎么做在 Elasticsearch 索引中找到该条目并对其进行部分更新。下面的查询似乎识别了我正在寻找的记录,但与上面的命令不同,没有.Doc 方法可以用来部分更新我感兴趣的索引部分(这是上的子元素之一Children列表):

await elasticClient.UpdateByQueryAsync<ChildParentModel>(u => u
                .Query(q => q
                    .Term(f => f
                        .Children.First().Uid, id)
                )
            );

知道我该怎么做吗?

【问题讨论】:

    标签: elasticsearch nest


    【解决方案1】:

    当您使用 Update By Query API 时,无法更新整个文档。相反,您可以使用脚本! 阅读documentaion

    代码:

    var scriptParams = new Dictionary<string, object> {{"paramName", "newValue"}};
    client.UpdateByQuery<ChildParentModel>(uq => uq
        .Query(q => q.Term(f => f.Children.First().Uid, id))
        .Script(s => s
            .Source("ctx._source.propertyName = params.paramName;")
            .Params(scriptParams)
         )
    );
    

    【讨论】:

    • 谢谢迈赫迪。我不是要更新整个文档。恰恰相反。我只需要更新文档的一部分。我有一个动态对象,其中包含更新的属性及其新值。我不确定如何使用 Script 方法仅更新这些属性。此外,ScriptDescriptor 对象似乎只有 Source()Id() 方法。在您的示例中,我没有看到任何 Inline() 方法。我错过了什么吗?
    • 嗨@MarChal!我已经更新了我的答案。希望它能按您的预期工作。
    • 谢谢伙计。我设法让更新工作,但问题是更新是在父对象的 paramName 上完成的(如果它碰巧有相同的字段)。原因是查询返回具有提供的 id 的孩子的父母。我需要更改查询以使其返回孩子。我的意思是 _source 指向父文档。不过我不知道该怎么做。
    • @MarChal 例如,如果你有这样的类: public class ParentClass { public ChildClass Child { get;放; } } 和 public class ChildClass { public string Name { get;放; } } 您可以使用以下方法轻松访问和更新 ChildClass.Name 属性:ctx._source.child.name
    • 我的场景有点复杂。子字段实际上是一个数组,我应该更新该数组的一个元素,其 id 与查询中使用的参数 (id) 匹配。我想出了这个,但它对我来说看起来不是很整洁:.Source("for (int j = 0; j &lt; ctx._source.children.size(); j++){ if (ctx._source.children[j].uid == params.uid){ctx._source.children[j].name=params.name; ...; break;}}") 我有多个字段要在该项目中更新,因此我必须动态构建字符串以包含所有更新的字段。我希望有更好的方法来做到这一点。
    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多