Cast Errors While Populating Referenced Mongoose Documents - node.js

My schema looks like the following:
User Schema {
name: String,
email: String
}
Job Schema {
title: String,
owner: { type: Schema.Types.ObjectId, ref: 'User' },
helper: { type: Schema.Types.ObjectId, ref: 'User' }
}
Both Users and Jobs use ObjectId's as their ID type.
Part of my application requires me to query the job collection for jobs that fit certain criteria. As part of this query I perform a population of the referenced user documents. Somethings like the following:
Job
.find(query, null, options)
.populate('owner helper', 'name email')
.sort(sort)
.exec(err, function(results) {
...Do Something with populated documents
})
However, this is throwing an error.
{ message: 'Cast to ObjectId failed for value "b" at path "_id"',
name: 'CastError',
type: 'ObjectId',
value: 'b',
path: '_id' }
I have checked all of the user object's ids and they all seem valid. I don't understand what could be causing this error.
Any help would be appreciated.

Related

How to populate a document inside an array inside another document?

Sorry if title looks complicated... I couldn't think of a better way to describing it.
My real case situation matches the following Schemes:
Collection1:
const mongoose = require('mongoose');
const itemSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: [true, 'Name is required.'] },
quantity: { type: Number, required: [true, 'Quantity is required.'] },
collection2: { type: mongoose.Schema.Types.ObjectId, ref: 'Collection2' }
}, { _id : false });
const collection1Schema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: [true, 'Name is required.'] },
imagePath: { type: String, required: [true, 'Image is required.'] },
items: [itemSchema]
});
module.exports = mongoose.model('Collection1', collection1Schema);
Note: itemsSchema is inside the collection1 file (and having no declared _id's) because they only exist for the Collection1 model (considering "quantity" and other fields I removed for simplification). This itemsScheme is not needed elsewhere as another collection.
Collection2:
const mongoose = require('mongoose');
const collection2Schema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: [true, 'Name is required.'], unique: true }
});
module.exports = mongoose.model('Collection2', collection2Schema );
Note: Other properties (such as 'imagePath') were removed for simplification.
Now, this is the query I am trying to run:
Collection1.find()
.populate({
path: 'items',
populate: {
path: 'collection2', model: 'Collection2'
}
})
.then(...)
.catch(...);
And this is the error message I am getting when I run it:
Error fetching collection1: Cast to ObjectId failed for value "{
name: 'an item name',
quantity: 750
}" at path "_id" for model "Collection1"
The exact same error happens if I just run:
Collection1.find()
.populate('items')
.then(...)
.catch(...);
Maybe I cannot run .populate('items') because it has no declared model. If this is the case, how can I populate collection2 while querying collection1? Again, I cannot consider storing items in a separated collection.
But if I run:
Collection1.find()
.populate('collection2')
.then(...)
.catch(...);
I get the items, no errors, but it doesn't populate collection2. Well, it makes sense for the items because they're just an array of a block of properties inside collection1. But what about populating collection2?
Collection2 already has a few documents added, all with their _ids and other fields well filled. In the controller, I set _id: new mongoose.Types.ObjectId(), while creating a new document for both cases, Collection1 and Collection2.
In the front-end, I create a new document for Collection1, I add items, each item with a document from Collection2, and I save everything with no errors. I also confirmed everything is been properly saved (collection1 has list of items and each item an _id reference to collection2). The only problem is populating collection2 inside this array.
I have already tried restructuring everything with _ids (including itemScheme) and dropping all collections to test it again but no success.
I have been stuck with this problem for about three days now.
Is there any special property I should be setting for populate to make it work for this specific structure?
Thanks in advance...
populate('items')
This will not work as item is not a model.
What you want is following:
Collection1.find()
.populate('items.collection2')
.then(...)
.catch(...);
This will populate collection2 in all the array elements

Is property `ref` necessary when schema field type is `ObjectId` in Mongoose?

I have a sample mongoose schema like below:
new Schema(
{
title: {
type: String,
},
digest: {
type: String,
},
owner: {
type: ObjectId,
ref: 'User'
}
}
)
I wonder to know that is property ref necessary when the field type is ObjectId like owner field.
No, not necessary, but if you have it, you'll be able to easily load the referenced entities. http://mongoosejs.com/docs/populate.html
Kitten.findOne().populate('owner').exec(function (err, kitten) {
console.log(kitten.owner.name) // Max
})
Without ref, it'll just be an ordinary field that contains ObjectId.

Mongoose, populate where an ID is specific to a project reference

