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.
Dynamic References via refPath
We can join more than one model with dynamic references and the refPath
property.
For example, we can write:
async function run() {
const { createConnection, Types, Schema } = require('mongoose');
const db = createConnection('mongodb://localhost:27017/test');
const commentSchema = new Schema({
body: { type: String, required: true },
subject: {
type: Schema.Types.ObjectId,
required: true,
refPath: 'subjectModel'
},
subjectModel: {
type: String,
required: true,
enum: ['BlogPost', 'Product']
}
});
const Product = db.model('Product', new Schema({ name: String }));
const BlogPost = db.model('BlogPost', new Schema({ title: String }));
const Comment = db.model('Comment', commentSchema);
const book = await Product.create({ name: 'Mongoose for Dummies' });
const post = await BlogPost.create({ title: 'MongoDB for Dummies' });
const commentOnBook = await Comment.create({
body: 'Great read',
subject: book._id,
subjectModel: 'Product'
});
await commentOnBook.save();
const commentOnPost = await Comment.create({
body: 'Very informative',
subject: post._id,
subjectModel: 'BlogPost'
});
await commentOnPost.save();
const comments = await Comment.find().populate('subject').sort({ body: 1 });
console.log(comments)
}
run();
We have the commentSchema
that has the subject
and subjectModel
properties.
The subject
is set to an object ID. We have the refPath
property that references the model that it can reference.
The refPath
is set to the subjectModel
, and the subjectModel
references the BlogPost
and Product
models.
So we can link comments to a Product
entry or a Post
entry.
To do the linking to the model we want, we set the subject
and subjectModel
when we create the entry with the create
method.
Then we call populate
with subject
to get the subject
field’s data.
Equivalently, we can put the related items into the root schema.
For example, we can write:
async function run() {
const { createConnection, Types, Schema } = require('mongoose');
const db = createConnection('mongodb://localhost:27017/test');
const commentSchema = new Schema({
body: { type: String, required: true },
product: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Product'
},
blogPost: {
type: Schema.Types.ObjectId,
required: true,
ref: 'BlogPost'
}
});
const Product = db.model('Product', new Schema({ name: String }));
const BlogPost = db.model('BlogPost', new Schema({ title: String }));
const Comment = db.model('Comment', commentSchema);
const book = await Product.create({ name: 'Mongoose for Dummies' });
const post = await BlogPost.create({ title: 'MongoDB for Dummies' });
const commentOnBook = await Comment.create({
body: 'Great read',
product: book._id,
blogPost: post._id,
});
await commentOnBook.save();
const comments = await Comment.find()
.populate('product')
.populate('blogPost')
.sort({ body: 1 });
console.log(comments)
}
run();
Then we set the product
and blogPost
in the same object.
We rearranged the commentSchema
to have the products
and blogPost
references.
Then we call populate
on both fields so that we can get the comments.
Conclusion
We can reference more than one schema within a schema.
Then we can call populate
to get all the fields.