4

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?

1

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

4 Comments

@Dano, I ended up adding '_id' : new ObjectID(), to the sub-document to be inserted, so MongoDB used that. I appreciate the heads up on the index. Yes, I will be querying frequently, so I will add an index in the collection.
Is there any way to make '_id' : new ObjectID(), work in mongo Shell ?
so if you explicitly assign object _id to a sub-document, this _id WILL NOT be automatically indexed, and query will be slow, right?
of course, no! indexing doesn't depend if the value is autogenerated or not. you can use ObjectIDs, UUID, ULID, integer or whatever you want. But you will need to ensureIndex on it.
4

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.

5 Comments

I am not familiar with MongooseArrays. Is this a separate library I need to require into the project? I notice this use of ES6 constructs with const and await. That is part of generator functions, if I recall correctly from past reading.
This is part of mongoose, see on the docs link i put. I just used es6 to be easier to understand the example, it's not an obligation.
You're welcome. Today I am working on a project and I am using mongoose, I passed through this same situation a couple of days ago.
This is the most correct answer for latest mongoose versions.
Any one, I think the questions try to indicate about the deeply nested sub documents.

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.