Mongoose Populate ignored for this basic setup - mongodb

I have a User Schema, which has multiple notes, and the Note which belongs to a userId
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'Note'}]
});
const NoteSchema = new Schema({
userId: {type: mongoose.Types.ObjectId, ref: 'User'},
content: {type: String, required: true, trim: true, lowercase: true},
});
I'm trying to populate my User with the notes using the following syntax (from the docs)
const user = await User.findById(mongoose.Types.ObjectId("5bd2a8c4963ac00f57a18074"))
.populate('notes')
.exec(function (err, result) {
console.log(result);
});
But it's returning the User without the Notes data. Any idea what I might be doing wrong?

NoteSchema here is the problem:
userId: {type: mongoose.Types.ObjectId, ref: 'User'}
Use below,
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.ObjectId, ref: 'User'} // For backword compatibility
Note:- The schema should always use mongoose.Schema.Types. And mongoose.Types.ObjectId can be used withing mongoose implementation.
I am able to get document properly (Below code):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
const NoteSchema = new Schema({
userId: {type: Schema.Types.ObjectId, ref: 'UserTest'},
content: {type: String, required: true, trim: true, lowercase: true},
});
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'NoteTest'}]
});
var Note = mongoose.model('NoteTest', NoteSchema);
var User = mongoose.model('UserTest', UserSchema);
User.find({_id : mongoose.Types.ObjectId("5bd2c84dd79cc5d8b1c62964")})
.populate('notes')
.exec(function (err, result) {
console.log("result.....", JSON.stringify(result));
});
Output:
[
{
"_id": "5bd2c84dd79cc5d8b1c62964",
"email": "hardik#com.com",
"notes": [
{
"_id": "5bd2c869d79cc5d8b1c62965",
"content": "ABC",
"userId": "5bd2c84dd79cc5d8b1c62964"
},
{
"_id": "5bd2c88ad79cc5d8b1c62966",
"content": "DEF",
"userId": "5bd2c84dd79cc5d8b1c62964"
}
]
}
]

Related

Mongoose populate method on query returns empty array

I am having trouble querying my model, and using the .populate method to grab referenced documents of my object. Here are my schemas:
var userSchema = new Schema({
firstname: { type: String, required: true, unique: false },
lastname: { type: String, required: true, unique: false },
...
children: [{type: mongoose.Schema.Types.ObjectId, ref: 'Child'}],
});
var childSchema = new Schema({
firstname: { type: String, required: true, unique: false },
lastname: { type: String, required: true, unique: false },
...
legal_guardian_id: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}],
});
And here is how i'm trying to run my query:
User.findOne({ _id: '5b9d30083e33585cc0b8c710' })
.populate('children').exec((err, doc) => {
if (err) { return console.error(err); }
res.send(doc);
})
This results in "children": []
When I just use the findOne method and return the user, I get "children":["5b9d3f23d1408c5f4e2624f3"].
What am I doing wrong?

Update field in another schema with post hook mongoose

I have that schemas:
var schema = new Schema({
number: {type: Number},
subtotal: {type: Float, required: true},
quantity: {type: Number, required: true},
prodprov: {type: Schema.Types.ObjectId, ref: 'ProdProv'},
order: {type: Schema.Types.ObjectId, ref: 'Order'}
});
module.exports = mongoose.model('OrderDetail', schema);
and
var schema = new Schema({
name: {type: String, required: true},
price: {type: Float, required: true},
idProvider: {type: Schema.Types.ObjectId, ref: 'Provider'},
idProduct: {type: Schema.Types.ObjectId, ref: 'Product'},
description: {type: String},
quantitySold: {type: Number}
});
module.exports = mongoose.model('ProdProv', schema);
I need to update field "quantitySold" when a post.save happens in order-detail, i've tried this:
schema.post('save', function(next){
//But this point I can't find the prodprov to update field
})
How I can do this?
Thank you.
Thank you #mjim, but that´s code not works. I've modify the code and works! this is my solution:
schema.post('save', function(doc){
var prod = ProdProv.findById(this.prodprov).exec().then((pp) => {
pp.quantitySold += this.quantity;
pp.save();
});
});
I would suggest:
var ProdProv = require('./ProdProv');
var schema = new Schema({
number: {type: Number},
subtotal: {type: Float, required: true},
quantity: {type: Number, required: true},
prodprov: {type: Schema.Types.ObjectId, ref: 'ProdProv'},
order: {type: Schema.Types.ObjectId, ref: 'Order'}
});
schema.post('save', async function(doc){
var prod = await ProdProv.findById(doc.prodprov);
prod.quantitySold = doc.quantity;
prod.save()
});
module.exports = mongoose.model('OrderDetail', schema);

Index containing multiple fields in MongoDB

