Deep population not working with embedded document - node.js

I have three documents as below:
var TrackAudioSchema = new Schema({
track_id: {
type: Number,
},
track_path:{
type:String,
required:'Please upload audio track'
}
});
mongoose.model('TrackAudio', TrackAudioSchema);
var trackSchema = new Schema({
title: {
type: String,
trim:true,
required:'Please fill track title'
},
version : {
type: String,
trim: true,
default: ''
},
trackpath:{
type: Schema.ObjectId,
ref: 'TrackAudio'
},
});
var AlbumSchema = new Schema({
language: {
type: String,
default: '',
trim: true
},
tracks:[trackSchema],
user: {
type: Schema.ObjectId,
ref: 'User'
},
)};
AlbumSchema.plugin(deepPopulate);
mongoose.model('Album', AlbumSchema);
but when I try to populate trackpath from trackSchema using the below query, it doesn't populate:
Album.findById(albumId)
.populate('user','name label').
deepPopulate('tracks.trackpath').
exec(function(err, albumdetail) {
}
Please help.

You're missing:
mongoose.model('Track', TrackSchema);

Related

Is that possible, to solve a complex mongoose populate query?

I have four tables.
#First table
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
#First table
var studentSchema=new Schema({
student_name: { type: String, required: true },
sendKey: { type: String },
created_by: { type:String },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('Student',studentSchema);
#Second table
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var institutionSchema=new Schema({
institution_name: { type: String, lowercase: true },
email: { type:String },
created_by: { type:String },
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('Institution',institutionSchema);
#third table
var mongoose=require('mongoose');
// var Institution = ('./institution');
var Schema=mongoose.Schema;
var batchSchema=new Schema({
batch_name: { type: String, required: true },
institution: { type: Schema.Types.ObjectId, ref: 'Institution' },
created_by: { type:String },
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('Batch',batchSchema);
#Fourth Table
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var batchtudentSchema=new Schema({
student_id: { type: Schema.Types.ObjectId, ref: 'Student', required : true},
batch_id: { type: Schema.Types.ObjectId, ref: 'Batch', required:true},
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('BatchStudent',batchtudentSchema);
I have an institution Id. I want to find all students of this institution with Batch details.
Primarily I have tried to.. do that.
Student.find().populate('BatchStudent').pupulate('Batch').populate('Institution').exec((err, docs) => {
console.log(docs)
res.json(
{
data:docs
}
)
})
It is not working.. sending just all student data.. How can I get the data correctlly?
// Student Schema
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var studentSchema=new Schema({
student_name: {
type: String,
required: true
},
sendKey: {
type: String
},
batchStudent: {
type: Schema.Types.ObjectId,
ref: 'BatchStudent',
}
created_by: {
type:String
},
updated_at: {
type: Date,
default: Date.now
},
})
module.exports=mongoose.model('Student',studentSchema);
// BatchStudent Schema
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var batchtudentSchema=new Schema({
student_id: {
type: Schema.Types.ObjectId,
ref: 'Student',
required : true
},
batch_id: {
type: Schema.Types.ObjectId,
ref: 'Batch'
},
institution: {
type: Schema.Types.ObjectId,
ref: 'Institution'
}
})
module.exports=mongoose.model('BatchStudent',batchtudentSchema);
// Institution Schema
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var institutionSchema=new Schema({
institution_name: {
type: String,
lowercase: true
},
email: {
type: String
},
created_by: {
type:String
}
});
module.exports=mongoose.model('Institution',institutionSchema);
If the I removed created_at and updated_at to avoid duplication. Obey DRY principles always (Don't repeat yourself)
If you need to get the document you can simply use Deep Population/Association for that as shown below:
Student.find({}).populate({
path : 'batchStudent',
populate : {
path : 'institution'
}
}).exec(function (err, res) {
// do whatever you need to do here
})

Populate returns whole parent document

I just started learning express and mongodb. I recently faced the kind of problem, I'm trying to select all the subdocuments which are inside of Room model.
const books = await Room.find().populate('book');
But it returns whole room document when i want to select only bookings field.
Here's the book schema
const bookSchema = new mongoose.Schema({
startDate: {
type: Date,
required: true,
},
endDate: {
type: Date,
required: true,
},
name: {
type: String,
required: true,
},
phone: {
type: String,
required: true,
},
});
module.exports = mongoose.model("book", bookSchema)
And here's the room schema
const roomSchema = new mongoose.Schema({
currentlyReserved: {
type: Boolean,
default: false,
},
people: {
type: Number,
required: true,
},
roomNumber: {
type: Number,
required: true,
},
pricePerPerson: {
type: Number,
required: true,
},
reservedUntil: {
type: Date,
default: null,
},
reservedBy: {
type: String,
default: null,
},
bookings: {
type: [{ type: mongoose.Schema.Types.ObjectId, ref: "book" }],
},
});
module.exports = mongoose.model("room", roomSchema);
You can project with with second arg to find().
https://docs.mongodb.com/manual/reference/method/db.collection.find/#projection
const books = await Room.find({}, {bookings: 1}).populate('bookings');

Mongoose populate method

I am having the most awful trouble trying to get the populate feature in mongoose to work. I have looked at all the threads here on SO and nothing has helped. My schema is mapped out below.
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Prodcut Feature Extra
*/
var extra = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Product name',
trim: true
},
price: {
type: Number,
default: 0
},
description: {
type: String,
trim: true
},
toolTip: {
type: String,
trim: true,
min: 3,
max: 140
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
/**
* Product Feature Schema
*/
var feature = new Schema({
name: {
type: String,
default: '',
required: 'Please fill feature name',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
/**
* Product Schema
*/
var ProductSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Product name',
trim: true
},
created: {
type: Date,
default: Date.now
},
features: [feature],
extras: [extra],
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Feature', feature);
mongoose.model('Extra', extra);
mongoose.model('Product', ProductSchema);
I have tried all of the following queries in a Mongoose Repl but nothing works
models.Product.find().populate("Extra", "name").exec()
models.Product.find().populate({path: "extras", location: "Extra"}).exec()
models.Product.find().populate('extras', 'name').exec()
models.Product.find().populate('extras', 'Extra').exec()
Does anyone have any suggestions? This is killing me!!
Just curious!
This initialization below, isn't has to be done before referencing in ProductSchema?
mongoose.model('Feature', feature);
mongoose.model('Extra', extra);
Something like this
mongoose.model('Feature', feature);
mongoose.model('Extra', extra);
var ProductSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Product name',
trim: true
},
created: {
type: Date,
default: Date.now
},
features: [ {
type: Schema.ObjectId,
ref: 'Feature'
}],
extras: [ {
type: Schema.ObjectId,
ref: 'Extra'
}],
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
Than this should work
models.Product.find().populate("extras")

Mongodb, search for text and geolocation in different collections

I have 3 collections: business, sevice, employee.
I need search by service (without fulltext), by employee and by the geolocation of each business, and should show only business.
var BusinessSchema = new Schema({
business_id: {
type: String,
required: true,
unique:true
},
name: {
type: String,
required: true
},
email: {
type: String,
},
description:{
type: String
},
location:{
country:{
type:String,
},
city:{
type:String
},
coord:[Number]
}
services:[{
type: Schema.Types.ObjectId,
ref: 'Service'
}]
},
{
timestamps: true
});
var ServiceSchema = new Schema({
business:{
type: Schema.Types.ObjectId,
ref: 'Business'
},
category:{
type: Schema.Types.ObjectId,
ref: 'Category',
index:true
},
name: {
type: String,
required: true,
index:true
},
employee: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
{
timestamps: true
});
var UserSchema = new Schema({
birthday:Date,
first_name: {
type: String,
required: true
},
last_name: {
type: String,
required: true
},
email: {
type: String,
unique: true,
match: [/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Please fill a valid email address'],
required: true
},
password:{
type: String
},
{
timestamps: true
});
What changes should i make collections to optimize the query?
Service.distinct('business',filter_services)
.exec(function (err, business) {
if (err) {
return cb({ status: 400, message: err }, null);
} else {
if(business.length > 0){
var filter_business = [{is_active:true},{is_approved:true}]
filter_business.push({_id:{$in:business}})
filter_business.push({location.coord:input_coord}})
filter_business = {$and:filter_business}
Business.find(filter_business)
.select('name services')
.exec(function (err,result){
if(err){
return cb({ status: 400, message: err }, null);
}
else{
if(result.length > 0){
var total = result.length;
}
return cb(null, result);
}
})
}
// si no hay business en el primer query, se retorna [].
else{
return cb(null, business);
}
}
});
Could geo filter by text and at the same time to get closer to a point?
For now, i am not using the Employee collection, but, if i would search by business name, employee name and service name simultaneously, what changes should make.
Your business model should be
var BusinessSchema = new Schema({
business_id: {
type: String,
required: true,
unique:true
},
name: {
type: String,
required: true
},
email: {
type: String,
},
description:{
type: String
},
address:{
country:{
type:String,
},
city:{
type:String
}
},
location : {
type: [Number],
index: '2dsphere'
},
services:[{
type: Schema.Types.ObjectId,
ref: 'Service'
}],
employees:[{
type: Schema.Types.ObjectId,
ref: 'User'
}]
},
{
timestamps: true
});
The change in schema is you have to create index on location, and for find business based on employee have to add employees id in business schema.Then you can you geo near query of mongodb.

one to many relationship in mongoose

I'm using mean stack to create a hybrid app.I'm using nosql to create DB in mongoose.My DB consists of two tables one is 'donors' and another one is 'bloodGroup'.
My 'bloodGroup' schema is as follows:
module.exports = function(mongoose) {
var Schema = mongoose.Schema;
/* bloodGroup Schema */
var bloodGroupSchema = new Schema({
name: { type: String, required: true }
});
}
My 'Donor'schema is as follows:
/* Donor Schema */
var DonorSchema = new Schema({
Name: { type: String, required: true },
DOB: { type: Date, required: true, trim: true },
Sex: { type: String },
BloodGroupID: { type: Schema.Types.ObjectId, ref: 'BloodGroup', required: true },
ContactNo: { type: String, required: true },
LocationId: { type: Schema.Types.ObjectId, ref: 'Location', required:true },
EmailId: { type: String, required: true },
Password: { type: String, required: true }
});
When many donors refer to a single blood group then BloodGroup object Id error is reported.How to solve this problem?
You can refer this link for documentation: http://mongoosejs.com/docs/populate.html
Saving Refs
/* Donor Schema */
var DonorSchema = new Schema({
_id : {type: Number},
Name: { type: String, required: true },
DOB: { type: Date, required: true, trim: true },
Sex: { type: String },
BloodGroupID: { type: Schema.Types.ObjectId, ref: 'BloodGroup', required: true },
ContactNo: { type: String, required: true },
LocationId: { type: Schema.Types.ObjectId, ref: 'Location', required:true },
EmailId: { type: String, required: true },
Password: { type: String, required: true }
});
/* bloodGroup Schema */
var bloodGroupSchema = new Schema({
_bid :{ type: Number, ref: 'Donor' },
name: { type: String, required: true }
});
module.exports = mongoose.model('Donor', DonorSchema);
module.exports = mongoose.model('Blood', bloodGroupSchema);
var vidya = new Donor({ _id: 0, name: 'Vidya', sex: 'F' });
vidya.save(function (err) {
if (err) return handleError(err);
var blood = new BloodGroup({
name: 'B+',
_bid: vidya._id // assign the _id from the Donor
});
blood.save(function (err) {
if (err) return handleError(err);
// thats it!
});
});
Mongo is not a Relational database, relation one to many does not exist in mongDB. The question is quite confusing, but following the title, you should either embed the donnors into the BloodGroup, or create an Id field unique to which you will refer and do two queries.

Resources