I have a Document
that has an array field called listsOfItems
. Its contents are Documents
and they all contain another array field called setOfItems
, which is composed of Document
.
So the structure is like listsOfItems
(Array of Documents
) > setOfItems
(Array of Documents
) > Items
(Documents
)
Each Document
in listsOfItems
has a listId
field which is used to uniquely identify it's contents.
Each Document
in setOfItems
has a itemId
field which is used to uniquely identify it's contents.
I want to change the value of a field inside a Document
of setOfItems
given the listId
and itemId
.
Currently, I'm trying to do it like this:
final var filter = Filters.and(Filters.eq("accessDetail.email", email),
Filters.eq("listsOfItems.listId", listId),
Filters.eq("listsOfItems.$.setOfItems.itemId", itemId));
final var updateQuery = Updates.set("listsOfItems.$.setOfItems.obtained", BsonBoolean.TRUE);
usersCollection.findOneAndUpdate(filter, updateQuery)
The query doesn't match any Document
I cannot access the elements in the setOfItems
by directly accessing them by index because they are ordered by other indexes and not according to their itemId
field.
What is the right query for performing the update given the condition?
EDIT1
I have replaced my filter
to:
final var filter = Filters.and(Filters.eq("accessDetail.email", email),
Filters.elemMatch("listsOfItems",
Filters.eq("listId", listId)),
Filters.elemMatch("listsOfItems.setOfItems",
Filters.eq("itemId", itemId)));
Now I get the error message: 'Cannot create field 'obtained' with the correct sub-document that it should make changes in.
The issue boils down to the updateQuery
.
To do this, you need to make use of arrayFilters.
Document filter = new Document("base-doc-field","<value>");//query for base doc
//fields if any
Document updateDoc = new Document("$inc",
new Document("listOfItems.$[elem].setOfItems.$[elem1].fieldName","value to
update"));
//prepare array filters.
List<Bson> arrayFilters = new ArrayList<>();
arrayFilters.add(new Document("elem.listId","<list_id>"));
arrayFilters.add(new Document("elem1.itemId","<item_id>"));
//prepare update options, and set these array filters to update options.
UpdateOptions options = new UpdateOptions().
arrayFilters(filterArr).bypassDocumentValidation(true);
//execute update method.
collection.updateOne(filter,updateDoc,options);