In Mongoose, there's a great and useful feature called Population, which makes it possible to dynamically connect a field to another document from another collection.
Let's say, in sales document you have costumer field. Costumer might be a person or a company. And you want to keep costumer in one field. No problem. You can create a schema like the one below.
costumer: { type: ObjectId, refPath: "costumerType" }, costumerType: { type: String, enum: ["people", "companies"] }
Then, when you need to get this sales document, you can "populate" costumer field like below.
await sales.find({}).populate("costumer")
Mongoose will bring you the costumer, whether person or company.
Very useful.
Switching to Aggregation API
If you're building much bigger app, there might be a need for complex database queries. MongoDB have a great query API called Aggregation API.
At the point that you're working with Aggregation API, you may encounter the limitation that aggregation doesn't directly support dynamic lookups — lookup ($lookup) is an operator for bringing documents from other collections in same database.
Nevertheless, nothing is impossible.
I created a trick to make dynamic lookups possible by the following method.
await sales.aggregate([ // Lookup for people and get result into "_temporaryPeople" { $lookup: { from: "people", localField: "costumer", foreignField: "_id", as: "_temporaryPeople", }}, // Lookup for companies and get result into "_temporaryCompanies" { $lookup: { from: "companies", localField: "costumer", foreignField: "_id", as: "_temporaryCompanies", }}, // Set "costumer" field with merge of two variables. // This will set "costumer" the wanted document. { $set: { costumer: { $mergeObjects: [ { $first: "$_temporaryPeople" }, { $first: "$_temporaryCompanies" }, ] } }}, // After we're done, we can destroy temporary fields. { $unset: ["_temporaryPeople", "_temporaryCompanies"] }, ])
Until MongoDB adds dynamic lookup to the Aggregation API,
I think this is the easiest way to handle this issue.
Stay with MongoDB 🏄♂️
Top comments (0)