Hello,
I have a basic Mongoose populate scenario working. However, any inserted documents added via populate that have fields in need of another populate call are just showing their ObjectId. How can I write a recursive code block to handle such a situation?
As as example, say I have a collection of C-style functions, where each function has a return data type, a set of parameters, and possibly some dependent functions. I have three schemas, one of which is self-referencing (the Function schema).
Example:
// schemas.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var DataType = new Schema({
name: {type: String, require: true, trim: true, unique: true}
});
module.exports = DataType;
var FunctionParameter = new Schema({
dataType: { type: ObjectId, ref: 'DataType' }
,position: {type: Number, require: true}
,name: {type: String, require: true, trim: true}
,value: {type: String, require: true, trim: true}
});
module.exports = FunctionParameter;
var Function = new Schema({
folderId: { type: Number }
,name: {type: String, require: true, trim: true}
,dependencies: [{ type: ObjectId, ref: 'Function' }] // self-referencing array of functions
,parameters: [{ type: ObjectId, ref: 'FunctionParameter' }]
,definition: {type:String, require: true, trim: true}
,returnDataType: { type: ObjectId, ref: 'DataType' }
});
module.exports = Function;
// models.js
var DataTypeSchema = require('../schemas/dataType');
var DataType = mongoose.model('DataType', DataTypeSchema);
module.exports = DataType;
var FunctionParameterSchema = require('../schemas/functionParameter');
var FunctionParameter = mongoose.model('FunctionParameter', FunctionParameterSchema);
module.exports = FunctionParameter;
var FunctionSchema = require('../schemas/function');
var Function = mongoose.model('Function', FunctionSchema);
module.exports = Function;
// controllers.js
// get all functions by folder id
app.get('/functionsByFolder/:id',function(req,res){
var id = parseInt(req.params['id']);
Function
.find({folderId: id}, function (err, functions){
if (err) {
res.send(err);
}
else {
var opts = [
{ path: 'returnDataType', model: 'DataType' }
,{ path: 'parameters', model: 'FunctionParameter' }
,{ path: 'dependencies', model: 'Function' }
];
Function.populate(functions,opts, function(err,data){
if (err) {
res.send(err);
}
else {
res.send(data);
}
});
}
});
});
When I hit this REST url, the json array of documents looks something like the following. The highlighted areas are where the ObjectId should be replaced with another child document:
[
{
"folderId": 5,
"name": "add",
"definition": "return a+b;",
"returnDataType": {
"name": "Number",
"_id": "5220c19cbaca0d8c1a00000e"
},
"_id": "5220c19cbaca0d8c1a00004d",
"parameters": [
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 1,
"name": "a",
"value": "0",
"_id": "5220c19cbaca0d8c1a000040"
},
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 2,
"name": "b",
"value": "0",
"_id": "5220c19cbaca0d8c1a000041"
}
],
"dependencies": []
},
{
"folderId": 5,
"name": "subtract",
"definition": "return a-b;",
"returnDataType": {
"name": "Number",
"_id": "5220c19cbaca0d8c1a00000e"
},
"_id": "5220c19cbaca0d8c1a00004e",
"parameters": [
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 1,
"name": "a",
"value": "0",
"_id": "5220c19cbaca0d8c1a000042"
},
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 2,
"name": "b",
"value": "0",
"_id": "5220c19cbaca0d8c1a000043"
}
],
"dependencies": []
},
{
"folderId": 5,
"name": "multiply",
"definition": "return a*b;",
"returnDataType": {
"name": "Number"
"_id": "5220c19cbaca0d8c1a00000e"
},
"_id": "5220c19cbaca0d8c1a00004f",
"parameters": [
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 1,
"name": "a",
"value": "0"
"_id": "5220c19cbaca0d8c1a000044"
},
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 2,
"name": "b",
"value": "0"
"_id": "5220c19cbaca0d8c1a000045"
}
],
"dependencies": []
},
{
"folderId": 5,
"name": "divide",
"definition": "return a/b;",
"returnDataType": {
"name": "Number",
"_id": "5220c19cbaca0d8c1a00000e"
},
"_id": "5220c19cbaca0d8c1a000050",
"parameters": [
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 1,
"name": "a",
"value": "0",
"_id": "5220c19cbaca0d8c1a000046"
},
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 2,
"name": "b",
"value": "0",
"_id": "5220c19cbaca0d8c1a000047"
}
],
"dependencies": []
},
{
"folderId": 5,
"name": "factorial",
"definition": "if (n <= 1) return n; return n * factorial(n - 1);",
"returnDataType": {
"name": "Number",
"_id": "5220c19cbaca0d8c1a00000e"
},
"_id": "5220c19cbaca0d8c1a000051",
"parameters": [
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 1,
"name": "n",
"value": "0",
"_id": "5220c19cbaca0d8c1a000048"
}
],
"dependencies": []
},
{
"folderId": 5,
"name": "combination",
"definition": "if (n <= 1) return n; return n * factorial(n - 1);",
"returnDataType": {
"name": "Number",
"_id": "5220c19cbaca0d8c1a00000e"
},
"_id": "5220c19cbaca0d8c1a000052",
"parameters": [
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 1,
"name": "n",
"value": "0",
"_id": "5220c19cbaca0d8c1a000049"
},
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 2,
"name": "r",
"value": "0"
"_id": "5220c19cbaca0d8c1a00004a",
"__v": 0
}
],
"dependencies": [
{
"folderId": 5,
"name": "factorial",
"definition": "if (n <= 1) return n; return n * factorial(n - 1);",
"returnDataType": "5220c19cbaca0d8c1a00000e",
"_id": "5220c19cbaca0d8c1a000051",
"parameters": [
"5220c19cbaca0d8c1a000048"
],
"dependencies": []
}
]
},
{
"folderId": 5,
"name": "permutation",
"definition": "float diff = n - k; float numerator = n; for (int i = n - 1; i > diff; i--) { numerator *= i; } return numerator;",
"returnDataType": {
"name": "Number",
"_id": "5220c19cbaca0d8c1a00000e"
},
"_id": "5220c19cbaca0d8c1a000053",
"parameters": [
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 1,
"name": "n",
"value": "0",
"_id": "5220c19cbaca0d8c1a00004b"
},
{
"dataType": "5220c19cbaca0d8c1a00000e",
"position": 2,
"name": "k",
"value": "0",
"_id": "5220c19cbaca0d8c1a00004c"
}
],
"dependencies": [
{
"folderId": 5,
"name": "factorial",
"definition": "if (n <= 1) return n; return n * factorial(n - 1);",
"returnDataType": "5220c19cbaca0d8c1a00000e",
"_id": "5220c19cbaca0d8c1a000051",
"parameters": [
"5220c19cbaca0d8c1a000048"
],
"dependencies": []
}
]
}
]
Any help regarding how to handle this particular situation would be greatly appreciated!
Thanks!