0

Running a java spring project (v2) with mongo v4. Trying to update a nested object and been reading a lot on SO but havent found any good solution.

I have something like the following:

menu {
   id
   name
   categories {
     id
     name
     products {
       id
       price
       referenceProduct {
         id
         name
       }
     }
   }
}

When I update a reference product, then I want all my referenceproducts in menus to be updated as well.

I have tried the following:

Query query = Query.query(Criteria
      .where("menuProductCategories.menuProducts.refProduct.id").is(refProduct.getId())
    );

Update update = new Update().set("menuProductCategories.$.menuProducts.$.refProduct", refProduct);

But then I get the too many positional elements found.

Next idea would be to use arrayfilters using something like the following (just trying to update name prop to 'TEST'):

Bson filter = Filters.eq("menuProductCategories.menuProducts.refProduct.id", new ObjectId(refProduct.getId()));
Bson update = new Document("$set", new Document().append("menuProductCategories.$[i].menuProducts.$[j].refProduct.name", "TEST"));

But then I get stuck on how to specify my arrayfilters since they all assume that you know the index, which I don't since I want to do a full search and update all that matches my initial criteria.

Any ideas? Of course I could just retrieve all the menus and iterate over them, but I would love to find a small neat solution.

1 Answer 1

2

You can use below query in 3.6 server version with 3.6.x mongodb driver.

 MongoCollection<Document> collection = mongoTemplate.getDb().getCollection("col");

 Bson update = Updates.set("menuProductCategories.$[].menuProducts.$[i].refProduct.name", "TEST");
 Bson filter = Filters.eq("i.refProduct.id", new ObjectId(refProduct.getId()));
 UpdateOptions updateOptions = new UpdateOptions().arrayFilters(Arrays.asList(filter));

 collection.updateOne(null, update, updateOptions);
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for answer, it worked but I had to set a filter for the first parameter in UpdateOne. It crashes when I want to replace the whole object: Bson update = Updates.set("menuProductCategories.$[].menuProducts.$[i].refProduct", refProduct); Any ideas on this?
Yw. do you see any error when it crashes ? Is it on application side or mongo side ?
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class se.a.b.model.RefProduct I guess it somehow needs to know that it is a refproduct? Do I need the object to bson?
Try registering the pojo codec( in 3.5.x driver ) and see if it gets picked up. Something like CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(MongoClient.getDefaultCodecRegistry(), CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())); MongoDatabase database = mongoClient.getDatabase(db).withCodecRegistry(pojoCodecRegistry); More here
Tried that but it didnt work, same problem. I think it has some problem to replace the refProduct since it is inside another object (Menu), it would probably work if it was in a RefProduct Collection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.