Setup
Let's say we have schemas for Foo
and Bar
. Foo
has a field bar
. This field can either contain an ObjectId that reference a document Bar
, or it could contain other arbitrary objects that are not ObjectIds.
const fooSchema = new mongoose.Schema({
bar: {
type: mongoose.Schema.Types.Mixed,
ref: 'Bar'
}
});
const Foo = <any>mongoose.model<any>('Foo', fooSchema);
const barSchema = new mongoose.Schema({
name: String
});
const Bar = <any>mongoose.model<any>('Bar', barSchema);
Problem
Now suppose we have a bunch of Foo
documents.
I would like to be able to use mongoose's populate
on the bar
field to automatically replace references to a Bar
document with the actual Bar
document itself. I would also like to leave all other objects that are not references to a Bar
document unchanged.
Normally, I would use something like this to get all the Foo
documents and then populate the bar
field:
Foo.find().populate('bar')
However, this method will throw an exception when it encounters objects in the bar
field that are not ObjectIds, as opposed to leaving them untouched.
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): CastError: Cast to ObjectId failed for value "Some arbitrary object" at path "_id" for model "Bar"
Attempt at finding a solution
I have examined using the match
option on populate
, by requiring that a field on Bar
exists:
Foo.find().populate({
path: 'bar',
match: {
name: {
$exists: true
}
}
}
Unfortunately, the error is the same.
Question
So my question is then, is there any way to get mongoose to only populate
a field if the field contains an ObjectId, and leave it alone otherwise?