Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert and return ID of sub-document in MongoDB document sub-document array

My node.js application will insert a sub-document into a nested sub-document array field of the following MongoDB document, and I need to determine the ID of the newly inserted sub-document:

{
  "_id" : ObjectId("578d5a52cc13117022e09def"),
  "name" : "Grade 5 - Section A",
  "scores" : [{
    "studentId" : ObjectId("5776bd36ffc8227405d364d2"),
    "performance" : [{
      "_id" : ObjectId("57969b8fc164a21c20698261"),
      "subjectId" : ObjectId("577694ecbf6f3a781759c54a"),
      "score" : 86,
      "maximum" : 100,
      "grade" : "B+"
    }]
  }]
}

The sub-document looks like this:

{
  "subjectId" : ObjectId("5776ffe1804540e29c602a62"),
  "score" : 74,
  "maximum" : 100,
  "grade" : "A-"
}

I am adding the sub-document using the following Mongoose code:

Class.update({
  _id: '578d5a52cc13117022e09def',
  'scores.studentId': '5776bd36ffc8227405d364d2'
}, {
  $addToSet: {
    'scores.$.performance': {
      'subjectId' : '5776ffe1804540e29c602a62',
      'score' : 74,
      'maximum' : 100,
      'grade' : 'A-'
    }
  }
}, function(err, result) {
  if (err) {
    throw err;
  }
  console.log(result);
});

The subject sub-document gets added in the performance sub-document array which is itself nested in the scores sub-document array. Notice that the newly inserted sub-document is assigned with its own ID, as instituted by the defined schema. Even if I get back the entire document, that's not very helpful. I specifically need the ID of that newly inserted sub-document. What is the recommended approach to this problem?

like image 856
Web User Avatar asked Feb 06 '23 12:02

Web User


2 Answers

In this case I prefer pre-assign the ID to the sub-document (i.e. sub._id = ObjectId() or use uuid package if you prefer uuid): is clear and predictable.

Also remember that if you frequent query by a subdoc id is good to add (using ensureIndex()) an index for this use case in the collection.

like image 189
Dario Avatar answered Feb 09 '23 07:02

Dario


There is a good solution for that, try to use the methods create and push of the MongooseArrays.

In your code you could return the Student and do something like this:

const newPerformance = student.performance.create(newData);
student.performance.push(newPerformance);
const updatedStudent = await student.save();

if (updatedStudent) return newPerformance._id;

This is just a simple example.

Using the create method of MongooseArrays, link for doc, the mongoose will create an _id and do all the validations and casts it needs, so if the save process is fine the created subdocument you could just use the _id of the subdocument you got with the create method.

like image 29
matheus.rocha89 Avatar answered Feb 09 '23 07:02

matheus.rocha89