Весеннее обновление критериев MongoDB

Как я могу написать запрос для обновления «contacts.collection.value._class = SubClass2» и установить значение xyz с критериями Spring Mongodb?

{ "_class" : "MyClass",
  "_id" : ObjectId( "51ecc95503644e4489bb742e" ),
  "contacts" : [ 
    { "property1" : "Value1",
      "property2" : "Value2",
      "collection" : [ 
        { "value" : "1",
          "_class" : "SubClass1" }, 
        { "value" : "2",
          "_class" : "SubClass2" }, 
        { "value" : "2",
          "_class" : "SubClass3" }, 

Я пытаюсь сделать это с помощью класса Spring Data Mongo Criteria.

Пока я получил это, но это не работает

            query = new Query(Criteria.where("_id").is(myClassId)
                    .and("contacts.collection.value").is("2")
                    .and("contacts.collection._class").is("SubClass2"));
            update.set("contacts.collection.$.value", "3");
            mongoTemplate.updateFirst(query, update, MyClass.class);

Я получаю эту ошибку;

java.lang.IllegalArgumentException: значение свойства не найдено в ...!

Примечания:

  1. Коллекция "контакты" представляет собой список некоторого интерфейса.
  2. Я продезинфицировал имена переменных и имена классов.
  3. Если вы не знаете, как это сделать с помощью Criteria, пожалуйста, дайте мне код Java.

Спасибо

Добавление трассировки стека

Вот трассировка стека

java.lang.IllegalArgumentException: No property xyz found on com.blah.SomeInterface!
        at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentPropertyPath(AbstractMappingContext.java:225) ~[spring-data-commons-1.5.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.convert.QueryMapper.getPath(QueryMapper.java:202) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.convert.QueryMapper.getTargetProperty(QueryMapper.java:190) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObject(QueryMapper.java:86) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.MongoTemplate$11.doInCollection(MongoTemplate.java:925) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.MongoTemplate$11.doInCollection(MongoTemplate.java:920) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:388) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.MongoTemplate.doUpdate(MongoTemplate.java:920) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]
        at org.springframework.data.mongodb.core.MongoTemplate.updateFirst(MongoTemplate.java:902) ~[spring-data-mongodb-1.2.1.RELEASE.jar:na]

Основываясь на ответе Джейза, я написал обновление с помощью RoboMongo, и оно работает, обновляет результат запроса!

db.myDB.update(
{
"_id":ObjectId("51ecc95503644e4489bb742e"),
"contacts.collection._class": "SubClass1",
"contacts.collection.value": "1",
},
{ 
    $set: { 'contacts.0.collection.$.value': '3' } 
},
{ getLastError: 1 });

Но когда я пытаюсь сделать это с помощью mongoTemplate, ничего не обновляется.


person aug70co    schedule 22.07.2013    source источник
comment
Не могли бы вы опубликовать всю трассировку стека?   -  person udalmik    schedule 22.07.2013


Ответы (2)


запрос даст вам индекс массива коллекций, который соответствует критериям запроса. С вашей структурой данных вам нужны два индекса массива, один для контактов и один для коллекции, что невозможно (насколько я знаю). Вам нужно знать положение либо элемента массива контактов, либо элемента массива коллекции. Предположим, вы знаете положение элемента массива контактов. если это 0-я позиция, вот ваш полный запрос:

query = new Query(new Criteria().andOperator(
        Criteria.where("_id").is(myClassId),
        Criteria.where("contacts.collection.value").is("2"),
        Criteria.where("contacts.collection._class").is("SubClass2"));
        update.set("contacts.0.collection.$.value", "3");
        mongoTemplate.updateFirst(query, update, MyClass.class);
person Jayz    schedule 23.07.2013
comment
Спасибо @Jayz. Это правильный запрос, но обновление не работает. Контакты — это коллекция, а коллекция — это коллекция. Итак, как мне указать значение, которое находится внутри коллекции другой коллекции? Ниже не работает - contact.collection.$.value Также пробовал - contact.0.collection.$.value Тоже не работает - person aug70co; 27.07.2013
comment
к сожалению ничего не обновляет. Я добавил WriteResult, чтобы увидеть, что результат getN() равен 0, а результат.getLastError().getErrorMessage() равен нулю. - person aug70co; 28.07.2013
comment
Вы проверили индекс массива коллекции контактов, которую хотите обновить? Я создал тестовый класс, создал весь документ, проверил (в оболочке mongo), индекс массива контактов, для которых необходимо обновить коллекцию, был равен 0, затем запустил запрос с использованием тестового класса, и это сработало. значение в поддокументе (коллекция-коллекция) обновлено. для вашего случая, если у вас есть точно такой же документ, который вы указали здесь, индекс массива равен 1, поэтому используйте: update.set(contacts.1.collection.$.value, 3); - person Jayz; 28.07.2013
comment
Я смог решить эту проблему, используя точные индексы для обеих коллекций. Я ожидал, что смогу написать запрос на обновление без предоставления такой информации, но, похоже, на данный момент это невозможно. Еще раз спасибо за ваш ответ. - person aug70co; 30.07.2013
comment
Я уверен, что вы можете избежать передачи точного индекса в одной коллекции, используя правильные критерии. Пожалуйста, отметьте ответ как правильный, если он помог вам решить проблему. - person Jayz; 30.07.2013

Отфильтрованный позиционный оператор $ идентифицирует элементы массива, соответствующие условиям arrayFilters для операции обновления.

запрос = новый запрос (новый критерий (). и оператор ( критерий. где («_id»). "contacts.collection._class").is("SubClass2")); update.set("contacts.$.collection.$.value", newValueToUpdate в определенной позиции); mongoTemplate.updateFirst(запрос, обновление, MyClass.class );

person Nithesh P    schedule 25.02.2020