Mongoose populate embedded document in cascade - javascript

I am modeling a 'friends' relationship between the user of my micro-blog app. It looks something like this:
in the user.js file
var db = require('mongoose')
, Schema = db.Schema
, ObjectId=Schema.ObjectId;
var userSchema = new Schema({
name:{firstname:String,surname:String},
birthdate:String,
email:String,
posts: [new Schema({
timestamp:Date,
post:{type: ObjectId, ref: 'Post'}
})],
friends: [new Schema({
friend: {type:ObjectId, ref:'User'}
})]
});
module.exports = db.model('User', userSchema);
in the post.js file
var db = require('mongoose')
, Schema = db.Schema,
ObjectId=Schema.ObjectId;
var postSchema = new Schema({
title:String,
content:String,
});
module.exports = db.model('Post', eventSchema);
What I want to achieve is to get all the current user's friends, with their posts array of embedded document, already populated. I clumsily tried with this function:
function getUserFriendsPost(req, res) {
var count = 0;
var output = new Array();
User.findOne({
_id: req.params.id
}, function(err, user) {
for (var i = 0; i < user.friends.length; i++) {
User.findOne({
_id: user.friends[i].friend
}).populate('posts.post').exec(function(err, post) {
output.push(post);
count++;
if (count==user.friends.length) {
res.send(output);
}
});
}
});
}
What I get instead is the friends array correctly returned but the element of the posts having value of null, like this:
[
{
"_id": "4fd5e5f3e45fd10100000004",
"birthdate": "11/11/1911",
"email": "blablabla#gmail.com",
"friends": [],
"posts": [
{
"timestamp": "2012-04-12T16:47:14.576Z",
"post": null,
"_id": "4f870712c488cf0100000081"
},
{
"timestamp": "2012-04-12T16:48:42.282Z",
"post": null,
"_id": "4f87076ac488cf01000000a3"
},
{
"timestamp": "2012-04-12T16:56:26.062Z",
"post": null,
"_id": "4f87093ac488cf0100000117"
}
"name": {
"firstname": "John",
"surname": "Doe"
}
}
]
Is there something that I am overlooking the in populate mechanism or should I proceed with a different approach?
Thank you

With any luck we will get recursive populating in Mongoose 3.0. Until then consider duplicating the data you want from the post (likely only the title) and storing it like this:
var db = require('mongoose')
, Schema = db.Schema
, ObjectId = Schema.ObjectId;
var userSchema = new Schema({
name: {firstname: String, surname: String},
birthdate: String,
email: String,
posts: [new Schema({
timestamp: Date,
title: String,
post: {type: ObjectId, ref: 'Post'}
})],
friends: [new Schema({
friend: {type: ObjectId, ref: 'User'}
})]
});
module.exports = db.model('User', userSchema);
Then you can do a regular:
User.findOne({_id: req.params.id}).populate('friends').exec(function(err, user) { ... })

Related

.populate() not working

I have been working on this for hours and can't find a solution.
I am making a school directory using a
Student Model:
var mongoose = require("mongoose");
var studentSchema = new mongoose.Schema(
{
name: String,
courses: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Course"
}
]
});
module.exports = mongoose.model("Student", studentSchema);
and a Course Model...
var mongoose = require("mongoose");
var courseSchema = new mongoose.Schema (
{
name: String,
student: [
{
id:
{
type: mongoose.Schema.Types.ObjectId,
ref: "Student"
},
name: String
}
]
}
);
module.exports = mongoose.model("Course", courseSchema);
When I run .populate on a found student... it does not populate the Course values within the Student...
app.get("/students/:id", function(req, res){
Student.findById(req.params.id).populate("courses").exec(function(err, foundStudent){
if(err){
console.log(err);
} else {
console.log(foundStudent);
res.render("students/show", {student: foundStudent});
}
});
});
The console.log(foundStudent) will display...
{ _id: 597e7a49c945ee13529d0871,
name: 'Collin DeSoto',
__v: 1,
courses: [ { _id: 597e7a4dc945ee13529d0872 } ] }
AFTER the populate.. any ideas?
try this way
User.find(match, function (err, users) {
var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }]
var promise = User.populate(users, opts);
promise.then(console.log).end();
})
and prefar this link link

Mongoose population

I have this Mongoose Schema
var ItemSchema = new Schema({
"name":String,
"review": [{ type: Schema.Types.ObjectId, ref: 'Reviews'}]
});
and the schema of the review is:
var ReviewSchema = new Schema({
"title": String,
"user": { type: Schema.Types.ObjectId, ref: 'Users' }
});
and the schema of the users is:
var UserSchema = new Schema({
"name":String,
"surname":String,
});
This is the code to get the item:
Item.findOne({_id:req.params.idItem})
.populate('review')
.exec(function (err, item) {
console.log(item);
});
But this code only populates the reviews, and I want that to populate also the user.
Item.findOne({_id:req.params.idItem})
.populate({
path: 'review',
populate: {
path: 'user'
}
})
.exec(function(err, item) {});
http://mongoosejs.com/docs/populate.html#deep-populate

node.js api with array's

