How to populate multilevel array in mongoose - mongodb

I have a Quiz Model with array of Section and each Sections has array of reference to Question.
I want to populate Quiz with question.
QuizModel
var quizSchema = new Schema({
name: String,
code: Number,
creator: String,
createdBy: { type: Schema.Types.ObjectId, ref: 'user' },
section:[{
title: String,
questions: [{type: Schema.Types.ObjectId ,ref: 'question'}]
}],
createdOn: {type:Date, default:Date.now}
});
and questionModel
var questionSchema = new mongoose.Schema(
{
question: String,
answer: [String],
correct: Number,
createdOn: {type:Date, default:Date.now}
});
I have following the official mongoose documentation for populating
http://mongoosejs.com/docs/populate.html#deep-populate
My attempt
quizSchema.find({_id: quiz_id})
.populate({
path: 'section' ,
populate: {
path: 'section.questions',
model: 'questionSchema'
}
})
.exec( function (err, result) {
if (err) return done(err,null);
console.log("list of questions are" + result);
return done(err, result);
});
}
The output I am getting is list of question's id not the actual question.
{
"status": "success",
"message": "Quiz data",
"result": [
{
"_id": "57fd5912ec0ad6bc8b67d71c",
"name": "My Quiz",
"creator": "foo",
"__v": 0,
"code": 124,
"createdOn": "2016-10-11T21:26:42.774Z",
"section": [
{
"_id": "57fd7e82c20a2fe5da3ed569",
"questions": [
"57fd7f8560e98fe710878820",
"57fd7f9d60e98fe710878821",
"57fd81408b20dae9108d347c",
"57fd81408b20dae9108d347d",
"57fd826aea5159ea5ff2f1a9",
"57fd82ab0dbc0feaa753e50c",
"57fd82efd789afeb0353f036",
"57fd84b0fef6a2ed21fad5ae",
"57fd84cc5dab10ed471bcaf5",
"57fd84cd5dab10ed471bcaf6"
]
},
{
"title": "next section",
"_id": "57fff1e0f1913138c27e50a0",
"questions": [
"57fff242f1913138c27e50a1"
]
}
]
}
]
}
I think I am doing something wrong with populate field, but not sure .

Just alter your query to
quizSchema.find({_id: quiz_id})
.populate({
path: 'section.questions'
})

Related

I cannot remove a subdocment in mongo Db?

I am trying to delete a subdocument from my users collection in Mongo Db, my best attempt to remove the subdocument is the the route below. However is does not work. I have been able to $unset the entire Favorite Movies array but I only want to delete one Item by its _id within the Favorite Movies Sub-Document. What am I doing Wrong.
// My Route That is supposed to Delete a Subdocument:
app.put('/Favorites/:UserName/delete/:_id',passport.authenticate('jwt', { session: false }), (req, res) => {
users.findOneAndUpdate({ UserName: req.params.UserName })
.then((user) => {
if (!user) {
res.status(400).send('ID: ' + req.params._id + ' was not found!!');
} else {
user.updateOne(
{UserName: req.params.UserName},
{
$pull: {
"FavoriteMovies": {
"ObjectId": req.params._id
}
}
})
res.status(200).send('ID: ' + req.params._id + ' was deleted!');
}
})
.catch((err) => {
console.error(err);
res.status(500).send('Error: ' + err);
});
});
//Mongoose Model Schema for User in which the Subdocuemnt I want to delete is in Favorite Movies:
let usersSchema = mongoose.Schema({
_id: {type: Object},
UserName: {type: String, required: true},
Password: {type: String, required: true},
Email: {type: String, required: true},
Birthday: Date,
FavoriteMovies:{type: Object},
ImagePath: String
});
The User Object with Favorite Movies Subdocument in Postman- Raw:
[
{
"_id": 1650119097711,
"UserName": "robbies",
"Password": "$2b$10$UZmRBLZF0UGWrB1OrZVI2ePc7N1ae5sSZj0RlSU8WyRIRsfdE.yYW",
"Email": "rob#gmail.com",
"Birthday": "1988-05-05T00:00:00.000Z",
"FavoriteMovies": [
{
"ObjectId": 2009,
"Title": "The NoteBook",
"Genre": "Romance"
},
{
"ObjectId": 2001,
"Title": "Hacksaw Ridge",
"Genre": "Action"
}
],
"ImagePath": null,
"__v": 0
}
]

