Как добавить json во вложенный массив документа mongodb с помощью Spring? - PullRequest
0 голосов
/ 16 марта 2020

Документ хранится в 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 в массив "CUSTOMERS" внутри "GROUPS" в том же документе выше. Клиент 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): «Невозможно создать поле« GROUPS »в элементе


[EDIT ADD]

Мне удалось обновить его с помощью отфильтрованного позиционного оператора. Ниже приведен запрос, который я использовал:

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

Обновление: апрель 1,2020

Код, который я пробовал:

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

Выдается следующее исключение:

ОШИБКА ком. sample.amt.mongoTemplate.MongoOperations - Исключение в количестве (запрос, collectionName, ключ, env) :: org.springframework.dao.DataIntegrityViolationException: ошибка фильтра массива :: вызвана :: Ожидается одно имя поля верхнего уровня, найдено 'SERVICE_CATEGORY' и 's'; Вложенное исключение - com.mongodb.MongoWriteException: Ошибка разбора фильтра массива :: вызвано :: Ожидается одно имя поля верхнего уровня, найдено 'SERVICE_CATEGORY' и 's'

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Этот запрос на обновление добавляет JSON к вложенному массиву "SERVICES.VERSIONS.GROUPS.CUSTOMERS" на основе указанных условий фильтрации. Обратите внимание, что ваши условия фильтрации направляют операцию обновления в указанный c массив (из вложенных массивов).

// 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. Обратите внимание, что это приведет к тому, что ваше обновление будет направлено на указанный c вложенный массив.
  • Для отфильтрованного позиционного оператора $[<identifier>] идентификатор должен начинаться со строчной буквы и содержать только буквы алфавита c символов.

Ссылки:

0 голосов
/ 01 апреля 2020

Спасибо @prasad_ за предоставление запроса. Мне удалось в итоге успешно преобразовать запрос в код с помощью метода updateMulti данных Spring из MongoTemplate. Я разместил код ниже:

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