$ lookup与深度嵌套的对象

时间:2018-06-21 15:03:53

标签: javascript arrays mongodb lookup aggregation

我是MongoDB的新手,目前正在为学校设计食谱应用程序,以建议饮食计划。因此,我需要将用户(集合“ Users”)的饮食计划中的“膳食” ObjectId与集合“ Meals”中的ObjectId进行关联。

然后,我需要将“ Meals”集合中的“成分” ObjectID与“成分”集合中的“成分” ID结合起来。问题是,集合“ Meals”中的“成分” ObjectID位于具有另一个整数变量“ amount”的对象中。该对象嵌套在称为“成分”的数组中,其中包含许多对象,例如刚刚描述的对象。

下面是我的结构:

用户

{
 "_id": ObjectId("5b28cab902f28e18b863bd36"),
 "username: "testUser1",
 "password": "$2a$08$KjddpaSQPjp6aF/gseOhVeddYdqWJCJ4DpFwxfNgsk81G.0TOtN5i",
 "dietPlans": Object
    {
     "dietPlanCurrent":Object
         {
          "monday":Object
               {
               "breakfast":Object
                    {
                     "meal": ObjectId("5b2b9a8bbda339352cc39ec4")
                 },
                 … 
           },
           … 
     },
     …
  },
}

用餐

{
   "_id" : ObjectId("5b2b9a8bbda339352cc39ec4"),
   "name": "Gulasch-breakfast",
   "cuisine": "International",
   "ingredients":[
       {
            "ingredient": ObjectId("5b1ec0f939b55efcd4e28a2d"),
            "amount": 20
       },
       {
            "ingredient": ObjectId("5b1ec42474fc1f58d84264d4"),
            "amount": 20
       },
       {
            "ingredient": ObjectId("5b1ec42474fc1f58d84264d5"),
            "amount": 20
       },
       …   
    ],

   "comments": [
        …
    ]
}

成分

{ 
    {
     "_id": ObjectId("5b1ec0f939b55efcd4e28a2d"),
     "name": "Walnut",
     "calories": 654
      … 
    }
    {
     "_id": ObjectId("5b1ec0f939b55efcd4e28a3d"),
     "name": "Apple",
     "calories": 123
     … 
    }
… 
}

我想要得到的是:

    {
 "_id": ObjectId("5b28cab902f28e18b863bd36"),
 "username: "testUser1",
 "password": "$2a$08$KjddpaSQPjp6aF/gseOhVeddYdqWJCJ4DpFwxfNgsk81G.0TOtN5i",
 "dietPlans": Object
    {
     "dietPlanCurrent":Object
         {
          "Monday":Object
               {
               "breakfast":Object
                    {
                     "meal": ObjectId("5b2b9a8bbda339352cc39ec4")
                     "matchedIngredients": [
                        {
                         "_id": ObjectId("5b1ec0f939b55efcd4e28a2d"),
                         "name": "Walnut",
                         "calories": 654
                         … 
                        }
                      … 
                      ]

                 },


                 … 
           },


           … 
     },
     …
  },
}

我的方法行不通(仅返回空的matchedIngredients数组)

    {
        $match: {
            '_id': mongoose.Types.ObjectId(req.params.userId)
        }
    },
    {
        $lookup:   {
            from: 'meals',
            localField: 'dietPlans.dietPlanCurrent.monday.breakfast.meal',
            foreignField: '_id',
            as: "dietPlans.dietPlanCurrent.monday.breakfast.mealObject"
        }              
    },
    {
        $unwind: {
            path: "$dietPlans.dietPlanCurrent.monday.breakfast.mealObject",
            preserveNullAndEmptyArrays: true
        }
    },
   {
        $unwind: {
               path: "$dietPlans.dietPlanCurrent.monday.breakfast.mealObject.ingredients",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        $lookup:   {
            from: 'ingredients',
            localField: 'dietPlans.dietPlanCurrent.monday.breakfast.mealObject.ingredients.ingredient',
            foreignField: '_id',
            as: "dietPlans.dietPlanCurrent.monday.breakfast.matchedIngredients"
        }              
    }

非常感谢您的帮助。我已经检查了这种方法,但是以某种方式不起作用:

Approach that didn't work for me

非常感谢您!

1 个答案:

答案 0 :(得分:0)

mongodb版本 3.4 无法实现您要执行的操作,但是如果升级到 3.6 ,则可以尝试以下聚合操作

db.collection.aggregate([
  { "$match": { "_id": mongoose.Types.ObjectId(req.params.userId) } },
  { "$lookup": {
    "from": Meals.collection.name,
    "let": { "meal_id": "$dietPlans.dietPlanCurrent.monday.breakfast.meal" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": [ "$_id", "$$meal_id" ] } } },
      { "$unwind": "$ingredients" },
      { "$lookup": {
        "from": Ingredients.collection.name,
        "let": { "ingredient_id": "$ingredients.ingredient" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": [ "$_id", "$$ingredient_id" ] } } }
        ],
        "as": "matchedIngredients"
      }},
      { "$unwind": "$ingredients.matchedIngredients" },
      { "$group": {
        "_id": "$_id",
        "name": { "$first":"$name" },
        "cuisine": { "$first":"$cuisine" },
        "ingredients": { "$push":"$ingredients" }
      }}
    ],
    "as": "dietPlans.dietPlanCurrent.monday.breakfast.mealObject"
  }},
  { "$unwind": "$dietPlans.dietPlanCurrent.monday.breakfast.mealObject" }
])