How to popoulate recursive schema references Mongodb, Mongoose, Express? - node.js

Using mongoose and Express with mongodb
So right now I have a schema for boxes, a box can contain objects or it can contain other boxes:
my schema for boxes looks like this:
var box = new Schema({
boxId: ObjectId,
boxContents: [{
contentType: {
type: String,
enum: ["box", "object"]
},
typeId: {
subBox: {
type: Schema.Types.ObjectId,
ref: 'box'
},
subObject: {
type: Schema.Types.ObjectId,
ref: 'object'
}
}
}]
});
I made sure to have my 'ref' labeled accordingly with the model names so I don't believe that is the problem. I create a new document like so:
var box1 = new Box({
contents: [{
contentType: 'object',
typeId: {
subObject: object1._id
}
}]
});
When I use:
Control.find({}).populate('contents.typeId')
.exec(function(error, posts) {
console.log(JSON.stringify(posts, null, "\t"));
});
It doesn't populate the subBox and subObject fields :( If I try to access the subBox or subObject fields, it gives me undefined.
What am I doing incorrectly?

First of all, you need to get a model of the collection:
var BoxModel = mongoose.connect(dbURI).model("box", box);
boxContents is in schema, but in the object is contents, that should be modified.
To create an object to be save, you need to use the model in that way, and then you can get your populated data this way:
var box1 = new BoxModel({
boxContents: [{
contentType: 'object',
typeId: {
subObject: object1._id
}
}]
});
BoxModel.find({}).populate('boxContents.typeId');
OR
BoxModel.find({}).populate({path:'boxContents.typeId'});

Related

How do I pass an object element in express using Mongo?

I want to pass a whole object from an ejs template
For example:
var schema = ... {
Name: [{
}]
}
With this you can achieve it, hope that's what you ask...
notifications: {
notifiId: {type: Schema.Types.ObjectId, ref: 'Notifications' },
viewed: { type: Number, default: 0 }
},
and to find it:
model_Variable.findById(req.params.id).populate("notifiId").exec(function (err,
callBack) {});
Source: How to populate in this case Mongoose

Mongoose populating array inside nested schema

This is my schema:
var userSchema = {
folders : [ folderSchema ],
...
}
var folderSchema = new mongoose.Schema({
itemlist : [{ type: String, ref: 'Item', required: true }],
foldername : { type: String},
...
});
// Item model
var itemSchema = {
name: { type: String },
...
}
I would like to populate itemlist (entire array) inside of each folderSchema, is this possible?
What I've tried so far but doesn't work:
userModel.findOne({ _id: userId }, null, callback).populate({
path: 'folders.$.itemlist',
select: 'name'
});
This post and this post are similar but they store the folder models and have a ref instead of nested document.
Bonus: is it possible to select only some folders by foldername to populate their itemlist?
I think you are looking for "deep population", see the population section "Populating across multiple levels"
rewrite your populate to:
userModel.findOne({ _id: userId }, null, callback).populate({
path: 'folders',
populate: { path : 'itemlist'}
});
The easiest solution is to actually retrieve the nested folder and perform a find manually. Then simply call find({_id: {$in : folder}}); to find all elements of array.

Mongoose dynamic sub document schema

I have an Inquiry schema:
const inquirySchema = new mongoose.Schema({
client: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Client' }],
data: dynamicSchema?
}, {
timestamps: true
});
I would like to populate the "data" property field with a sub-document, but I want it to accept different sub-document schemas. I have an "Event" and a "Property" child schema which can be inserted as "data". How do I allow this in my Inquiry schema? It seems I have to actually specify WHICH sub-document schema it expects...
My Child schemas:
const eventSchema = new mongoose.Schema({
name: { min: Number, max: Number },
date: { type: Date },
zone: { type: String }
});
const propertySchema = new mongoose.Schema({
price: { min: Number, max: Number },
status: { type: String },
zone: { type: String }
});
you can make your data as type : ObjectId without defining any reference in the schema, and when you want to populate them, use path and model in the populate to populate from different collection, but you must have a logic for choosing which collection to populate from.
Here is how you can do the same:
inquirySchema
const inquirySchema = new mongoose.Schema({
client: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Client' }],
data: { type: mongoose.Schema.Types.ObjectId }
}, {
timestamps: true
});
Populating data
if(isEvent)
{
//Populate using Event collection
Inquiry.find({_id : someID}).
populate({path : 'data' , model : Event}).
exec(function(err,docs){...});
}
else if(isProperty)
{
//Populate using Property collection
Inquiry.find({_id : someID}).
populate({path : 'data' , model : Property}).
exec(function(err,docs){...});
}

Compare Array with Collection-Array containing Objects

This is my collection schema:
var objectSchema = new Schema({
members: [{
user_id: ObjectId,
settings: {
type: Boolean
}
}],
title: String
});
And now I'm trying to search for objects with specific members (identified by their "user_id", for example ["asdf123lkd", "asdf1223"]).
Is there any way to search for these objects?
Thanks!
You can try this:
objectModel.find({ 'members.user_id' : {'$in' : ['asdf123lkd', 'asdf1223']} }, function(err, data) {
console.log(err,data);
})

Mongoose Relationship Populate Doesn't Return results

var SecuritySchema = new Mongoose.Schema({
_bids: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'BuyOrder'
}],
_asks: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'SellOrder'
}]
});
var OrdersSchema = new Mongoose.Schema({
_security: {
type: Mongoose.Schema.Types.ObjectId,
ref: 'Security'
},
price: {
type: Number,
required: true
},
quantity: {
type: Number,
required: true
}
});
// declare seat covers here too
var models = {
Security: Mongoose.model('Security', SecuritySchema),
BuyOrder: Mongoose.model('BuyOrder', OrdersSchema),
SellOrder: Mongoose.model('SellOrder', OrdersSchema)
};
return models;
And than when I save a new BuyOrder for example:
// I put the 'id' of the security: order.__security = security._id on the client-side
var order = new models.BuyOrder(req.body.order);
order.save(function(err) {
if (err) return console.log(err);
});
And attempt to re-retrieve the associated security:
models.Security.findById(req.params.id).populate({
path: '_bids'
}).exec(function(err, security) {
// the '_bids' array is empty.
});
I think this is some sort of naming issue, but I'm not sure, I've seen examples here and on the moongoose website that use Number as the Id type: http://mongoosejs.com/docs/populate.html
The ref field should use the singular model name
Also, just do:
models.Security.findById(req.params.id).populate('_bids').exec(...
My main suspicion given your snippet at the moment is your req.body.order has _security as a string instead of an array containing a string.
Also, you don't need an id property. Mongodb itself will automatically do the _id as a real BSON ObjectId, and mongoose will add id as a string representation of the same value, so don't worry about that.
While I don't understand your schema (and the circular nature of it?), this code works:
var order = new models.BuyOrder({ price: 100, quantity: 5});
order.save(function(err, orderDoc) {
var security = new models.Security();
security._bids.push(orderDoc);
security.save(function(err, doc) {
models.Security.findById({ _id: doc._id })
.populate("_bids").exec(function(err, security) {
console.log(security);
});
});
});
It:
creates a BuyOrder
saves it
creates a Security
adds to the array of _bids the new orderDoc's _id
saves it
searches for the match and populates
Note that there's not an automatic method for adding the document to the array of _bids, so I've done that manually.
Results:
{ _id: 5224e73af7c90a2017000002,
__v: 0,
_asks: [],
_bids: [ { price: 100,
quantity: 5,
_id: 5224e72ef7c90a2017000001, __v: 0 } ] }

Resources