如何使用 Nest Elasticsearch 更新嵌套对象?

我有产品索引,为简单起见,它有两个字段Id和ProductAttributes作为嵌套对象,定义如下:


public class ProductType

{

    public Guid Id { get; set; }


    public List<ProductAttribute> ProductAttributes { get; set; }

 }


public class ProductAttribute

{

    public Guid Id { get; set; }


    public string Name { get; set; }


    public string Value { get; set; }

}

以及以下映射:


elasticClient.CreateIndex("product", i => i

       .Settings(s => s

                 .NumberOfShards(2)

                 .NumberOfReplicas(0)

                 )

                 .Mappings(m => m

                   .Map<ProductType>(map => map

                         .AutoMap()

                         .Properties(p => p

                          .Nested<ProductAttribute>(n => n

                            .Name(c => c.ProductAttributes)

                            .AutoMap()

                            .Properties(nc => nc

                               .Keyword(t => t

                                   .Name(nn => nn.Name)

                                   )

                              .Keyword(t => t

                                .Name(nn => nn.Value)

                             )

                  )

             )

现在我正在尝试更新嵌套对象中的名称字段,并且我已尝试使用脚本更新实现它,如下所示:


        var scriptParams = new Dictionary<string, object>

                            {

                                {"name", "new name"}

                            };


        var result = elasticClient.UpdateByQuery<ProductType>(u => u

                              .Script(sn => sn

                                   .Inline(

                                          $"ctx._source.productAttributes= params.name;" 

                                      )

                                  .Params(scriptParams)

                              )

                              .Conflicts(Conflicts.Proceed)

                              .Refresh(true)

                          );

但是使用上面的查询我无法更新嵌套对象,您能告诉我如何使用嵌套ES使用_update_by_query api更新嵌套对象吗?


芜湖不芜
浏览 270回答 2
2回答

慕的地8271018

最后,我发现了如何根据特定的嵌套对象的id仅更新其名称属性,如下所示:var result = elasticClient.UpdateByQuery<ProductType>(u => u&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Query(q => q&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Nested(n => n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Path(Infer.Field<ProductType>(ff => ff.ProductAttributes))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Query(nq => nq&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Term(Infer.Field<ProductType>(ff => ff.ProductAttributes.First().Id), productAttributeId)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Script(ss => ss.Inline("if (ctx._source.productAttributes != null){for (item in ctx._source.productAttributes){if (item.id == params.id) {item.name = params.name;}}}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Params(new Dictionary<string, object>()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{"id", productAttributeId},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{"name", productAttributeName}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}).Lang("painless")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Conflicts(Conflicts.Proceed)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Refresh(true)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );这里生成的查询:&nbsp;POST product/producttype/_update_by_query?conflicts=proceed&refresh=true&nbsp;{&nbsp; "query": {&nbsp; &nbsp; "bool": {&nbsp; &nbsp; &nbsp; "must": [&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "nested": {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "query": {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "term": {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "productAttributes.id": {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "value": "563243f0-8fbb-4adf-a78d-1339e5971a43"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "path": "productAttributes"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; }&nbsp; },&nbsp; "script": {&nbsp; &nbsp; "params": {&nbsp; &nbsp; &nbsp; &nbsp; "id":"563243f0-8fbb-4adf-a78d-1339e5971a43",&nbsp; &nbsp; &nbsp; &nbsp; "name": "CPU"&nbsp; &nbsp; },&nbsp; &nbsp; "lang": "painless",&nbsp; &nbsp; "inline": "if (ctx._source.productAttributes != null){for (item in ctx._source.productAttributes){if (item.id == params.id) {item.name = params.name;}}}"&nbsp; }}那么上面的查询有什么作用:它首先搜索产品属性为 563243f0-8fbb-4adf-a78d-1339e5971a43 ID 的产品,然后循环访问 productAttribute 嵌套对象以仅更新具有该 ID 的属性,然后再次为文档重新编制索引。我希望我的答案可以帮助其他在 Elasticsearch 中更新嵌套对象时遇到问题的人。

MMTTMM

看起来像问题在这里 $“ctx._source.productAttributes= params.name;”productAttributes 是一个对象(嵌套对象),params.name 是一个值(字符串),ES 在查询响应中抱怨什么。不确定您到底想做什么,如果您的要求是更新所有产品属性元素的名称,您可以尝试以下操作:&nbsp; &nbsp; &nbsp; &nbsp; var result = elasticClient.UpdateByQuery<ProductType>(u => u&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Index("product")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Script(ss => ss.Source("for(int i=0; i<ctx._source.productAttributes.size(); i++){HashMap myKV = ctx._source.productAttributes.get(i);myKV.put(params.item.fieldName, params.item.fieldValue);}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Params(d => d.Add("item", new Dictionary<string, object>()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {"fieldName", "name" },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {"fieldValue", "new name" }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })).Lang("painless")));
打开App,查看更多内容
随时随地看视频慕课网APP