How to populate an field in array of Mongooese?

I have a collection schema like this:
const PrescriptionSchema = new Schema({
patientId:{type: mongoose.Schema.ObjectId, ref: 'User'},
prescriptionName: String,
prescriptionNote: String,
prescriptionDate: Date,
diseaseId: {type: mongoose.Schema.ObjectId, ref: 'Diseases'},
drugs: [{
drugcateId:{type: mongoose.Schema.ObjectId, ref: 'DrugCategory'},
quantity: Number,
howtouse: String
}],
is_deleted: {type: Boolean, default: false},
createdBy: {type: mongoose.Schema.ObjectId, ref: 'User'}
}, {
timestamps: true,
collection: 'prescriptions'
}
);
export default mongoose.model('prescriptions', PrescriptionSchema );
Note that in this collection I have an array of "drugs", this is an array of drug that I get from 'DrugCategory', in each drug I have quantity and howtouse..so that I group it (drugCateId, quantity, howtouse) in drugs array.
When I find a prescription, I want to populate drugCateId inside drugs array. How can I do it?
Below is my current code:
async findOne(req, res){
const { id } = req.params;
await Prescriptions.
findOne({ is_deleted: false, _id: id}).
.populate(
{
path: 'drugs',
populate: {
path: 'drugCateId',
model: 'DrugCategory'
}
}).
exec(function (err, data) {
if (err) return handleError(err);
res.send(data)
});
}
But it's not work.
Below is my result:
{
"is_deleted": false,
"_id": "5f32768a06693a520806717d",
"patientId": "5c80930d447df7735138693e",
"prescriptionName": "Prescription for you",
"prescriptionNote": "Please drink follow doctor",
"prescriptionDate": "2020-07-08T00:00:00.000Z",
"diseaseId": "5f22a6d600980c081ca9e14f",
"drugs": [
{
"_id": "5f32768a06693a5208067181",
"drugcateId": "5f23deca04e3150a48632229", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
},
{
"_id": "5f32768a06693a5208067180",
"drugcateId": "5f23deca04e3150a48632233", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
},
{
"_id": "5f32768a06693a520806717f",
"drugcateId": "5f23deca04e3150a48632234", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
},
{
"_id": "5f32768a06693a520806717e",
"drugcateId": "5f23deca04e3150a4863224a", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
}
],
"createdBy": "5d1cd947231ceb95b8838c1b",
"createdAt": "2020-08-11T10:44:26.842Z",
"updatedAt": "2020-08-11T10:44:26.842Z",
"__v": 0
}
I hope you understand my issue, please take a look. Thanks you
You were very close it seems, but make sure to give the proper path:
.populate({
path: 'drugcateId',
model: 'DrugCategory'
})
Change drugCateId to drugcateId.
Also, you should be able to directly populate DrugCategory.
Your current version does not match your schema. It suggest you want to populate both drugs and drugs.drugcateId. But here drugs are embedded directly and not references to documents in another collection, so it's not possible to populate():
.populate({
path: 'drugs', // this assumes drugs are objectIds: [{ type: ObjectId, ref: 'Drug' }]
populate: {
path: 'drugCateId',
model: 'DrugCategory'
}
})
Instead, you should be able to use dot-notation for arrays:
.populate({ path: "drugs.drugcateId" })
or short
.populate("drugs.drugcateId")
Thanks you for your reply. I have a mistake that my model is "drugcate" but in my populate command is "drugCate". I already change my model to "drugCate" and bellow query is worked.
populate({ path: 'drugs.drugCateId',
populate: {path: 'drugs.drugCateId'}
})
Thanks

Mongoose $push add to document

