How to find in mongoose with deep population? - node.js

I succeed to make a deep population with find and the search key in first model, but now i want to find by key on the sub object generated by the deep populate.
I have three models : Product, Category, and Event
I want to find my Products by e_fk_club_id that is in Event model
I tried two solutions but they didn't work
First solution in find :
model.find({'categories.events.e_fk_club_id':id})`
Second solution with match :
`$match : { e_fk_club_id : id }`
these are my models
product.js
var ProductSchema = new mongoose.Schema({
p_id: Number,
p_name: String,
p_fk_category: {type: mongoose.Schema.Types.ObjectId, ref: 'categories'},
}
, {collection: 'products'});
module.exports = mongoose.model('products', ProductSchema);
Category.js
var CategorySchema = new mongoose.Schema({
c_id: Number,
c_name: String,
c_fk_event: {type: mongoose.Schema.Types.ObjectId, ref: 'events'},
}
, {collection: 'categories'});
module.exports = mongoose.model('categories', CategorySchema);
Event.js
var EventSchema = new mongoose.Schema({
e_id: Number,
e_name: String,
e_fk_club_id: Number,
}
, {collection: 'events'});
module.exports = mongoose.model('events', EventSchema);
This is the code which i am trying to fetch the data :
getProductsByClub:function (id, callback){
var model = require("Product");
//model
model .find({'categories.events.e_fk_club_id':id})
.populate({
path:'p_fk_category',
model:'categories',
populate:
{
path:'e_fk_event',
model:'events',
//$match : { e_fk_club_id : id }
}
})
.exec (function(err, doc){
if (err) {
callback(err) ;
} else {
callback(doc) ;
}
})
},
Is There any solution.
Thank you in advance.

Related

Join two collection in mongoose using nodejs

I want to join two collection in MongoDB. I have two collections 1. student 2. course.
student collection:
course collection
I tried some code but that is not working.
This is my code
student.js
router.get('/student/:id', function(req, res){
Student.find({_id:req.params.id}, function(err, user){
res.send(user);
})
})
This is Schema:
student.js
const mongoose = require('mongoose');
let StudentSchema = mongoose.Schema({
name:{
type: String
},
email:{
type: String
},
phone:{
type: String
},
password:{
type: String
},
course :[{
type: mongoose.Schema.Types.ObjectId,
ref: 'Course'
}]
}, { collection: 'student' });
const Student = module.exports = mongoose.model('Student', StudentSchema);
course.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let CourseSchema = mongoose.Schema({
student_id:{
type: String
},
course_name:{
type: String
},
course_cost:{
type: String
}
}, { collection: 'course' });
const Course = module.exports = mongoose.model('Course', CourseSchema);
Result:
you need to query like this :
findOne : to find single document (return object {} )
find : to find multiple documents (return array [])
Student.findOne({_id:req.params.id}, function(err, student){
if(!err && student){
Courses.find({student_id:req.params.id},function(error,courses){
if(!error && courses){
student.courses=courses;
}else{
student.courses=[];
}
res.send(student);
});
}
});
currently you are getting course :[] , because there is no field found in students collection , as you can see in photo-1
you need to set course :["coures_id1","coures_id2"] while inserting a document in student collection.
then you can use mongoose populate to populate course into students
Student.findOne({_id:req.params.id}).populate('course').exec(function(err,student){
res.send(student);
});
so after than no need to store , student_id field in courses collection , as you are getting from students collection.

Mongoose: Find from reference object document

I am trying to search data from collection.
Model for 'USER' collection:
var model = new Schema({
userName: String,
password: String
});
module.exports = mongoose.model('user', model);
Model for 'BLOG'
var model = new Schema({
title: String,
createdBy: { type: Object, ref: 'user' }
});
module.exports = mongoose.model('blog', model);
My search code for blog collection:
objModel.find({ 'createdBy.userName': 'test_user' }).populate('createdBy')
.exec(function (err, lstBlog) {
console.log(lstBlog.length);
});
But not able to get any record. There are 2 record in database for 'test_user'.
You need to make some changes in your 'BLOG' model :
var mongoose = require('mongoose');
var SCHEMA = mongoose.Schema;
var model = new Schema({
title: String,
createdBy: { type: SCHEMA.Types.ObjectId, ref: 'user' }
});
module.exports = mongoose.model('blog', model);
and then the following query will work
blog.find({}).populate(
{
path: 'createdBy',
match: {'userName': 'test_user' }
}
).exec(function (err, lstBlog) {
console.log(lstBlog.length);
});;

How to push data into array using mongoose, with schema having single only single object

I am learning Mongoose, and got struct on pushing data into array blogs.
my schema is
module.exports = function(mongoose) {
var UserSchema = new Schema({
count:String,
_id : {id:false},
blogs: [{ type: Schema.Types.ObjectId, ref: 'Blog' }]
},
{
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
});
var BlogSchema = new Schema({
blogs:[{
post : String,
title: String,
author : String,
userId: {
type: String,
default: function() {
return crypto.randomBytes(12).toString('hex');
}
},
_id: {type: String, required: true}
}],
});
var models = {
User : mongoose.model('User', UserSchema),
Blog : mongoose.model('Blog', BlogSchema)
};
return models;
}
Problem is here userSchema will always have/be a single object, whcih will keep track of count of total blogs.
I know it can be done using findOneAndUpdate but I don't have id/object created for UserSchema.
Any help is appreciated. Thanks

Mongoose, how do I join to collections using populate?

First Schema:
const ProviderSchema = new mongoose.Schema({
provName : { type: String, index: true }
});
module.exports = mongoose.model('provider', ProviderSchema);
Second Schema:
const WebProviderSchema = new mongoose.Schema({
userId : { type: Schema.Types.ObjectId, ref: 'users'},
providerId : { type: Schema.Types.ObjectId, ref: 'providers'}
});
module.exports = mongoose.model('webProvider', WebProviderSchema);
How do I join these two schemas?
So far if I do the following, I only get data from the second schema:
webProvider
.find({userId : '23423df234434bc956'})
.populate("providers")
.exec( function (error, listData) {
console.log(listData);
});
To populate you should use local field providerId. Should be .populate("providerId") instead of .populate("providers").
webProvider.find({userId : '23423df234434bc956'})
.populate("providerId")
.exec( function (error, listData) {
console.log(listData);
});
To populate multiple field can use like :
.populate("providerId userId")
or
.populate("providerId")
.populate("userId")

Mongoose Refs to children

I am struggling to find examples or documentation on mongoose children population.
http://mongoosejs.com/docs/populate.html
On the documentation they have:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
It makes sense, a Person can have many stories thus the 'parent' field 'stories' which has a list of all the stories in.
What I am struggling to understand is how do you push the the story into the person schema.
For example, i have an assignment schema:
var mongoose = require ( 'mongoose' ),
Schema = mongoose.Schema;
var assignmentSchema = new Schema (
{
_id: String,
assignName: String,
modInsID: [{ type: Schema.Types.Number, ref: 'ModuleInst' }],
studentAssigns: [{type: Schema.Types.ObjectId, ref: 'StudentAssign' }]
}
);
module.exports = mongoose.model ( 'Assignment', assignmentSchema );
The studentAssigns stores all the id's of the studentAssigns which then can be used with the .pre middleware for cascade deleting.
So now my StudentAssign schema:
var mongoose = require ( 'mongoose' ),
autoIncrement = require ( 'mongoose-auto-increment' ),
Schema = mongoose.Schema;
var connection = mongoose.createConnection("************");
autoIncrement.initialize(connection);
var studentAssignSchema = new Schema (
{
assID: [{ type: Schema.Types.String, ref: 'Assignment' }],
studentID: [{ type: Schema.Types.Number, ref: 'Student' }]
}
);
var StudentAssign = connection.model('StudentAssign', studentAssignSchema);
module.exports = mongoose.model ('StudentAssign', studentAssignSchema );
As you can see it already is referencing 'Assignment'
Here is my api code:
studentAssign POST:
router.route('/student-assignment').post( function(req, res) {
var studentAssign = new StudentAssign();
studentAssign.assID = req.body.assID;
studentAssign.studentID = req.body.studentID;
studentAssign.save(function(err, studentAssign) {
if(err) console.log(err);
res.status(200).json(studentAssign);
});
})
So that's the part I am confused at where would I push the 'studentAssign' into 'Assignment' schema's 'studentAssigns array ??
here is my current api json callback:
[
{
"_id": "As 1",
"assignName": "Software Implementation",
"__v": 0,
"studentAssigns": [],
"modInsID": [
{
"_id": 22,
"semester": "TRI 3",
"year": 2016,
"__v": 0,
"modID": [
111
]
}
]
}
]
The documentation just does not make it clear as they just show:
aaron.stories.push(story1);
aaron.save(callback);
With no explanation?
I have attempted:
var assignment = new Assignment();
assignment.studentAssigns.push(studentAssign); and nothing gets stored ??
Here is a working example based on the documentation docs
const mongoose = require('mongoose');
const { Schema } = mongoose;
const personSchema = Schema({
_id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
const storySchema = Schema({
author: { type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
const Story = mongoose.model('Story', storySchema);
const Person = mongoose.model('Person', personSchema);
Person model has its stories field set to an array of ObjectId's
For saving Refs to children you may have first to save stories before pushing them to Person's stories field
const story1 = new Story({
title: 'Casino Royale',
author: author._id // assign the _id from the person
});
story1.save();
And before pushing story1 find the author id you want to push to
const author = await Person.findOne({_id: "624313f302e268b597b8df1f"})
if(Array.isArray(author.stories)) author.stories.push(story1);
author.save()
You model states :
assID: [{ type: Schema.Types.String, ref: 'Assignment' }],
studentID: [{ type: Schema.Types.Number, ref: 'Student' }]
I think from your code you don't want to store multiple assignments in assID and multiple Students in studentID. Modify your model to
assID: { type: Schema.Types.String, ref: 'Assignment' },
studentID: { type: Schema.Types.Number, ref: 'Student' }
Your save code can stay the same.
If you do want to store for example multiple assignments, you need to push them into the assID array ;-)
router.get('/author', (req, res, next) => {
Person.
find().
exec( (err, person) => {
if (err) return handleError(err)
Story.find({author: person[0]._id}).
exec( (err, story) => {
if (err) return handleError(err)
person[0].stories.push(story[0])
res.json( { person: person })
})
})
})

Resources