【问题标题】:How to add a json in a nested array of a mongodb document using Spring?如何使用 Spring 在 mongodb 文档的嵌套数组中添加 json?
【发布时间】:2020-06-27 07:41:50
【问题描述】:

存储在 mongodb 中的文档:


{
"CNF_SERVICE_ID":"1",
"SERVICE_CATEGORY":"COMMON_SERVICE",
"SERVICES":[{
    "SERVICE_NAME":"Authentication Service",
    "VERSIONS":[{
            "VERSION_NAME":"AuthenticationServiceV6_3",
            "VERSION_NUMBER":"2",
            "VERSION_NOTES":"test",
            "RELEASE_DATE":"21-02-2020",
            "OBSOLETE_DATE":"21-02-2020",
            "STATUS":"Y",
            "GROUPS":[{
                "GROUP_NAME":"TEST GROUP",
                "CREATED_DATE":"",
                "NODE_NAMES":[
                    ""
                    ],
                "CUSTOMERS":[{
                    "CUSTOMER_CONFIG_ID":"4",
                    "ACTIVATION_DATE":"21-02-2020",
                    "DEACTIVATION_DATE":"21-02-2020",
                    "STATUS":"Y"
                }]
            }]
        }]
    }
    ]
}

现在,我需要将另一个客户 json 添加到上述同一文档中“GROUPS”内的数组“CUSTOMERS”中。客户 json 是这样的:

{
    "CUSTOMER_CONFIG_ID":"10",
    "ACTIVATION_DATE":"16-03-2020",
    "DEACTIVATION_DATE":"16-03-2021",
    "STATUS":"Y"
}

我试过这个:


Update update = new Update().push("SERVICES.$.VERSIONS.GROUPS.CUSTOMERS",customerdto);
mongoOperations.update(query, update, Myclass.class, "mycollection");


但是,我得到了异常:org.springframework.data.mongodb.UncategorizedMongoDbException: 命令失败,错误 28 (PathNotViable): 'Cannot create field 'GROUPS' in element


[编辑添加]

我能够使用过滤的位置运算符对其进行更新。以下是我使用的查询:

 update( 
   { "SERVICE_CATEGORY":"COMMON_SERVICE", "SERVICES.SERVICE_NAME":"Authentication Service", "SERVICES.VERSIONS.VERSION_NAME":"AuthenticationServiceV6_3"}, 
   { $push:{"SERVICES.$[].VERSIONS.$[].GROUPS.$[].CUSTOMERS": { "CUSTOMER_CONFIG_ID":"6", "ACTIVATION_DATE":"31-03-2020", "STATUS":"Y" } } } 
 );

实际上,此查询更新了所有字段,而与过滤条件无关。所以。我试过这个,但我面临语法异常。请帮忙。

update(
 {"SERVICE_CATEGORY":"COMMON_SERVICE"},
 {"SERVICES.SERVICE_NAME":"Authentication Service"},
 {"SERVICES.VERSIONS.VERSION_NAME":"AuthenticationServiceV6_3"}
 {
    $push:{"SERVICES.$[service].VERSIONS.$[version].GROUPS.$[group].CUSTOMERS":{
        "CUSTOMER_CONFIG_ID":"6",
        "ACTIVATION_DATE":"31-03-2020",
        "STATUS":"Y"
    }
    }
 },
 {
        multi: true,
        arrayFilters: [ { $and:[{ "version.VERSION_NAME": "AuthenticationServiceV6_3"},{"service.SERVICE_NAME":"Authentication Service"},{"group.GROUP_NAME":"TEST GROUP"}]} ]
    }
 );

更新:2020 年 4 月 1 日

我试过的代码:

validationquery.addCriteria(Criteria.where("SERVICE_CATEGORY").is(servicedto.getService_category()).and("SERVICES.SERVICE_NAME").is(servicedetail.getService_name()).and("SERVICES.VERSIONS.VERSION_NAME").is(version.getVersion_name()));
Update update=new Update().push("SERVICES.$[s].VERSIONS.$[v].GROUPS.$[].CUSTOMERS", customer).filterArray(Criteria.where("SERVICE_CATEGORY").is(servicedto.getService_category()).and("s.SERVICE_NAME").is(servicedetail.getService_name()).and("v.VERSION_NAME").is(version.getVersion_name()));
mongoOperations.updateMulti(validationquery, update, ServiceRegistrationDTO.class, collection, key,env);

抛出以下异常:

错误 com.sample.amt.mongoTemplate.MongoOperations - count(query, collectionName,key,env) :: org.springframework.dao.DataIntegrityViolationException 中的异常:解析数组过滤器时出错 :: 由 :: 预期单个顶部-level 字段名称,找到 'SERVICE_CATEGORY' 和 's';嵌套异常是 com.mongodb.MongoWriteException: Error parsing array filter :: 由 :: Expected a single top-level field name, found 'SERVICE_CATEGORY' and 's'

