DEV Community

Cover image for Dynamic Lookup with MongoDB Aggregation API
Taner Tunçer
Taner Tunçer

Posted on

Dynamic Lookup with MongoDB Aggregation API

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"] }
Enter fullscreen mode Exit fullscreen mode

Then, when you need to get this sales document, you can "populate" costumer field like below.

await sales.find({}).populate("costumer")
Enter fullscreen mode Exit fullscreen mode

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"] },
])
Enter fullscreen mode Exit fullscreen mode

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)