To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.
In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.
Parents of Subdocuments
We can get the parent document from a child document.
For example, we can write:
async function run() {
const mongoose = require('mongoose');
const connection = mongoose.createConnection('mongodb://localhost:27017/test');
const childSchema = new mongoose.Schema({ name: 'string' });
const parentSchema = new mongoose.Schema({
children: [childSchema],
child: childSchema
});
const Child = await connection.model('Child', childSchema);
const Parent = await connection.model('Parent', parentSchema);
const parent = new Parent({ child: { name: 'Matt' }, children: [{ name: 'Matt' }] })
await parent.save();
console.log(parent === parent.child.parent());
console.log(parent === parent.children[0].parent());
}
run();
Then both console log statements are true
because the parent
method returns the parent object of the child
and a subdocument in the children
fields.
If we have a deeply nested subdocument, we can call the ownerDocument
method to get the root document:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const parentSchema = new Schema({
level1: new Schema({
level2: new Schema({
test: String
})
})
});
const Parent = await connection.model('Parent', parentSchema);
const doc = new Parent({ level1: { level2: { test: 'test' } } });
await doc.save();
console.log(doc === doc.level1.level2.ownerDocument());
}
run();
We call the ownerDocument
method with on the level2
subdocument to get the root document.
Therefore, the console log should log true
.
Alternative Declaration Syntax for Arrays
We can declare nested documents in more than one way.
One way is to put the array straight into the schema object:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const parentSchema = new Schema({
children: [{ name: 'string' }]
});
const Parent = await connection.model('Parent', parentSchema);
const doc = new Parent({ children: { name: 'test' } });
await doc.save();
}
run();
We can also create a schema with the Schema
constructor:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const parentSchema = new Schema({
children: [new Schema({ name: 'string' })]
});
const Parent = await connection.model('Parent', parentSchema);
const doc = new Parent({ children: { name: 'test' } });
await doc.save();
}
run();
Alternative Declaration Syntax for Single Nested Subdocuments
There are also 2 ways to declare subdocuments schema.
One way is to write:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
nested: {
prop: String
}
});
const Parent = await connection.model('Parent', schema);
}
run();
or:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
nested: {
type: new Schema({ prop: String }),
required: true
}
});
const Parent = await connection.model('Parent', schema);
}
run();
Both ways will set the nested
subdocument with the data type string.
Conclusion
We can work with MongoDB subdocuments in different ways with Mongoose.