https://loizenai.com/mongoose-one-to-many-relationship-example/
- Tutorial: "Mongoose One-to-Many Relationship Example - Mongodb One-to-Many Relationship Example"
In the tutorial, we will show you how to develop One-to-Many related document with NodeJs/Express, MongoDB using Mongoose.
Objective - Mongoose One-to-Many Relationship Example
In the tutorial, we show how to develop One-to-Many related documents with NodeJS/Express, MongoDB. Project structure:
/nodejs-restapi-mongodb
/app
/config
mongodb.config.js
/controllers
companies.controller.js
products.controller.js
/models
company.model.js
product.model.js
/routes
companies.routes.js
products.routes.js
/node_modules
package.json
server.js
One-to-Many related models - Mongoose One-to-Many Relationship Example
For working with related documents, we use the ObjectId schema field.
- CompanySchema:
const Product = require('../models/product.model.js');
const mongoose = require('mongoose'), Schema = mongoose.Schema;
const CompanySchema = mongoose.Schema({
name: String,
street: String,
phone: String
});
module.exports = mongoose.model('Company', CompanySchema);
- ProductSchema:
const Company = require('../models/company.model.js');
const mongoose = require('mongoose'), Schema = mongoose.Schema;
const ProductSchema = mongoose.Schema({
code: String,
name: String,
details: String,
company : { type: Schema.Types.ObjectId, ref: 'Company' }
});
module.exports = mongoose.model('Product', ProductSchema);
We can save the references to the related document by assigning the _id value:
var apple = new Company({
name: 'Apple',
street: 'Cupertino, CA 95014',
phone: '1-408-996-1010'
});
apple.save(function (err) {
if(err) return console.error(err.stack)
console.log("Apple company is added")
//Apple now exists, so lets create a Product
var iphone7 = new Product({
code: "A-123",
name: "Iphone7",
details: "Price: 649.00 USD & FREE shipping",
company: apple._id
});
iphone7.save(function (err) {
if(err) return console.error(err.stack)
console.log("Iphone 7 is added")
});
});
We use populate()
to get the Company information in Product:
Product.findOne({ name: req.params.productName })
.populate('company')
.exec(function (err, product) {
if (err){
// handle error here
...
}
res.send(product);
});
We didn't add our products to companies, how to get all products by a particular company?
One way, we create a references array field of products in CompanySchema as below:
const Product = require('../models/product.model.js');
const mongoose = require('mongoose'), Schema = mongoose.Schema;
const CompanySchema = mongoose.Schema({
name: String,
street: String,
phone: String,
products : [{ type: Schema.Types.ObjectId, ref: 'Product' }]
});
module.exports = mongoose.model('Company', CompanySchema);
BUT What is problem? - We have two places where the information relating companies and products needs to be maintained.
What is the better solution?
-> We get the _id of our company, then use find()
to search for this in the company field across all products.
Product.find({ company : req.params.companyId })
.exec(function (err, products) {
if (err){
// handle error here
...
}
res.send(products);
});
Create a NodeJS/Express project - Mongoose One-to-Many Relationship Example
Following below guide:
Crud RestAPIs with NodeJS/Express, MongoDB using Mongoose
See dependencies in 'package.json' file:
"dependencies": {
"body-parser": "^1.18.2",
"express": "^4.16.3",
"mongoose": "^5.0.13",
"npm": "^5.8.0"
}
Create Mongoose Model Schema
- CompanySchema:
const Product = require('../models/product.model.js');
const mongoose = require('mongoose'), Schema = mongoose.Schema;
const CompanySchema = mongoose.Schema({
name: String,
street: String,
phone: String,
products : [{ type: Schema.Types.ObjectId, ref: 'Product' }]
});
module.exports = mongoose.model('Company', CompanySchema);
- ProductSchema :
const Company = require('../models/company.model.js');
const mongoose = require('mongoose'), Schema = mongoose.Schema;
const ProductSchema = mongoose.Schema({
code: String,
name: String,
details: String,
company : { type: Schema.Types.ObjectId, ref: 'Company' }
});
module.exports = mongoose.model('Product', ProductSchema);
Nodejs Express RestAPI Route - Mongoose One-to-Many Relationship Example
- Company Routes :
module.exports = function(app) {
var companies = require('../controllers/companies.controller.js')
app.get('/api/companies/init', companies.init);
app.get('/api/companies', companies.findAll);
}
- Product Routes :
module.exports = function(app) {
var products = require('../controllers/products.controller.js');
app.get('/api/products', products.findAll);
// Find a single Product by Name
app.get('/api/products/:productName', products.findByName);
// Find all Products of a Company
app.get('/api/products/company/:companyId', products.findByCompanyId);
}
Nodejs Express RestAPI Controller
- Company Controllers :
const Company = require('../models/company.model.js');
const Product = require('../models/product.model.js');
exports.init = (req, res) => {
var apple = new Company({
name: 'Apple',
street: 'Cupertino, CA 95014',
phone: '1-408-996-1010'
});
apple.save(function (err) {
if(err) return console.error(err.stack)
console.log("Apple company is added")
//Apple now exists, so lets create a Product
var iphone7 = new Product({
code: "A-123",
name: "Iphone7",
details: "Price: 649.00 USD & FREE shipping",
company: apple._id
});
iphone7.save(function (err) {
if(err) return console.error(err.stack)
console.log("Iphone 7 is added")
});
var iPadPro = new Product({
code: "A-456",
name: "IPadPro",
details: "Price: 417.67 USD & FREE shipping",
company: apple._id
});
iPadPro.save(function(err){
if(err) return console.error(err.stack)
console.log("IPadPro is added");
});
});
var samsung = new Company({
name: 'Samsung',
street: 'Seocho District, Seoul, South Korea',
phone: '+82-2-2053-3000'
});
samsung.save(function(err){
if(err) return console.error(err.stack)
console.log("Samsung company is added")
// Samsung now exists, so lets create a Product
var galaxyJ7 = new Product({
code: "S-012",
name: "GalaxyJ7",
details: "Price: 219.00 USD & FREE shipping",
company: samsung._id
});
galaxyJ7.save(function(err){
if(err) return console.error(err.stack)
console.log("GalaxyJ7 is added")
});
var galaxyTabA = new Product({
code: "S-456",
name: "GalaxyTabA",
details: "Price: 299.99 USD & FREE shipping",
company: samsung._id
});
galaxyTabA.save(function(err){
if(err) return console.error(err.stack)
console.log("GalaxyTabA is added")
})
});
res.send("Done Initial Data!");
}
exports.findAll = (req, res) => {
Company.find()
.then(products => {
res.send(products);
}).catch(err => {
res.status(500).send({
message: err.message
});
});
};
- Product Controllers :
const Company = require('../models/company.model.js');
const Product = require('../models/product.model.js');
exports.findAll = (req, res) => {
Product.find()
.then(products => {
res.send(products);
}).catch(err => {
res.status(500).send({
message: err.message
});
});
};
// Find a Products by Name
exports.findByName = (req, res) => {
Product.findOne({ name: req.params.productName })
.populate('company')
.exec(function (err, product) {
if (err){
if(err.kind === 'ObjectId') {
return res.status(404).send({
message: "Products not found with given name " + req.params.productName
});
}
return res.status(500).send({
message: "Error retrieving Products with given Company Id " + req.params.productName
});
}
res.send(product);
});
};
// Find all products by a CompanyId
exports.findByCompanyId = (req, res) => {
Product.find({ company : req.params.companyId })
.exec(function (err, products) {
if (err){
if(err.kind === 'ObjectId') {
return res.status(404).send({
message: "Products not found with given Company Id " + req.params.companyId
});
}
return res.status(500).send({
message: "Error retrieving Products with given Company Id " + req.params.companyId
});
}
res.send(products);
});
};
Run & Check results - Mongoose One-to-Many Relationship Example
Run MongDB server by commandline:
\MongoDB\Server\3.6\bin>mongod.exe
2018-04-11T03:11:42.209+0700 I CONTROL [initandlisten] MongoDB starting : pid=2432 port=27017 dbpath=C:\data\db\ 64-bit host=LOI-COMPUTER
2018-04-11T03:11:42.211+0700 I CONTROL [initandlisten] targetMinOS: Windows 7/Windows Server 2008 R2
2018-04-11T03:11:42.212+0700 I CONTROL [initandlisten] db version v3.6.3
2018-04-11T03:11:42.212+0700 I CONTROL [initandlisten] git version: 9586e557d54ef70f9ca4b43c26892cd55257e1a5
2018-04-11T03:11:42.212+0700 I CONTROL [initandlisten] OpenSSL version: OpenSSL 1.0.1u-fips 22 Sep 2016
2018-04-11T03:11:42.212+0700 I CONTROL [initandlisten] allocator: tcmalloc
Run NodeJS/Express application:
\nodejs-restapi-mongodb>node server.js
App listening at http://:::8081
Successfully connected to MongoDB.
- Initial data
-> localhost:8081/api/companies/init
[caption id="attachment_4820" align="alignnone" width="705"] Node.js Mongodb One-to-many Related Document Initial Data[/caption]
- Get all Companies:
-> localhost:8081/api/companies
[caption id="attachment_4821" align="alignnone" width="452"] Nodejs Mongodb One-to-many Related Document Find All Company[/caption]
- Get all Products
-> localhost:8081/api/products
[caption id="attachment_4822" align="alignnone" width="440"] Nodejs Mongodb One-to-many Related Document Find All Product[/caption]
- Find Product by Name:
-> localhost:8081/api/product/Iphone7
[caption id="attachment_4823" align="alignnone" width="410"] Nodejs Mongodb One-to-Many Related Document Find Product By Name Polulate Company[/caption]
- Find Products by Company Id:
-> localhost:8081/api/products/company/5acd590b203d8e1ac01cb184
[caption id="attachment_4824" align="alignnone" width="532"] Nodejs Mongodb One-to-many Related Document Find All Products By Company ID[/caption]
Read More
Related posts:- Reference Link: Mongoose Association
Sourcecode
Top comments (0)