$lookup 与深度嵌套的对象

Posted

技术标签:

【中文标题】$lookup 与深度嵌套的对象【英文标题】:$lookup with deeply nested object 【发布时间】:2018-11-30 23:29:12 【问题描述】:

我是 MongoDB 的新手,目前正在为学校开发一款建议饮食计划的食谱应用程序。因此,我需要将用户饮食计划(集合“用户”)中的“膳食”ObjectId 与集合“膳食”中的 ObjectId 结合起来。

之后,我需要在“Meals”集合中加入一个“ingredient”ObjectID,并在“Ingredients”集合中加入“ingredient”的ID。问题是,集合“Meals”中的“成分”ObjectID 位于具有另一个整数变量“amount”的对象中。该对象嵌套在一个名为“ingredients”的数组中,其中包含许多对象,例如刚刚描述的对象。

下面是我的结构:

用户


 "_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 Array)

    
        $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

非常感谢!

【问题讨论】:

你的mongodb版本是多少? 【参考方案1】:

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" 
])

【讨论】:

如果您能解决这样的相关问题,请提供帮助:***.com/questions/61109179/… @newdeveloper 当然我会做......这是晚上会在早上做 提前致谢!

以上是关于$lookup 与深度嵌套的对象的主要内容,如果未能解决你的问题,请参考以下文章

MongoDb:使用 $lookup 查找深度嵌套的对象

Ramda js:具有嵌套对象数组的深度嵌套对象的镜头

React:使用 Hooks 为深度嵌套对象设置状态

Mongoose - 查询深度嵌套的对象

打字稿:嵌套对象的深度键

对象数组 深度复制,支持对象嵌套数组数组嵌套对象