In MongoDB, How do i restrict the data entry bases on 3 fields RegisterUserId ,PageId and IsFavourite. None of them is unique?
what should the query be?
Below is my Schema
var FavMasterSchema = new Schema({
FavUrl:String,
RegisterUserId : { type: Schema.Types.ObjectId, ref: 'User',select: false},
PageId: { type: Schema.Types.ObjectId},
IsFavourite: {type: Boolean,default:false}
});
module.exports = mongoose.model('t_FavMaster', FavMasterSchema);
Try this:
var FavMasterSchema = new Schema({
FavUrl:String,
RegisterUserId : { type: Schema.Types.ObjectId, ref: 'User',select: false},
PageId: { type: Schema.Types.ObjectId},
IsFavourite: {type: Boolean,default:false}
});

Mongoose delete nested subdocuments and documents

I have:
let userSchema = mongoose.Schema({
email: {type: String, required: true, unique: true},
passwordHash: {type: String, required: true},
fullName: {type: String, required: true},
salt: {type: String, required: true},
ads: [{type: ObjectId, ref: 'Ad'}],
roles: [{type: String}]
}
let adSchema = mongoose.Schema({
author: {type: ObjectId, ref: 'User'},
title: {type: String, required: true},
category: {type: ObjectId, ref: 'Category', required: true},
town: {type: ObjectId, ref: 'Town', required: true},
}
);
let categorySchema = mongoose.Schema({
name: {type: String, required: true, unique: true},
ads: [{type: ObjectId, ref: 'Ad'}]
}
);
let townSchema = mongoose.Schema({
name: {type: String, required: true, unique: true},
ads: [{type: ObjectId, ref: 'Ad'}]
}
);
I want to find for example town by id and remove all ads in it(and ofcourse to remove the ads from their categories and authors).How can i do that?
I would suggest bulk getting the array of object Ids and using it like this:
Ad.remove({_id: {$in: Ad_ids_array}}, function(){...}); // and so on
You can add a pre-remove hook in the ad schema definition like this:
adSchema.pre('remove', function(next) {
let lethis = this;
// Pull ad out of all the Category docs that reference the removed ad.
this.model('Category').update({}, { $pull: {ads: lethis._id}}, { safe: true }, next);
// Pull ad out of all the User docs that reference the removed ad.
this.model('User').update({}, { $pull: {ads: lethis._id}}, { safe: true }, next);
});
This will remove the ad from the categories and users that have it in their ads array.

Population to sub-scheme in Mongoose

I have two schemas:
Clinic:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var ProcedureSchema = mongoose.Schema({
name: {
type: String,
trim: true,
required: true
},
alias: {
type: String,
trim: true,
required: true
}
});
var ClinicSchema = mongoose.Schema({
name: {
type: String,
trim: true,
required: true
},
procedures: [ProcedureSchema]
});
module.exports = mongoose.model('Clinic', ClinicSchema);
and Record:
var mongoose = require('mongoose'),
Patient = require('./patient'),
User = require('./user'),
Clinic = require('./clinic'),
Schema = mongoose.Schema;
var RecordSchema = Schema({
doctor: {
type: Schema.Types.ObjectId,
ref: 'User'
},
clinic: {
type: Schema.Types.ObjectId
},
date: {
type: Date
},
patient: {
type: Schema.Types.ObjectId,
ref: 'Patient'
},
procedure: {
type: [Schema.Types.ObjectId],
ref: 'Clinic'
}
});
module.exports = mongoose.model('Record', RecordSchema);
In record schema i store all ids of procedure, which sub-scheme for Clinic
I want to get full object of procedures in record.
I try this query:
Record.find({}).
populate('procedures.procedure').
populate('doctor').
populate('patient').
exec(function(err, records) {
...
});
But get only array of ids, instead array of objects.
Where is problem?
You totally mix all schemes:
populate('procedures.procedure')
But you have not procedures in RecordSchema. Even if it is type mistake, an you mean procedure.procedures - you don't have procedures in ProcedureSchema.
read more about references in MongoDB especially http://docs.mongodb.org/manual/applications/data-models-tree-structures/
Try to make nesting path less than 2. Something like this:
var User,
Procedure,
Clinic,
Patient,
Record;
function defineModels(mongoose, fn) {
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
User = new Schema({
...
});
Procedure = new Schema({
name: { type: String, trim: true, required: true },
alias: { type: String, trim: true, required: true }
});
Clinic = new Schema({
name: { type: String, trim: true, required: true },
procedures: [ProcedureSchema]
});
Patient = new Schema({
...
});
Record = new Schema({
'date': {type: Date, default: Date.now},
'doctor': {type: ObjectId, ref: 'User'},
'clinic': {type: ObjectId, ref: 'Clinic'},
'patient': {type: ObjectId, ref: 'Patient'},
'procedure': {type: ObjectId, ref: 'Procedure'},
});
mongoose.model('User', User);
mongoose.model('Procedure', Procedure);
mongoose.model('Clinic', Clinic);
mongoose.model('Patient', Patient);
mongoose.model('Record', Record);
fn();
}
exports.defineModels = defineModels;
Hope this help.