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.
Populate
We can use the populate
method to join 2 models together.
For example, we can write:
async function run() {
const { createConnection, Types, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
const storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
const Story = connection.model('Story', storySchema);
const Person = connection.model('Person', personSchema);
const author = new Person({
_id: new Types.ObjectId(),
name: 'James Smith',
age: 50
});
author.save(function (err) {
if (err) return handleError(err);
const story1 = new Story({
title: 'Mongoose Story',
author: author._id
});
story1.save(function (err) {
if (err) {
return console.log(err);
}
Story.
findOne({ title: 'Mongoose Story' }).
populate('author').
exec(function (err, story) {
if (err) {
return console.log(err);
}
console.log('author', story.author.name);
});
});
});
}
run();
We created the Story
and Person
models.
The Story
model references the Person
model by setting author._id
as the value of the author
field.
Then we save both the author and story.
Then in the callback for story1.save
, we get the Story
entry with the exec
method with a callback to get the data.
Then we can access the author’s name of the story with the story.author.name
property.
The documents created with the models will be saved in their own collections.
Therefore the story.author.name
‘s value is 'James Smith'
.
Setting Populated Fields
We can also set the author
value directly by writing:
async function run() {
const { createConnection, Types, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
const storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
const Story = connection.model('Story', storySchema);
const Person = connection.model('Person', personSchema);
const author = new Person({
_id: new Types.ObjectId(),
name: 'James Smith',
age: 50
});
author.save(function (err) {
if (err) return handleError(err);
const story1 = new Story({
title: 'Mongoose Story',
});
story1.save(function (err) {
if (err) {
return console.log(err);
}
Story.findOne({ title: 'Mongoose Story' }, function (error, story) {
if (error) {
return console.log(error);
}
story.author = author;
console.log(story.author.name);
});
});
});
}
run();
We set story.author
to author
to link the author
to the story
.
And now story.author.name
is 'James Smith'
.
Checking Whether a Field is Populated
We can check whether a field is populated with the populated
method.
For example, we can write:
async function run() {
const { createConnection, Types, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
const storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
const Story = connection.model('Story', storySchema);
const Person = connection.model('Person', personSchema);
const author = new Person({
_id: new Types.ObjectId(),
name: 'James Smith',
age: 50
});
author.save(function (err) {
if (err) return handleError(err);
const story1 = new Story({
title: 'Mongoose Story',
});
story1.save(function (err) {
if (err) {
return console.log(err);
}
Story.findOne({ title: 'Mongoose Story' }, function (error, story) {
if (error) {
return console.log(error);
}
story.author = author;
console.log(story.populated('author'));
});
});
});
}
run();
We get the ID of the author that the store is populated with.
We call depopulate
to unlink the author
and the story
.
For example, we can write:
async function run() {
const { createConnection, Types, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
const storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
const Story = connection.model('Story', storySchema);
const Person = connection.model('Person', personSchema);
const author = new Person({
_id: new Types.ObjectId(),
name: 'James Smith',
age: 50
});
author.save(function (err) {
if (err) return handleError(err);
const story1 = new Story({
title: 'Mongoose Story',
});
story1.save(function (err) {
if (err) {
return console.log(err);
}
Story.findOne({ title: 'Mongoose Story' }, function (error, story) {
if (error) {
return console.log(error);
}
story.author = author;
console.log(story.populated('author'));
story.depopulate('author');
console.log(story.populated('author'));
});
});
});
}
run();
We call the depopulate
method to unlink the author and story.
Now when we log the value of populated
again, we see undefined
.
Conclusion
We can join 2 documents together by referencing one document’s ID with the other.
Then we can use Mongoose’s method to check whether they’re linked.