I m trying to populate a mongoose model where I only want the returned items to be the ones that are matched with an ID.
Edit update: In the User model below, I need to first find the correct user by id, then for the task property, I need to populate it where the projectID matches req.params.ID. How can I only populate the tasks where the projectID matches the req.params.ID. I have included my full User model as well as the Task model
//User Schema
var UserSchema = new Schema({
name: {
type: String,
trim: true,
required: "First Name is Required"
},
username: {
type: String,
trim: true,
required: "Username is Required"
},
skills: {
type: String,
trim : true
},
avatar: {
type: String
},
SQLid: {
type: Number
},
userCreated: {
type: Date,
default: Date.now
},
lastUpdated: {
type: Date
},
adminTeams: [{
type: Schema.Types.ObjectId,
ref: "Team"
}],
team: [{
type: Schema.Types.ObjectId,
ref: "Team"
}],
task: [{
projectID: {
type: String
},
theTask: {
type: Schema.Types.ObjectId,
ref: "Task"
}
}]
});
//Task Schema
var TodoSchema = new Schema({
task: {
type: String
}
});
How can I only get the task populated where the projectID is equal to a specific ID. I tried
User.findById({ "_id": req.params.id }).populate({ path: 'task', match: {projectID: req.params.pID}, select: 'theTask' })
.exec(function(err, docs){
console.log("POPULATE TASKS DOCS", docs)
But this is showing that the docs is empty.
you can use $elemMatch ,it will give you all those docs which matches your projectId and populate your task document .
So the query would be -
var query={
task:{
$elemMatch:{
projectId: req.params.id
}
}
}
User.find(query)
.populate('theTask')
.select('theTask') // use for getting selective data from document
.exec(function(){}) //your callback fuction
Hope I answer your question.
Thanks.
In your task schma you have kept the type of the task type as string and in your user schema the theTask have the refrence of the task and task its Self is just a string . Thats why it is not being populated ..
So change the task schema to (Keep it simple)-
var Task= new Schema({
name :string
});
Populate need refrence Id to get the whole document

how does the populate method works in mongoose?

I have the following schemas defined:
module.exports.contact=Schema({
_id:Number,
name: String,
email: String,
contactNumber: String,
company:String,
_invoices:[{ type: Schema.Types.ObjectId, ref: 'invoice' }],
},{strict:false});
module.exports.invoice=Schema({
_contact: { type : Number, ref: 'contact'},
_id:Number,
invoiceNumber:Number,
},{strict:false});
And following data is inserted in mongodb:
//CONTACT COLLECTION
{_id:1,name:"Mrinal Purohit",email:"mrinal#mrinalpurohit.com",contactNumber:"+919016398554",company:""}
//INVOICE COLLECTION
{ _id:1, invoiceNumber:3 , _contact:1 }
Only one document is there in the respective collections. Now i attempt this:
models.contact.find().populate('_invoices').exec(function(err,data){
console.log(data);
res.send(data)
});
I get the following:
[ { _id: 1,
name: 'Mrinal Purohit',
email: 'mrinal#mrinallabs.com',
contactNumber: '+919016398554',
company: '',
__v: 0,
_invoices: [] } ]
I actually expected the invoices to be populated in the array. Is there something wrong with the schema definition?
I am unable to completely understand the .populate function of mongoose :(
Your _id type is mismatched
In your invoice schema _id is defined as a Number. However in your definition of _invoices in the contact schema, you've selected the Schema.Types.ObjectId type
Try changing the type of _invoices to Number, e.g.
module.exports.contact=Schema({
_id:Number,
name: String,
email: String,
contactNumber: String,
company:String,
_invoices:[{ type: Number, ref: 'invoice' }],
},{strict:false});
Alternatively, you can let Mongoose set _id for you by omitting the _id property in your schemas (so you can leave _invoices unchanged). It would save you a bit of work in generating unique IDs and it also has a bunch of other useful properties (like the embedded timestamp)
Update
damphat is also correct in pointing out the other error (which I missed). According to the data you're inserting, you've haven't pushed the _id of your new invoice into the relevant contact document
Here's a sketch of how to create an invoice while properly updating the relevant contact
Invoice.create(invoiceAttributes, function (err, invoice) {
if (err) // Handle your error
Contact.findOne({ _id: invoiceAttributes._contact}, function (err, contact) {
if (err) // Handle your error
contact._invoices.push(invoice._id); // The important step you were missing
contact.save(); // Insert your callback
});
});
Just add 1 line _invoices: [1] to the contact document:
{
_id: 1,
name: "Mrinal Purohit",
email: "mrinal#mrinalpurohit.com",
contactNumber: "+919016398554",
company: "",
_invoices: [1]
}
and correct the typo in your contact schema as well.

MongoDB cast error in _id

I am using mongoose.
My schema is like
var tblTypes = new Schema({
_id: { type: String, required: true }
, desc: String
, priority: Number
}, { collection: 'tblTypes' });
while fetching records in the query i am giving like dis as query in findone
JSON
{ _id: "SFK" }
Its giving
{ message: 'Cast to ObjectId failed for value "CONFIRM" at path "_id"',
name: 'CastError',
type: 'ObjectId',
value: 'CONFIRM',
path: '_id' }
as error. Earlier its working in different system.
I am not sure about both the versions.
Where i am going wrong ?

Resources