I'm pretty new to node.js and javascript. I'm builded and api and out of the sudden the data model changed and now i'm kinda lost.
This is my code:
var mongoose = require('mongoose');
//create schema
var MedicSchema = new mongoose.Schema({
nombre:{
type: String,
required: true
},
especialidad:{
type: String,
required: true
},
ranking:{
type: Number,
},
direccion: [{
direccion: {type: String, required: true},
telefono: {type: String},
horario:{type: String}
}],
foto:{
type: String,
}
});
MedicSchema.find({})
.populate('direccion')
.exec(function (err, medic) {
console.log(medic.direccion); // This should have your information now
});
//export model
module.exports = MedicSchema;
I'm able to send data to the direccion array... but when i call the api; i get this:
{
"_id": "557839b36bcdd00e09173e36",
"nombre": "Sra. Hong",
"especialidad": "general",
"__v": 0,
"direccion": [
{
"_id": "55a44392b2e774572b957a8e"
},
{
"_id": "55a44392b2e774572b957a8d"
}
]
}
i can't find a way to call the details of the array.
edit: i posted it on bitbucket https://bitbucket.org/weput/api-server
You need to .populate your "direccion" array. For example:
MedicSchema.find({})
.populate('direccion')
.exec(function (err, medic) {
console.log(medic.direccion); // This should have your information now
});

How can I check if the user already follows other users in NodeJs - Mongoose

I have a followSchema:
var followSchema = mongoose.Schema({
user : { type: Number, ref: 'User'},
following : { type: Number, ref: 'User'}
});
I have two users.
Of the first one I need to have a list of all the users he follows.
The second one I need to check if he already follows some of the users that I gathered from the first one.
How can I do this in an affective way in Mongoose.
To get a list of followers from the first user isn't that hard, but to check if the second user follows one of them is a little harder and I have no idea how I can manage that.
This is fairly simple, all you need to do is query for the two conditions. Assuming "Follow" as the model:
Follow.find({
"user": 1,
"following": 2
})
Depending on your "scale" though, the following schema might be more useful:
var userSchema = new Schema({
"_id": Number,
"name": String,
"following": [{ "type": Number, "ref": "User" }],
"followedBy": [{ "type": Number, "ref": "User" }]
})
The query is almost identical:
User.find({
"_id": 1,
"following": 2
})
But of course it always gives you other options, as long as the general constraints for best practice with "arrays" can be adhered to.
One approach you can take is to modifying your followSchema to have the following field as an array and use the concept of population:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var userSchema = Schema({
_id: Number,
name: String,
age: Number,
followers: [{ type: Schema.Types.ObjectId, ref: 'Follow' }]
});
var followSchema = Schema({
_user: { type: Number, ref: 'User' },
following: [{ type: Number, ref: 'User' }]
});
var Follow = mongoose.model('Follow', followSchema);
var User = mongoose.model('User', userSchema);
which you can then query with the some sample users. As an example guide (untested):
var user1_id = 1,
user2_id = 2,
user3_id = 3,
user1_following = [],
user2_following = [];
var user1 = new User({ _id: user1_id, name: 'User1', age: 31 });
var user2 = new User({ _id: user2_id, name: 'User2', age: 32 });
var user3 = new User({ _id: user3_id, name: 'User3', age: 32 });
user3.save(function (err) {
if (err) return handleError(err);
})
user1.save(function (err) {
if (err) return handleError(err);
var follower3 = new Follow({ _user: user3_id });
follower3.save(function (err) {
if (err) return handleError(err);
// thats it!
});
})
user2.save(function (err) {
if (err) return handleError(err);
var follower3 = new Follow({ _user: user3_id });
follower3.save(function (err) {
if (err) return handleError(err);
// thats it!
});
})
Follow
.find({ _user: user1_id })
.exec(function (err, following) {
if (err) return handleError(err);
user1_following = following;
})
Follow
.find({ _user: user2_id })
.exec(function (err, following) {
if (err) return handleError(err);
user2_following = following;
})
You can then use Underscore's intersection() which will give you a list of values present in both arrays.
var commonFollowings = _.intersection(user1_following, user2_following);
// In the example above, commonFollowings => [3]

How to change sub document after finding with mongoose

I have some code like below using mongoose.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/hoge');
var UserSchema = new Schema({
name: String,
children: [ChildSchema],
});
var ChildSchema = new Schema({
name: String,
}, {_id: false});
var User = mongoose.model('User', UserSchema);
var Child = mongoose.model('Child', ChildSchema);
User.findOne({_id: '52299322fdbbdec515000001'}, function(err, user) {
console.log(user);
for (var i=0; i<user.children.length; i++) {
var child = user.children[i];
child.name = 'newchild';
}
user.save(function(err) {
console.log(user);
mongoose.disconnect();
});
});
And here is my record in mongodb.
{
"name" : "u1",
"_id" : ObjectId("52299322fdbbdec515000001"),
"children" : [ { "name" : "c2" } ],
"__v" : 0
}
When I run the script, it outputs below.
{ name: 'u1',
_id: 52299322fdbbdec515000001,
__v: 0,
children: [ { name: 'c2' } ] }
{ name: 'u1',
_id: 52299322fdbbdec515000001,
__v: 0,
children: [ { name: 'newchild' } ] }
But my record in mongodb has not been changed. Why?
FYI, the record changed if I insert this code before saving.
user.children.push({name: 'somechild'});
Sorry, I've resolved myself.
The problem is the order of declarating Schemas.
It worked if I tried this change.
/* first, children's schema */
var ChildSchema = new Schema({
name: String,
}, {_id: false});
/* seconds, parent's schema */
var UserSchema = new Schema({
name: String,
children: [ChildSchema],
});

Categories

Resources