jigarzon
jigarzon

Reputation: 1228

MongoDB Many to Many lookup

I have following situation.

Offer {
id,
name
}

OfferCategory {
 offerId,
 categoryId
}

Category {
id,
name
}

I want to retrieve al Offers with their Categories including the name in the same query (before that, I filter using a geoNear step). I have this but its bringing an empty categoriesObj array. I think that the localField of the last $lookup operation is not correct:

db.Offer.aggregate([
{
    $geoNear: {
        near: { type: "Point", coordinates: [ -58, -34 ] },
        distanceField: "dist.calculated",
        maxDistance: 200,
        spherical: true
    }
},
{
    $lookup: {
                from: "OfferCategory",
                localField: "_id",
                foreignField: "offerId",
                as: "categories"
    }
},
{
    $lookup: {
                from: "Category",
                localField: "categories._id",
                foreignField: "_id",
                as: "categoriesObjs"
    }
},
]);

Upvotes: 0

Views: 1223

Answers (2)

jigarzon
jigarzon

Reputation: 1228

Thanks @Ashok for your help, this resolves the Many to Many relationship. I added an unwind and project steps to the pipeline and its working


db.Offer.aggregate([
  { $geoNear: {
      near: { type: "Point", coordinates:  [ -58.475332, -34.527155 ]},
      distanceField: "dist.calculated",
      maxDistance: 200000,
      spherical: true
  }},
  { $lookup: {
      from: "OfferCategory",
      let: { offerId: "$_id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$$offerId", "$offerId"] } } },
        { $lookup: {
            from: "Category",
            let: { categoryId: "$categoryId" },
            pipeline: [{ $match: { $expr: { $eq: ["$$categoryId", "$_id"] } } }],
            as: "categories"
        }},
         { $unwind: "$categories" },
        { $project : { name:'$categories.name' }}
      ],
      as: "categories"
    }
  }

]);

Upvotes: 0

Ashok
Ashok

Reputation: 2932

You can use this aggregation with mongoDB version ^3.6

db.offers.aggregate([
  { $geoNear: {
      near: { type: "Point", coordinates: [ -58, -34 ] },
      distanceField: "dist.calculated",
      maxDistance: 200,
      spherical: true
  }},
  { $lookup: {
      from: "offerCategory",
      let: { offerId: "$_id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$$offerId", "$offerId"] } } },
        { $lookup: {
            from: "Category",
            let: { categoryId: "$categoryId" },
            pipeline: [{ $match: { $expr: { $eq: ["$$categoryId", "$id"] } } }],
            as: "cateogries"
        }}
      ],
      as: "offerCategories"
    }
  }
]);

Upvotes: 1

Related Questions