How to add a json in a nested array of a mongodb document using Spring?

别等时光非礼了梦想. 提交于 2021-02-02 09:58:16

问题


Document stored in 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"
                }]
            }]
        }]
    }
    ]
}

Now, I need to add another customer json to the array "CUSTOMERS" inside "GROUPS" in the same document above. The customer json would be like this:

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

I tried this:


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


But, I am getting the exception: org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 28 (PathNotViable): 'Cannot create field 'GROUPS' in element


[ EDIT ADD ]

I was able to update it using the filtered positional operator. Below is the query I used:

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

Actually, this query updated all the fields irrespective of the filter conditions. So. I tried this but I am facing syntax exception. Please help.

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

Update: April 1,2020

The code I tried:

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);

The below exception is thrown:

ERROR com.sample.amt.mongoTemplate.MongoOperations - Exception in count(query, collectionName,key,env) :: org.springframework.dao.DataIntegrityViolationException: Error parsing array filter :: caused by :: Expected a single top-level field name, found 'SERVICE_CATEGORY' and 's'; nested exception is com.mongodb.MongoWriteException: Error parsing array filter :: caused by :: Expected a single top-level field name, found 'SERVICE_CATEGORY' and 's'


回答1:


This update query adds the JSON to the nested array, "SERVICES.VERSIONS.GROUPS.CUSTOMERS", based upon the specified filter conditions. Note that your filter conditions direct the update operation to the specific array (of the nested arrays).

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

Few things to note when updating documents with nested arrays of more than one level nesting.

  • Use the all positional operator $[] and the filtered positional operator $[<identifier>], and not the $ positional operator. With filtered positional operator specify the array filter conditions using the arrayFilters parameter. Note that this will direct your update to target the specific nested array.
  • For the filtered positional operator $[<identifier>], the identifier must begin with a lowercase letter and contain only alphanumeric characters.

References:

  • Array Update Operators
  • db.collection.update() with arrayFilters



回答2:


Thanks to @prasad_ for providing the query. I was able to eventually convert the query successfully to code with Spring data MongoTemplate's updateMulti method. I have posted the code below:

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);


来源:https://stackoverflow.com/questions/60701824/how-to-add-a-json-in-a-nested-array-of-a-mongodb-document-using-spring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!