为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
芜湖不芜 2022-08-20 16:12:17
我有产品索引,为简单起见,它有两个字段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更新嵌套对象吗?
查看完整描述

2 回答

?
慕的地8271018

TA贡献1796条经验 获得超4个赞

最后,我发现了如何根据特定的嵌套对象的id仅更新其名称属性,如下所示:


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

                  .Query(q => q

                        .Nested(n => n

                          .Path(Infer.Field<ProductType>(ff => ff.ProductAttributes))

                          .Query(nq => nq

                              .Term(Infer.Field<ProductType>(ff => ff.ProductAttributes.First().Id), productAttributeId)

                          )

                        )

                  )

                  .Script(ss => ss.Inline("if (ctx._source.productAttributes != null){for (item in ctx._source.productAttributes){if (item.id == params.id) {item.name = params.name;}}}")

                     .Params(new Dictionary<string, object>()

                     {

                         {"id", productAttributeId},

                         {"name", productAttributeName}

                     }).Lang("painless")

                  )

                  .Conflicts(Conflicts.Proceed)

                  .Refresh(true)

              );

这里生成的查询:


 POST product/producttype/_update_by_query?conflicts=proceed&refresh=true 

{

  "query": {

    "bool": {

      "must": [

        {

          "nested": {

            "query": {

              "term": {

                "productAttributes.id": {

                  "value": "563243f0-8fbb-4adf-a78d-1339e5971a43"

                }

              }

            },

            "path": "productAttributes"

          }

        }

      ]

    }

  },

  "script": {

    "params": {

        "id":"563243f0-8fbb-4adf-a78d-1339e5971a43",

        "name": "CPU"

    },

    "lang": "painless",

    "inline": "if (ctx._source.productAttributes != null){for (item in ctx._source.productAttributes){if (item.id == params.id) {item.name = params.name;}}}"

  }

}

那么上面的查询有什么作用:


它首先搜索产品属性为 563243f0-8fbb-4adf-a78d-1339e5971a43 ID 的产品,然后循环访问 productAttribute 嵌套对象以仅更新具有该 ID 的属性,然后再次为文档重新编制索引。


我希望我的答案可以帮助其他在 Elasticsearch 中更新嵌套对象时遇到问题的人。


查看完整回答
反对 回复 2022-08-20
?
MMTTMM

TA贡献1869条经验 获得超4个赞

看起来像问题在这里 $“ctx._source.productAttributes= params.name;”


productAttributes 是一个对象(嵌套对象),params.name 是一个值(字符串),ES 在查询响应中抱怨什么。


不确定您到底想做什么,如果您的要求是更新所有产品属性元素的名称,您可以尝试以下操作:


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

            .Index("product")

            .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);}")

                        .Params(d => d.Add("item", new Dictionary<string, object>()

                        {

                            {"fieldName", "name" },

                            {"fieldValue", "new name" }

                        })).Lang("painless")));


查看完整回答
反对 回复 2022-08-20
  • 2 回答
  • 0 关注
  • 269 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信