How can I store data other than ObjectId using Mongoose populate? - mongodb

Taking the example from here
http://mongoosejs.com/docs/populate.html
If I try to tweak it so that 'fans' also contains a rating
var db = require('houselib/db');
var Schema = db.Schema;
var mongoose = db.mongoose;
var PersonSchema = new Schema({
name : String
, age : Number
, stories : [{ type: Schema.ObjectId, ref: 'Story' }]
});
var StorySchema = new Schema({
_creator : { type: Schema.ObjectId, ref: 'Person' }
, title : String
, fans : [{ type: Schema.ObjectId, ref: 'Person', rating: Number}]
});
var Story = mongoose.model('Story', StorySchema);
var Person = mongoose.model('Person', PersonSchema);
var aaron = new Person({ name: 'Aaron', age: 100 });
aaron.save(function (err) {
if (err) throw err;
var story1 = new Story({
title: "A man who cooked Nintendo"
, _creator: aaron._id
, fans: [{type: aaron._id, rating: 4}]
});
story1.save(function (err) {
if (err) throw err;
Story
.find({ _creator: aaron._id })
.populate('_creator') // <-- not really necessary
.run(function (err, stories) {
if (err) throw err;
console.log('The stories JSON is an array: ', stories);
})
});
})
I get the following error
CastError: Cast to undefined failed for value "[object Object]"

The documentation says that manual linking is preferred over DBRef
http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-SimpleDirect%2FManualLinking

story.fans is an array of objectids. objectids do cannot have ratings. You need to add the rating to the Person schema instead of the story schema.
var PersonSchema = new Schema({
name : String
, age : Number
, rating: Number
, stories : [{ type: Schema.ObjectId, ref: 'Story' }]
});

Related

deep populating in mongoose

I've got two schemas,
one for user and another one for post
in the user schema, I've got a property for latestPost which would be an ObjectId of an entry in the post schema
when I load up the user object,
I want to get the lastestPost as an object that includes the author's username from the user schema where the author is an ObjectId that'd match an _id field in the user schema.
the mongoose tutorials seem to use the syntax of
User.findOne({ _id: req.user.id})
.populate('latestPost')
.populate({ path: 'latestPost', populate: 'author'})
but it doesn't work
it's showing
{ _id: 58f54fa51febfa307d02d356,
username: 'test',
email: 'test#test',
firstName: 'test',
lastName: 'test',
__v: 0,
latestPost:
{ _id: 58f54fa51febfa307d02d357,
user: 58f54fa51febfa307d02d356,
author: 58f54fa51febfa307d02d356,
date: 2017-04-17T23:28:37.960Z,
post: 'Test',
__v: 0 } }
but I want it to show
latestPost:
{
author: {
username : something
}
}
how does one do something like this? is there something wrong with the design of the schema or the query?
var UserSchema = new Schema({
username : String,
firstName : String,
lastName : String,
email : String,
password : String,
views : Number,
latestPost : { type: Schema.Types.ObjectId, ref: 'Post' }
});
var PostSchema = new Schema({
user : { type: Schema.Types.ObjectId, ref: 'User' },
author : { type: Schema.Types.ObjectId, ref: 'User' },
date : Date,
body : String
});
var User = mongoose.model('User', UserSchema);
var Post = mongoose.model('Post', PostSchema);
User.findOne({ _id: req.user.id})
.populate('latestPost')
.populate({ path: 'latestPost', populate: 'author'})
.exec(function(err, user) {
if (err) res.json(err)
console.log(user)
})
Maybe just this.
I don't think you need .populate('latestPost') as your next .populate() should take care of populating the latestPost. Maybe that is interfering with the next one.
User.findOne({ _id: req.user.id }).populate({
path: 'latestPost',
model: 'Post',
populate: {
path: 'author',
model: 'User'
}
}).exec(function (err, user) {
});
You need to provide the model name also in populate function:
var UserSchema = new Schema({
username : String,
firstName : String,
lastName : String,
email : String,
password : String,
views : Number,
latestPost : { type: Schema.Types.ObjectId, ref: 'Post' }
});
var PostSchema = new Schema({
user : { type: Schema.Types.ObjectId, ref: 'User' },
author : { type: Schema.Types.ObjectId, ref: 'User' },
date : Date,
body : String
});
var User = mongoose.model('User', UserSchema);
var Post = mongoose.model('Post', PostSchema);
User.findOne({ _id: req.user.id})
.populate('latestPost')
.populate({
model: 'Post',
path: 'latestPost',
select: 'author -_id'
})
.exec(function(err, user) {
if (err) res.json(err)
console.log(user)
})

Mongoose Populate a field

