【问题标题】:how to push data into array mongodb如何将数据推送到数组mongodb
【发布时间】:2020-06-19 03:06:20
【问题描述】:

使用三个集合查找重新管理数据。我很困惑该使用哪个。请指导一下

db.post.aggregate([
  {
    $lookup: {
      from: "users",
      localField: "created_by",
      foreignField: "_id",
      as: "created_users"
    }
  },
  {
    $lookup: {
      from: "comments",
      let: {
        p_id: "$_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$post_id",
                "$$p_id"
              ]
            }
          }
        }
      ],
      as: "comments"
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "comments.sender_id",
      foreignField: "_id",
      as: "commented_user"
    }
  }
])

我们想得到三个收藏帖子,用户和cmet,谁对帖子有评论,评论的用户应该在这样的cmet下

[
  {
    "_id": ObjectId("5eeb02881982961ada625c7d"),
    "commented_user": [
      {
        "_id": ObjectId("5e4d0973babf2b74ca868f4d"),
        "first_name": "James",
        "last_name": "Smith",
        "timestamp": 1.582106995137e+12
      },
      {
        "_id": ObjectId("5e4d0973babf2b74ca868f6d"),
        "first_name": "Alex",
        "last_name": "Jimy",
        "timestamp": 1.582106995139e+12
      }
    ],
    "comments": [
      {
        "_id": ObjectId("5eeb08e26fb7f270e4077617"),
        "date": 1.592461538924e+12,
        "post_id": ObjectId("5eeb02881982961ada625c7d"),
        "sender_id": ObjectId("5e4d0973babf2b74ca868f4d"),
        "text": "Nice ",
        "commented_user": {
            "_id": ObjectId("5e4d0973babf2b74ca868f4d"),
            "first_name": "James",
            "last_name": "Smith",
            "timestamp": 1.582106995137e+12
        },
      },
      {
        "_id": ObjectId("5eeb08e26fb7f270e4077618"),
        "date": 1.592461538923e+12,
        "post_id": ObjectId("5eeb02881982961ada625c7d"),
        "sender_id": ObjectId("5e4d0973babf2b74ca868f6d"),
        "text": "Nice One",
        "commented_user": {
            "_id": ObjectId("5e4d0973babf2b74ca868f6d"),
            "first_name": "Alex",
            "last_name": "Jimy",
            "timestamp": 1.582106995137e+12
        },
      }
    ],
    "created_by": ObjectId("5e4e74eb380054797d9db623"),
    "created_users": [],
    "date": 1.589441206774e+12,
    "title": "Covid19"
  }
]

这是我的尝试https://mongoplayground.net/p/UwRjj-er0K5

请帮忙解决一下,谢谢

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    你可以这样做:

    策略是$unwinding 结果,因此我们可以匹配每个评论,然后重建以前的结构。

    db.post.aggregate([
     {
       $lookup: {
         from: "users",
         localField: "created_by",
         foreignField: "_id",
         as: "created_users"
       }
     },
     {
       $lookup: {
         from: "comments",
         let: {
           p_id: "$_id"
         },
         pipeline: [
           {
             $match: {
               $expr: {
                 $eq: [
                   "$post_id",
                   "$$p_id"
                 ]
               }
             }
           }
         ],
         as: "comments"
       }
     },
     {
       $unwind: "$comments"
     },
     {
       $lookup: {
         from: "users",
         localField: "comments.sender_id",
         foreignField: "_id",
         as: "commented_user"
       }
     },
     {
       $unwind: "$commented_user"
     },
     {
       $addFields: {
         comments: {
           $mergeObjects: [
             "$comments",
             {
               commented_user: "$commented_user"
             }
           ]
         }
       }
     },
     {
       $group: {
         _id: "$_id",
         comments: {
           $push: "$comments"
         },
         created_by: {
           $first: "$created_by"
         },
         created_users: {
           $first: "$created_users"
         },
         date: {
           $first: "$date"
         },
         title: {
           $first: "$title"
         },
    
       }
     }
    ])
    

    Mongo Playground

    【讨论】:

    • 我们可以不使用 $group 或使用 $project 吗?如果请帮助不同的游乐场
    • 需要 $group 才能将 cmets 结构恢复为数组,但如果您不介意将其展开,您可以将其替换为 project yes。
    • 为什么会失败? mongoplayground.net/p/aKVO0Eo4bbX
    • 因为如果你不分组,那么$comments 不是一个数组:mongoplayground.net/p/8FTIbHv7fmQ
    • 是的,看看这里:mongoplayground.net/p/OA1s79voayX。我没有展开 cmets,而是选择了最后一个。 (这假设它在集合中按日期排序)
    【解决方案2】:

    从您尝试的代码开始,您可以将第二个 $lookup 移动到第一个 $lookup 的管道中,然后 $unwind

    db.post.aggregate([
      {
        $lookup: {
          from: "users",
          localField: "created_by",
          foreignField: "_id",
          as: "created_users"
        }
      },
      {
        $lookup: {
          from: "comments",
          let: { p_id: "$_id" },
          pipeline: [
            {
              $match: {
                $expr: { $eq: ["$post_id", "$$p_id"] }
              }
            },
            { // second level $lookup
              $lookup: {
                from: "users",
                localField: "sender_id",
                foreignField: "_id",
                as: "commented_user"
              }
            },
            { // $unwind to get single object instead of array
              $unwind: "$commented_user"
            }
          ],
          as: "comments"
        }
      },
    ])
    

    Mongo Playground

    OP 提示:有discussion 来获取最新评论。使用这种方法,您可以在最外面的$lookup 中使用$sort$limit

    db.post.aggregate([
      {
        $lookup: {
          from: "users",
          localField: "created_by",
          foreignField: "_id",
          as: "created_users"
        }
      },
      {
        $lookup: {
          from: "comments",
          let: { p_id: "$_id" },
          pipeline: [
            {
              $match: {
                $expr: { $eq: ["$post_id", "$$p_id"] }
              }
            },
            {
              $sort: { date: -1 } // or { _id: -1 }
            },
            {
              $limit: 1 // limit to only one element
            },
            {
              $lookup: {
                from: "users",
                localField: "sender_id",
                foreignField: "_id",
                as: "commented_user"
              }
            },
            {
              $unwind: "$commented_user"
            }
          ],
          as: "comments"
        }
      },
      { // // $unwind to get single object instead of array
        $unwind: "$comments"
      }
    ])
    

    Mongo Playground

    【讨论】:

    • 真棒@thammada 非常感谢您的解释。你的回答真的很有用。
    猜你喜欢
    • 2017-09-19
    • 2018-02-08
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2019-04-30
    • 2017-03-16
    相关资源
    最近更新 更多