Example of a lookup in MongoDB
This mini tutorial demonstrates a lookup
in MongoDB, the equivalent of a "JOIN" in SQL, using Mongoose
.
Code and example data is available on my Github page.
Data model
In this example we have two collections for the data of cooking recipes - one for the title and overview metadata, and one for the one or many component part(s) of a single recipe.
The data model looks like this:
The collection recipeparts
references the collection recipes
via the recipe_id
field.
The rationale behind this modeling is that the use cases indicate the data in the collection recipes
is accessed far more frequently than that in the recipeparts
collection.
Node.js
/ Mongoose
implementation
The model schemata might then be defined like this:
const mongoose = require('mongoose')
const ingredQtyModel = new mongoose.Schema({
amt: { type: String, required: true },
unit: { type: String },
})
const ingredModel = new mongoose.Schema({
name: { type: String },
qty: { type: ingredQtyModel },
})
const recipeModel = new mongoose.Schema({
title: { type: String, required: true },
})
const recipePartModel = new mongoose.Schema({
title: { type: String, required: true },
recipe_id: { type: mongoose.Types.ObjectId, ref: 'recipes' }, // <<== this is the lookup link
ingreds: [ ingredModel ],
method: [ String ]
})
const Recipes = mongoose.model('recipes', recipeModel)
const RecipeParts = mongoose.model('recipeParts', recipePartModel)
Note that the lookup linkage is effected in the recipePartModel
(line 19) by specifying the ref
to the
parent 'recipes' model (line 24) for the attribute recipe_id
of type ObjectId.
A minimal implementation on the command line might look like this:
const mongoose = require('mongoose')
const URI = `mongodb+srv://${MONGODB_USER}:${MONGODB_PASS}@cluster01.koazls1.mongodb.net/db1`
const main = async () => {
await mongoose.connect(URI)
const recipe = await Recipes.findOne({ title: { $regex: /^Warm salmon/ } })
const oid = new mongoose.Types.ObjectId(recipe?._id.toString())
const recipeParts = await RecipeParts.find({ recipe_id: oid }).populate('recipe_id')
console.log(JSON.stringify(recipeParts, null, 2))
}
main().catch(err => console.log(err))
with the .populate()
method (line 74) effecting the lookup or join between the collections.
Demo
On my Github page there are two scripts which demonstrate how this join works.