I'm trying to add an element to an existing array, but it produces an error:
The field 'data' must be an array but is of type object in document
Scheme:
const testScheme = new Schema({
user: {
type: String,
required: true
},
data: [{
platform: {
type: String,
required: true
},
item_name: {
type: String,
required: true
},
price: {
type: Number,
default: 0
},
updatedAt: Date
}]
}, {
versionKey: false,
timestamps: true
});
Document in mongodb:
"data": [{
"price": 50,
"_id": "5a84268d6c78a60c10479437",
"platform": "pl1",
"item_name": "test"
}],
"_id": "5a841bccb44cb8cd5b974d71",
"user": "Ivan",
"updatedAt": "2018-02-14T12:07:41.793Z",
"createdAt": "2018-02-14T11:21:48.104Z"
Query:
var item = {
"platform": "pl700",
"item_name": "someText",
"price": 700,
"updatedAt": new Date()
};
Data.findOneAndUpdate({
'user': 'Ivan'
}, {
$push: {
'data': item
}
}, {
safe: true,
upsert: true
},
function(err, data) {
if (err) return res.status(500).send({
'error': err
});
res.status(200).send({
'data': data
});
}
);
I trying query with $set parametr and it works, but $push, $addToSet didn't work for me. Also i tried to google this problem and can't solve it.
It is not clear what you are intending to do.
To push an item into array you use $addToSet/$push. For updating a array you use $set.
Using $set you can update the whole document or you can update the specific field.
Update whole doc
Data.findOneAndUpdate({
'user': 'Ivan',
'data._id':item._id
}, {
$set: {
'data.$': item
}
}...
)
Update specific field
Data.findOneAndUpdate({
'user': 'Ivan',
'data._id':item._id
}, {
$set: {
'data.$.price': item.price
}
}...
)

Return true/false if users id is found in array of objects

I am new with mongodb. I am saving user recommendations in below schema. I am saving date on which user liked the business. I only want to return true/false if user id (uid) is present in users array.
const userSchema = new Schema({
uid: { type: String},
createdAt: { type: Date, default: Date.now() },
_id: false
});
const businessRecommendationsSchema = new Schema({
businessID: { type: String, unique: true},
users: [userSchema]
},{
timestamps: true
});
I do not want to return whole object if present but only true of false. Please help.
Sample data:
{
"businessID": "35M1L66a8YXzKmDYvbya3sHGJkH2",
"updatedAt": {
"$date": "2017-09-27T10:03:01.866Z"
},
"createdAt": {
"$date": "2017-09-27T10:03:01.866Z"
},
"users": [
{
"uid": "PFwwUecwpFhhWCbJEaFjmfnGOix1",
"createdAt": {
"$date": "2017-09-27T10:03:01.867Z"
}
}
]
}
I tried below query but this only works if it is simple array not array of objects.
Business.aggregate()
.match({ businessID: req.params.businessID })
.lookup({ from : 'businessrecommendations', localField: 'businessID', foreignField: 'businessID',
as: 'recommendations' })
.project({_id: 0, businessID: 1, businessName: 1,
recommendedBy: { $arrayElemAt: [ "$recommendations", 0]}})
.project({_id: 0, businessID: 1, businessName: 1,
recommended: { $in : [req.query.uid, "$recommendedBy.users"]}});

how to use mongoose populate/ref like this?

I'm tring to find every sensor(according to sensor_id) infomation.
the sensor_id is related _id.
my code is:
//this is vnodeInfo
var vnodesSchema = new Schema({
"_id": {
type: Schema.Types.ObjectId //this is ref sensor_id
},
"node_id": {
type: String
},
"name": String,
"sensors": [
{
"sensor_id": {
type: Schema.Types.ObjectId,
ref: "sensors"
},
"name": String,
"alias": String
}
]
});
//this is sensorsInfo
var sensorsSchema = new Schema({
"_id": {
type: Schema.Types.ObjectId //this is link
},
"node_id": {
type: String,
ref: "Nodes"
},
"order": String,
"name": String,
"alias": String,
"low_limit": {
type: Number
},
"high_limit": {
type: Number
},
"value": {
type: Number
},
"state": String,
"last_update": {
type: Date, default: Date.now
}
});
this is my statics method:
I'm tring use sensor.sensor_id related to sensorSchema
"sensor_id==_id" use this ref to get sensors's infomation
findSensorsById: function (vnodeId,callback) {
//use sensors.sensor_id to get sensorinfo
//this is a static method.
return this.findById(vnodeId).populate('sensors.sensor_id').exec(callback)
}