3

I've created a collection with following insert statement

db.test.insert({
"_id": 1,
"updatedAt": ISODate("2016-05-27T05:37:44.928Z"),
"created_at": ISODate("2016-05-13T09:41:23.000Z"),
"batchId": "BATCH-Con-0",
"size": 7,
"currentlySubscribed": 0,
"startDate": ISODate("2016-05-15T18:30:00.000Z"),
"endDate": ISODate("2016-07-08T18:30:00.000Z"),
"dailyHours": 6,
"trainer": null,
"status": "Started",
"attendance": [
 {
 "date": ISODate("2016-05-04T18:30:00.000Z"),
 "students": [
 {
 "studentId": 1,
 "entryTime": ISODate("1969-12-31T19:31:00.000Z"),
 "exitTime": ISODate("1969-12-31T19:31:00.000Z"),
 "attendanceStatus": "Present"
 },
 {
 "studentId": 2,
 "entryTime": ISODate("1969-12-31T19:31:00.000Z"),
 "exitTime": ISODate("1969-12-31T19:31:00.000Z"),
 "attendanceStatus": "Present"
 },
 {
 "studentId": ("5735a3266c1e1dc423c302cf"),
 "entryTime": ISODate("1969-12-31T19:31:00.000Z"),
 "exitTime": ISODate("1969-12-31T19:31:00.000Z"),
 "attendanceStatus": "Present"
 }
 ]
 },
 {
 "date": ISODate("2016-05-05T18:30:00.000Z"),
 "students": [
 {
 "studentId": 1,
 "entryTime": ISODate("1969-12-31T19:31:00.000Z"),
 "exitTime": ISODate("1969-12-31T19:31:00.000Z"),
 "attendanceStatus": "Present"
 },
 {
 "studentId": 2,
 "entryTime": ISODate("1969-12-31T19:31:00.000Z"),
 "exitTime": ISODate("1969-12-31T19:31:00.000Z"),
 "attendanceStatus": "Present"
 },
 {
 "studentId": 3,
 "entryTime": ISODate("1969-12-31T19:31:00.000Z"),
 "exitTime": ISODate("1969-12-31T19:31:00.000Z"),
 "attendanceStatus": "Present"
 }
 ]
 }
 ]})

Now I want to delete the attendance record of some of the students with this query:

db.test.update({},{$pull: {"attendance.$.students": {"studentId":{$in:[1,2,3]}}}},{multi:true})

But this gives me an error stating "The positional operator did not find the match needed from the query. Unexpanded update: attendance.$.students"

Md Haidar Ali Khan
6,5339 gold badges40 silver badges62 bronze badges
asked May 27, 2016 at 11:58

2 Answers 2

3

If you want to use the $ positional operator, you have to have matched the array items already, something like this:

db.test.update(
 {"attendance.students.studentId":{$in:[1,2,3]}},
 {$pull: {"attendance.$.students": {studentId: {$in:[1,2,3]}}}},
 {multi:true}
)

Remember that this will only update the first matching item in the attendance array in each document, so you will have to run this update more than once to make it update each attendance item.

answered Feb 27, 2017 at 13:50
0

such a complex manipulations a very hard to achieve.

Workaround to that limitation is to use forEach loop on resultSet and interate every document

var searchCriteria = [1, 2, 3];
db.test.find({
 "attendance.students.studentId" : {
 $in : searchCriteria
 }
}).forEach(function (myDoc) {
 var len = myDoc.attendance.length;
 for (var i = 0; i < len; i++) {
 var x = myDoc.attendance[i];
 var xLen = x.students.length;
 var newArrayWithStudents = [];
 for (var j = 0; j < xLen; j++) {
 if (searchCriteria.indexOf(x[j].studentId) < 0) {
 newArrayWithStudents.add(x[j]);
 };
 };
 myDoc.attendance[i] = newArrayWithStudents;
 };
 myDoc.save();
});
answered May 27, 2016 at 14:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.