i'm having a problem with updating a member in schema that contained in other schema.
var User = new mongoose.Schema({
first_name : { type: String, required: true , lowercase: true},
last_name : { type: String, required: true , lowercase: true},
log : { type: [Log], default: [Log] },
});
var Log = new mongoose.Schema({
left_groups : [{ type: mongoose.Schema.Types.ObjectId, ref: 'Group' }],
});
i'm trying to update the left_groups member (from the user) which is a reference to group schema and i can't do that.
after a research on the net, the best i came up with is:
User.update({_id: "549a972f243a461c093f8ebb"}, {log:{$push:{left_groups: gr}}}, function () {
console.log("updated")
});
and this seems not working for me.
//gr[0] means for group.
i succeed to figure it out..
i'm not sure it's a proper solution though:
Group.findOne({_id: "549b18c73117388028c3990f"}, function (err, gr) {
User.findOne({_id: '549b18c73117388028c39904'}, function(err, user){
user.log[0].left_groups.push(gr);
user.save();
});
})
Related
Hello so I am making a basic app with users and posts.
I followed the mongoose documentation on population (http://mongoosejs.com/docs/2.7.x/docs/populate.html) and setup my Schemas so that the users and be connected to posts
var userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
email: String,
created_at: Date,
updated_at: Date,
admin: Boolean,
posts: [{ type: mongoose.Schema.ObjectId, ref: 'Post' }]
});
var postSchema = new mongoose.Schema({
_user : [{ type: mongoose.Schema.ObjectId, ref: 'User' }],
audioFile: { type: String, required: true },
imageFile: { type: String },
title: { type: String, required: true },
artist: { type: String, required: true },
start: { type: String, required: true },
stop: { type: String, required: true },
genre: { type: String, required: true },
tags: [{ type: String }]
});
app.get('/', function (req, res){
Post.find({}, function(err, allPosts){
if(!err){
res.render('main.njk', {
posts : allPosts,
title : 'Title',
isLogged : req.session.isLogged,
user : req.session.user,
messages : req.flash('alert')
});
} else { return done(err); }
});
});
Thats all fine and gravy and I can run a foreach loop on allPosts to pull each one in my HTML, but when I try to think of how I am going to display all the posts with their respective users attached to each post I am unsure of how to connect the two since all the examples in the mongoose doc is just mainly for findOne.
I was thinking something like this
app.get('/', function (req, res){
Post.find({}, function(err, allPosts){
if(!err){
allPosts.populate('_user', ['username']);
allPosts.exec(function (err, users){
if(err) console.log(err);
console.log(users);
});
res.render('main.njk', {
posts : allPosts,
title : 'Spaurk.net',
isLogged : req.session.isLogged,
user : req.session.user,
messages : req.flash('alert')
});
} else { return done(err); }
});
});
but that doesn't work of course.
So I was wondering if anyone with experience with this situation would be able to help me solve this.
Thanks a lot for any input.
EDIT, thanks to Daves help I was able to get the populate to work properly, I just cant pull the fields I want correctly with
Post.find({}).populate('_user').exec(function(err, allPosts){
In my loop {% for post in posts %}
, when I do post._user it shows the whole user schema, but when I do post._user.username it doesn't return anything. I am unsure as to why this is.
The proper way to structure a populate on a query is like this:
Post.find({})
.populate('_user')
.exec((err, allposts){...})
Then you will have an array of your Posts with the _user array populated. If you need to access a property of a user, you will need to do another loop through the _user array or specify with use you want to use _user[0].<property>
This question already has answers here:
Querying after populate in Mongoose
(6 answers)
Closed 6 years ago.
Mongo is driving me crazy. I have these schemas:
var userSchema = new Schema({
username: {
type: String,
require: true,
unique: true
},
password: {
type: String,
require: true,
}
});
var User = mongoose.model('user', userSchema);
var deviceSchema = new Schema({
name: {
type: String,
require: true,
unique: true
},
type: String,
lastvalue: {
type: Schema.ObjectId,
ref: 'event'
},
owner: {
type: Schema.ObjectId,
ref: 'user',
require: true
},
apiKey: {
type: String,
unique: true,
default: function() {
return crypto.randomBytes(64).toString('hex');
}
}
});
var Device = mongoose.model('device', deviceSchema);
and I want to retrieve all devices of a user. So:
Device.find({'owner.username': req.params.username})
But it returns an empty array!
I've also tried:
Device.find({'owner.username': req.params.username}, {'owner':1})
Device.find({'owner.username': req.params.username}, {'owner.$':1)
Without any luck...
I've searched the whole internet but I can't find anything useful!
You need to get the associated user _id first then query the Device model on the owner field using the _id from the first user query. The following shows this approach:
User.findOne({ "username" : req.params.username }),
.exec(function(err, user) {
if (err) throw err;
Device
.find({"owner": user._id})
.populate('owner', 'username') // only return the username
.exec(function(err, devices) {
if (err) throw err;
console.log(JSON.stringify(devices, undefined, 4));
});
}
);
I have two mongoose schema as following
var ServiceSubType = new Schema({
displaySubTypeName : String,
subTypeDescription : String,
status : { type: String, default: Constants.ACTIVE },
lastUpdatedOn : Date,
createdOn : { type: Date, default: Date.now }
} , { collection: 'SERVICE_SUB_TYPES' });
and
var ServiceType = new Schema({
displayName : String,
description : String,
status : { type: String, default: Constants.ACTIVE },
lastUpdatedOn : Date,
serviceSubTypeId : {type: Schema.Types.ObjectId, ref: 'ServiceSubType', index: true},
createdBy : { type: Schema.Types.ObjectId, ref: 'SystemUser', index: true },
createdOn : { type: Date, default: Date.now }
} , { collection: 'SERVICE_TYPES' });
I have populated Type Object as below
module.exports.addNewServiceType = function(serviceType_obj, callback) {
serviceType_obj.save(serviceType_obj,callback);
}
Now I am trying to populate ServiceSubType document and then at the same time trying to populate "serviceSubTypeId" of ServiceType object referenced to ServiceSubType created.
Here is my piece of code for the same purpose.
module.exports.addServiceSubType = function(serviceTypeObjId, serviceSubType_obj, callback) {
serviceSubType_obj.save(serviceSubType_obj, function (error, serviceSubType) {
});
serviceSchema.ServiceType.findById(serviceTypeObjId, function (err, serviceType) {
var opts = { path: 'serviceSubTypeId'};
serviceSchema.ServiceType.populate(serviceType, opts, function (err, user) {
console.log(serviceType);
});
}).exec(callback);
}
But it is not workign and not populating any value in Existing SubType object.
I admit my approach could be very wrong as I am very new in this technology. Appreciate any kind of help to run this piece of code as expected.
Thanks
Ajoy
I think your ref should be the same setting as the collection on the object
serviceSubTypeId : {
type: Schema.Types.ObjectId,
ref: 'SERVICE_SUB_TYPES', <==== your collection type goes here
index: true
},
Mongoose doesn't know anything about your JavaScript object types. Instead, it tracks things based on the collection name that you provide (or that it generates).
update based on comments below
I have some example code that I wrote a while back, and it looks like I'm letting Mongoose generate the collection name for me. However, I am supplying a name to the mogoose.model() call, when registering my type for a collection.
For example, I have a Post type and a User type. The Post contains an author which is a reference to the User.
It looks like this:
// post
// ----
var PostSchema = new mongoose.Schema({
date: {type: Date, required: true, default: Date.now},
title: {type: String, required: true},
content: {type: String, required: true},
author: {
type: SchemaTypes.ObjectId,
ref: "user"
},
comments: [CommentSchema]
});
var Post = mongoose.model("blog", PostSchema);
// user
// ----
var UserSchema = mongoose.Schema({
firstName: {type: String},
lastName: {type: String},
username: {type: String, required: true, index: {unique: true}},
email: {type: String, required: true},
password: {type: String, required: true},
url: {
type: mongoose.Schema.Types.ObjectId,
ref: "url"
}
});
User = mongoose.model("user", UserSchema);
In this example code, I'm setting the ref to "user" because I am registering my model as "user" down below, in the mongoose.model method call.
Are you registering your models using mongoose.model and supplying a name? if so, use that name.
I have two models like this:
var UserSchema = mongoose.Schema({
name : {type: String, required: true},
image : {type: String, required: true}
});
var RoomSchema = mongoose.Schema({
_user : {type: mongoose.Schema.ObjectId, ref: 'User', required: true},
name : {type: String, required: true}
});
I know how to use populate like this:
Room.findOne({_id : req.body._id}).populate('_user').exec(function(err, room){
console.log(room);
});
And works fine, my problem is that I need to write something like (witch is wrong):
Room.findOne({_id : req.body._id}, function(err, room){
room.populate('_user');
console.log(room);
});
Because I have no access to the function that find the rooms and I have a long list of different Objects Ids that I need to populate. Any ideas how to solve this problem?
You can use Model.populate to do this:
Room.findOne({_id : req.body._id}, function(err, room){
Room.populate(room, {path: '_user'}, function(err, room) {
console.log(room);
});
});
can someone please help me with population of this schema? I need to populate array of Staff by their userId.
var PlaceSchema = new Schema ({
name: { type: String, required: true, trim: true },
permalink: { type: String },
country: { type: String, required: true },
...long story :D...
staff: [staffSchema],
admins: [adminSchema],
masterPlace:{ type: Boolean },
images: []
});
var staffSchema = new Schema ({
userId: { type: Schema.Types.ObjectId, ref: 'Account' },
role: { type: Number }
});
var adminSchema = new Schema ({
userId: { type: Schema.Types.ObjectId, ref: 'Account'}
})
var Places = mongoose.model('Places', PlaceSchema);
I tried to use this query, but without success.
Places.findOne({'_id' : placeId}).populate('staff.userId').exec(function(err, doc){
console.log(doc);
});
Polpulation is intended as a method for "pulling in" information from the related models in the collection. So rather than specifying a related field "directly", instead reference the related fields so the document appears to have all of those sub-documents embedded in the response:
Places.findOne({'_id' : placeId}).populate('staff','_id')
.exec(function(err, doc){
console.log(doc);
});
The second argument just returns the field that you want. So it "filters" the response.
There is more information on populate in the documentation.