'Mongoose: Populate on existing DBRef
I am migrating a Spring project to Nextjs&co for personal enrichment. I have an existing mongodb database with school related collections such as:
// school (as json)
"_id" : ObjectId("5f457f041291df2910dea1ed"),
"name" : "San Lucas Primary School",
...
"campus" : DBRef("campus", ObjectId("5f457dd9126d210893e14e11"))
I've loaded up mongoose, and have tried to wrangle it for the last few days to get it to populate campus.
If I define the schema like so:
import mongoose from 'mongoose'
const SchoolSchema = new mongoose.Schema({
name: String,
campus: {type: mongoose.Schema.Types.ObjectId, ref: 'campus'},
});
module.exports = mongoose.model("School", SchoolSchema, 'school') // i define the existing collection name 'school' to avoid the built in pluralization
When I do school.find() in debugger, I get the mongoose model object. The campus field is missing, and there is an error: ValidatorError: Cannot read properties of undefined (reading 'options')\n at _init
When I alter the Schema to not include campus:
import mongoose from 'mongoose'
const SchoolSchema = new mongoose.Schema({
name: String,
// campus: {type: mongoose.Schema.Types.ObjectId, ref: 'campus'},
});
module.exports = mongoose.model("School", SchoolSchema, 'school')
The debugger now spits out the whole object, including campus but it looks like this:
campus = DBRef {collection: "campus", oid: ObjectId, db: undefined, fields: Object}
There was another configuration where it was spitting it out as if it were creating the object at runtime, new DBref("campus", new ObjectId("...")) or something like that.
When I json it out, it always ends up {$ref: 'campus', $id: ...}. But if I do not include it in the schema, I can't do all that handy populate and things.
I'm this far from extracting the id as a string and doing findById().
Folks, I am STUMPED.
Solution 1:[1]
DBRef is a rather controversial convention of data format coming from early versions (doc for v2.2) long before $lookup was added in v3.2. The main reason was to allow cross-database references between documents, yet even then it was not recommended except very niche usecases:
In most cases you should use the manual reference method for connecting two or more related documents. However, if you need to reference documents from multiple collections, consider using DBRefs.
It is not supported by all drivers, caused many problems with export/import because regular field names could not start with $ as recently as in v4.4 https://www.mongodb.com/docs/v4.4/reference/limits/#mongodb-limit-Restrictions-on-Field-Names
Mongoose on the other hand, is quite opinionated ODM which comes with it's own conventions. Automatic opted out from DBRefs in favour of their own Population logic, which is so much incompatible with DBRefs, that they even stopped calling it "DBRef-like" starting from v3.0.
There was an attempt to add support of native DBRefs to mongoose, but the project looks abandoned. You may find it useful to read this explaination: DbRef with Mongoose - mongoose-dbref or populate?
Anyway, apart from DBRefs you will likely face other issues related to mongoose vs spring conventions of document structure. Off the top of my head it's mongoose optimistic locking, which relies on the value of _v field, otherwise not exposed on the application level, etc.
If you intend to use the same database in a heterogeneous setup you can't really use anything but native drivers, as all ODMs come with own conventions and it is very likely they won't match.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alex Blex |
