Exception in thread "main" com.mongodb.MongoWriteException: The array filter for identifier 'element' was not used in the update { $set: { leave_history: { leave_history.$[element].pl_used: 6, leave_history.$[element].cl_used: 6, leave_history.$[element].sl_used: 6 } } } at com.mongodb.client.internal.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:1060) at com.mongodb.client.internal.MongoCollectionImpl.executeUpdate(MongoCollectionImpl.java:1037) at com.mongodb.client.internal.MongoCollectionImpl.updateOne(MongoCollectionImpl.java:622) at MongoDBExample.displayempDocs(MongoDBExample.java:226) at MongoDBExample.main(MongoDBExample.java:253)
Consider the document
ali@MongoDB>db.employees.find({$and : [{empno:7839},{leave_history:{$exists:true}}]}).pretty()
{
"_id" : ObjectId("5e907ad23997181dde06e8fc"),
"empno" : 7839,
"ename" : "KING",
"mgrno" : 0,
"hiredate" : "1990-05-09",
"sal" : 100000,
"deptno" : {
"_id" : ObjectId("5e9065f53997181dde06e8f8")
},
"username" : "none",
"password" : "none",
"is_admin" : "N",
"is_approver" : "Y",
"is_manager" : "Y",
"user_role" : "AP",
"admin_approval_received" : "Y",
"active" : "Y",
"created_date" : "2020-04-10",
"updated_date" : "2020-04-10",
"application_usage_log" : [
{
"logged_in_as" : "AP",
"log_in_date" : "2020-04-10"
},
{
"logged_in_as" : "EM",
"log_in_date" : ISODate("2020-04-16T07:28:11.959Z")
}
],
"leave_history" : [
{
"calendar_year" : 2020,
"pl_used" : 1,
"cl_used" : 2,
"sl_used" : 0
},
{
"calendar_year" : 2021,
"pl_used" : 0,
"cl_used" : 0,
"sl_used" : 0
}
]
}
I am trying to update the field [leave_history] that is an array of sub-documents containing four other fields. Specifically the fields pl_used,cl_used and sl_used need to be updated. The following snippet was used
//Update the leaves used for this employee.
query = and(eq("empno",7839),exists("leave_history",true)); // parent document query
Bson update = new Document("$set",new Document("leave_history",new Document("leave_history.$[element].pl_used",6)
.append("leave_history.$[element].cl_used", 6).append("leave_history.$[element].sl_used", 6)));
UpdateOptions update_options = new UpdateOptions(); // setting the options for sub-document arrays.
List<Bson> array_filters = new ArrayList<Bson>(); // array list of filters.
Bson arrayElement = Filters.eq("element.calendar_year", year); //creating the array element
array_filters.add(arrayElement); // add the filter element to the list of array list filters.
update_options.arrayFilters(array_filters); // add the filters to the updateOptions.
update_result = generic_collection.updateOne(query, update, update_options); // calling the update.
But that raises the exception stated above. What does the exception mean ? Is there another way to update multiple fields with an array of sub-documents ?.
Hello Joe, I have the query that is needed for the Mongo Shell. Here is what I am using
db.employees.updateOne({empno:7839},{$set: {"leave_history.$[elem].pl_used":6,"leave_history.$[elem].cl_used":6,"leave_history.$[elem].sl_used":6}},{arrayFilters:[{"elem.calendar_year":2020}]})
I run into a problem when I try to replicate this within a Java program.
The update operation that you are ultimately running appears to be:
db.collection.update({"empno":7839), "leave_history",{$exists:true}},
{"$set":{ "leave_history":{
"leave_history.$[element].pl_used":6,
"leave_history.$[element].cl_used":6,
"leave_history.$[element].sl_used":6
}}},
{"arrayFilters":[{"element.calendar_year":year}]}
)
The problem is that the $set
is attempting to replace the leave_history
array with an object containing a leave_history
object, so there is never an array element comparison.
You just need to remove one layer of document so that your update is:
db.collection.update({"empno":7839), "leave_history",{$exists:true}},
{"$set":{
"leave_history.$[element].pl_used":6,
"leave_history.$[element].cl_used":6,
"leave_history.$[element].sl_used":6
}},
{"arrayFilters":[{"element.calendar_year":year}]}
)