I am trying to build a REST API on top of a MongoDB store.
I have considered simply embedding documents but I need to lock access to certain data which is why it is needed to separate data on multiple collections. Considered manual referencing,but it is not designed for multiple collections referencing. The only option left is DBRef but seems to be complicated to resolve the references especially it is accross two or more collections.
the data model looks like the following :
model/factory.js
// Factory Schema
const factorySchema = mongoose.Schema({
name:{
type: String, required: true
},
mainainter:String,
factory_contacts:{name:String,email_tel:String,url:String},
notes:String,
materials:{type:[DBRef], resolve: true},
products:{type:[DBRef], resolve: true}
});
const Factory = module.exports = mongoose.model('Factory', factorySchema);
module.exports.getFactories = (callback, limit) => {
Factory.find(callback).limit(limit);
}
module.exports.getFactoryById = (id, callback) => {
Factory.findById(id, callback);
}
- two middle level collections "materials" and "products"
model/material.js
// Materials Schema
const materialSchema = mongoose.Schema({
name:String, //name of the factory using these materials
materials: {type:[DBRef], resolve: true}
});
const Material = module.exports = mongoose.model('Material',materialSchema);
module.exports.getMaterials = (callback, limit) => {
Material.find(callback).limit(limit);
}
module.exports.getMaterialById = (id, callback) => {
Material.findById(id, callback);
}
model/product.js
// Product Schema
const productSchema = mongoose.Schema({
name:String, //name of the factory manufactoring these products
products: [product: {type: DBRef, resolve: true},
process :{type: DBRef, resolve: true}]
});
const Product = module.exports = mongoose.model('Product', productSchema);
module.exports.getProducts = (callback, limit) => {
Product.find(callback).limit(limit);
}
module.exports.getProductById = (id, callback) => {
Product.findById(id, callback);
}
And a growing number of collections with specifications of either materials and products for which i wish to not define a schema since it varies from one record to another but looks more or less like this
// specific factory's materials schema-like
const factory_name_materialSchema = mongoose.Schema({
name:String, //name of the factory using these materials
specifications: {type: String, value: Number, unit: String}
});
// specific factory's product schema-like
const factory_name_productSchema = mongoose.Schema({
name:String, //name of the factory manufactoring these products
specifications: {type: String, value: Number, unit: String}
});
The DBRef type is a ailed attempt to use the DBRef-mongoose plugin
Also as far as I know populate is not designed to resolve multiple collections.
app.js
Factory =require('./models/factory');
Material =require('./models/material');
Product =require('./models/product');
mongoose.connect('mongodb://localhost/photonicsdb');
var db = mongoose.connection;
app.get('/api/factories', (req, res) => {
Factories.getFactories((err, factories) => {
if(err){
throw err;
}
res.json(factories);
});
});
app.get('/api/factories/:_id', (req, res) => {
Factories.getFactoriesById(req.params._id, (err, factories) => {
if(err){
throw err;
}
res.json(factory);
});
});
app.get('/api/products/', (req, res) => {
Product.getProducts((err, products) => {
if(err){
throw err;
}
res.json(products);
});
});
app.get('/api/products/:_id', (req, res) => {
Product.getProductById(req.params._id, (err, product) => {
if(err){
throw err;
}
res.json(product);
});
});
app.get('/api/materials/', (req, res) => {
material.getMaterials((err, materials) => {
if(err){
throw err;
}
res.json(materials);
});
});
app.get('/api/materials/:_id', (req, res) => {
Materials.getMaterialsById(req.params._id, (err, material) => {
if(err){
throw err;
}
res.json(material);
});
});
app.listen(3000);
Finally, my question is, how can i resolve a reference accross multiple collections ?
my question is, how can i resolve a reference accross multiple collections ?
Hi Mehdi,
It’s been a while since you posted this question have you found a solution yet ?
You can try to execute an aggregation pipeline directly from the data model i.e. Product. In the aggregation pipeline you can have more than one $lookup stages. You can also just use manual reference instead of DBRefs to define the relationship between the collections.
If you have further question about Mongoose itself, you may want to post a question in StackOverflow: mongoose to reach wider audience with Mongoose expertise.
Regards,
Wan.