Mongoose Relationships Locating Embedded Subdocuments
Learning Objective: By the end of this lesson, students will be able to retrieve embedded subdocuments using an id in Mongoose.
The challenge with embedded documents
While embedding documents in Mongoose has many advantages, it introduces complexity when modifying embedded subdocuments. This is because subdocuments are not compiled into models and therefore lack model methods.
In order to perform database operations on a subdocument, developers must interact with the parent document in which the subdocument is held.
Finding a subdocument in a document array
Before modifying or removing a subdocument, you first have to find it within the parent document. Mongoose’s subdocument arrays have an id() method that allows you to find a specific subdocument by its _id.
Take a look at this example of the id() method using a todo and its subtasks:
const subtask = todo.subtasks.id(subtaskId);
Once you have retrieved the specific subdocument, you can perform various operations on it. To save changes, we’ll always need to call save() on the parent, as the subdocument does not exist in its own collection.
🚨 The
id()method on a document array is different from the_idproperty of a document. Every subdocument still has its own unique_id.
Implementing the id() method
Let’s create a function to demonstrate finding a subdocument in an array. Add the following to queries.js at the bottom of the Query Functions section:
const findSubtask = async () => {
// Replace 657b25adc8146427465857d7 with an existing Todo ID
const todoId = '657b25adc8146427465857d7';
// Replace 6580677cf30bfef697ae046f with an existing Subtask ID
const subtaskId = '6580677cf30bfef697ae046f';
const todo = await Todo.findById(todoId);
const subtask = todo.subtasks.id(subtaskId);
console.log('Subdocument:', subtask);
};
🚨 Make sure that you replace
todoIdandsubtaskIdwith actualObjectIdsfrom your database.
Next, call upon findSubtask within the runQueries function:
const runQueries = async () => {
console.log('Queries running.');
await findSubtask();
};
Run the queries.js file with the following command:
node queries.js
You should see a similar output in your terminal:
Subdocument: {
text: 'Learn how props work',
isComplete: false,
_id: new ObjectId('6580677cf30bfef697ae046f')
}