【问题讨论】:

  • 你必须使用$arrayFilters。位置$ 运算符不能用于遍历多个数组(您有嵌套数组)的查询。此外,发布更新操作的查询。
  • 是的。由于 $ 运算符不能多次使用,还有哪些其他方法可以实现此目的?
  • 这是一篇有类似问题的帖子(在嵌套数组中添加数组元素):stackoverflow.com/questions/60035042/…
  • @prasad_ 该帖子只有 2 层嵌套。即,数组内的数组。因此,位置操作员进行了操作。但是,就我而言,有 4 级嵌套。请建议我可以做些什么来向“客户”数组列表中添加一个元素。
  • $ positional $[<id>] filtered positional operator 之间有区别。我认为您必须尝试使用​​过滤位置运算符。另外,我在第一条评论中已经提到您必须发布(请更新您的问题)更新操作的 查询 方面。

标签: spring mongodb spring-data spring-mongodb


【解决方案1】:

此更新查询根据指定的过滤条件将 JSON 添加到嵌套数组 "SERVICES.VERSIONS.GROUPS.CUSTOMERS"。请注意,您的过滤条件将更新操作定向到(嵌套数组的)特定数组。

// JSON document to be added to the CUSTOMERS array
new_cust = { 
             "CUSTOMER_CONFIG_ID": "6", 
             "ACTIVATION_DATE": "31-03-2020", 
             "STATUS": "Y" 
}

db.collection.update( 
  { 
      "SERVICE_CATEGORY": "COMMON_SERVICE", 
      "SERVICES.SERVICE_NAME": "Authentication Service",
      "SERVICES.VERSIONS.VERSION_NAME": "AuthenticationServiceV6_3"
  }, 
  { 
      $push: { "SERVICES.$[s].VERSIONS.$[v].GROUPS.$[g].CUSTOMERS": new_cust } 
  },
  {
      multi: true,
      arrayFilters: [
          { "s.SERVICE_NAME": "Authentication Service" },
          { "v.VERSION_NAME": "AuthenticationServiceV6_3" },
          { "g.GROUP_NAME": "TEST GROUP" }
      ]
  }
);

更新具有多于一级嵌套的嵌套数组的文档时需要注意的事项。

  • 使用所有位置运算符$[] 和过滤后的位置运算符 运算符$[<identifier>]不是$位置运算符。 使用过滤位置运算符指定数组过滤条件 使用arrayFilters 参数。请注意,这会将您的更新定向到特定的嵌套数组。
  • 对于过滤的位置运算符$[<identifier>], 标识符必须以小写字母开头并且仅包含 字母数字字符。

参考资料:

【讨论】:

  • 感谢您的帮助!只是另一个疑问......如果arrayfilter是根据我们提供的条件进行过滤的,为什么甚至需要更新函数中的第一个参数?另外,请指导我如何使用 Spring MongoTemplate 方法 updateMulti 进行相同的查询。
  • 当集合中有多个文档时,初始过滤器只会选择与过滤器中初始条件匹配的文档。 arrayFilters 用于定位数组中的特定子文档。
  • 你使用的是什么版本的 Spring Data?
  • 好的。我使用的相关依赖的版本如下: spring-boot-starter-data-mongodb : 2.2.2.RELEASE -> mongodb-driver : 3.11.2 -> spring-data-mongodb : 2.2.3.RELEASE I还用我的最新代码更新了问题。
【解决方案2】:

感谢@prasad_ 提供查询。我最终能够使用 Spring data MongoTemplate 的 updateMulti 方法成功地将查询转换为代码。我已经发布了下面的代码:

Query validationquery = new Query();
                        validationquery.addCriteria(Criteria.where("SERVICE_CATEGORY").is(servicedto.getService_category()).and("SERVICES.SERVICE_NAME").is(servicedetail.getService_name()).and("SERVICES.VERSIONS.VERSION_NAME").is(version.getVersion_name()));

Update update=new Update().push("SERVICES.$[s].VERSIONS.$[v].GROUPS.$[].CUSTOMERS", customer).filterArray(Criteria.where("s.SERVICE_NAME").is(servicedetail.getService_name())).filterArray(Criteria.where("v.VERSION_NAME").is(version.getVersion_name()));    
                            mongoOperations.updateMulti(validationquery, update, ServiceRegistrationDTO.class, collection, key,env);
mongoTemplateobj.updateMulti(validationquery, update, ServiceRegistrationDTO.class, collection, key,env);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-03
    • 2023-03-20
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 2022-01-20
    • 2017-06-05
    • 1970-01-01
    相关资源
    最近更新 更多