I have two mongoose schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var itemSchema = new Schema({
name: {type: String, required: true, max: 25, trim: true},
price: {type: Number, required: true, trim: true, default: 0},
tax: {
type: Schema.Types.ObjectId,
ref: "Store"
}
});
module.exports = mongoose.model('Item', itemSchema);
The second Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var storeSchema = new Schema({
name: {type: String, required: true, trim: true},
taxes: [
{
name: String,
rate: Number
}
]
});
module.exports = mongoose.model('Store', storeSchema);
What I want to do is populate the itemSchema tax object with the storeSchema taxes array of object. every time I pushed a new tax object to the taxes array mongoose created an ObjectId. I stored that ObjectId in my itemSchema Tax. I want to use that _id to retrieve the store taxes that matches the itemSchema _id.
I have tried this so far, but I get no in the tax attribute.
Item.find().populate("tax", "taxes").exec(function (err, docs) {
if (err) return console.error(err);
console.log(items);
});
Try this query
Item.find().populate({
path: 'tax',
select: 'taxes'
}).exec(function (err, docs) {
if (err) {
console.error(err);
} else {
console.log(docs);
}
});
Item.find().populate(path:"tax", model: )
Mention your item model file name... don't use "" or '' for the file name, simply add the file name.
Use Item.find().populate("Store", "taxes") instead of Item.find().populate("tax", "taxes").

`_id` in where clause

I face an issue trying to access _id in a query.where.
My schema:
var testSchema = new Schema({
test2id: [{ type: Schema.Types.ObjectId, ref: 'Test2' }],
test3id: [{ type: Schema.Types.ObjectId, ref: 'Test3' }]
});
var test2Schema = new Schema({
name: String
});
var test3Schema = new Schema({
name: String
});
My query:
testSchema.statics.findByid = function (id, callback) {
var query = this.findOne();
Test2.findOne({'name': name}, function (error, t2) {
query.where({
test2id: _id,
}).exec(callback);
});
return query
};
_id is undefined, I try also this._id but the query return null.
I just want to get all documents from testSchema with test2id = _id of the testSchema document.
Any idea to fix that and access to _id from a query.where clause?
I finally resolve it by passing it in parameter.
var test = new Test();
test.findByid(test._id, req.params.id, function(err, res) {
...
});

null results of search by _id in mongoose

I'm getting [] res in mongoose find by {parentId: cat._id}
var ObjectId = Schema.ObjectId;
var CategorySchema = new Schema({
name: String,
slug: String,
parentId: {type: ObjectId, required: false},
ancestors: {
type: [{
_id: ObjectId,
name: String,
slug: String
}], required: false
}
});
CategorySchema.statics.getNested = function(parentSlug,cb){
this.findOne({slug:parentSlug},function(err,cat){
if (err) {
cb(err);
} else {
this.find({parentId: cat._id},function(err, cats){
console.log(cats);
if (err){
cb(err);
} else {
cb(null,cats);
}
});
}
});
};
I tried {parentId: ObjectId(cat._id)} but this did not work too // ObjectId(cat._id) -> undefined
How do I search mongoose by _id?
UPDATE!
The query
Category.find({parentId:'5634eeb38a33a59c1dffa6ee'}, function(err,res){
console.log(res);
});
is working fine but how?
It should be {parentId: mongoose.Types.ObjectId(cat._id)}
You have incorrect ObjectId type in your schema, you should use Schema.Types.ObjectId instead of Schema.ObjectId because they return different values:
http://mongoosejs.com/docs/api.html#schema-objectid-js
http://mongoosejs.com/docs/api.html#types-objectid-js
If you replace your ObjectId definition to the following
var ObjectId = Schema.Types.ObjectId;
your code should work correctly.

Mongoose: how to set a schema-field to be the ID?

Given the following schema:
var UserSchema = new Schema({
, email : { type: String }
, passwordHash : { type: String }
, roles : { type: [String] }
});
I'd like email to be the key.
How can I define this?
I could do:
var UserSchema = new Schema({
, _id: { type: String }
, passwordHash : { type: String }
, roles : { type: [String] }
});
so MongoDB would recognize it as the id-field, and adapt my code to refer to _id instead of email but that doesn't feel clean to me.
Anyone?
Since you're using Mongoose, one option is to use the email string as the _id field and then add a virtual field named email that returns the _id to clean up the code that uses the email.
var userSchema = new Schema({
_id: {type: String},
passwordHash: {type: String},
roles: {type: [String]}
});
userSchema.virtual('email').get(function() {
return this._id;
});
var User = mongoose.model('User', userSchema);
User.findOne(function(err, doc) {
console.log(doc.email);
});
Note that a virtual field is not included by default when converting a Mongoose doc to a plain JS object or JSON string. To include it you have to set the virtuals: true option in the toObject() or toJSON() call:
var obj = doc.toObject({ virtuals: true });
var json = doc.toJSON({ virtuals: true });