【问题标题】:Lookup stage not working after unwind operation in aggregate pipeline in mongodb在mongodb的聚合管道中展开操作后查找阶段不起作用
【发布时间】:2020-06-28 16:06:18
【问题描述】:

在 mongodb 中相对较新,我用这三个表执行了一个聚合管道,令人惊讶的是,在管道的第三个查找阶段我得到 “r2”数组为空。我交叉检查了字段名称一切都很好。

db.user.aggregate([
{
    $lookup:{
            from:"enrollment",
            localField:"user_id",
            foreignField:"userID",
            as:"r1"
        }
},

{
    $unwind:{
            path:"$r1",
            includeArrayIndex:"r1_id"
        }
},
{
    $lookup:{
            from:"course",
            localField:"r1.courseID",
            foreignField:"courseID",
            as:"r2"
        }
}
])

我有三个集合,分别是 user 、enrollment 和 course

用户身份

> db.user.find()
{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2ca"), "user_id" : 1, "first_name" : "Christian", 
"last_name" : "Hur", "email" : "christian@uta.com", "password" : "abc1234" }
{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2cb"), "user_id" : 2, "first_name" : "Mary", "last_name" : 
"Jane", "email" : "mary.jane@uta.com", "password" : "password123" }
{ "_id" : ObjectId("5ef4bc2563742adee5403b1d"), "user_id" : 3, "first_name" : "ari", "last_name" : 
"dutta", "email" : "dutta@uta.com", "password" : "po1234" }

而且,当然是

> db.course.find()
{ "_id" : ObjectId("5ef4c1b64a77aec0af5e73ae"), "courseID" : 3333, "title" : "Adv PHP 201", 
"description" : "Advance PHP programming", "credits" : 3, "term" : "fall" }
{ "_id" : ObjectId("5ef4c20d4a77aec0af5e73af"), "courseID" : 5555, "title" : "Java 201", 
"description" : "Advanced Programming", "credits" : 4, "term" : "fall"}
{ "_id" : ObjectId("5ef4c2564a77aec0af5e73b0"), "courseID" : 6666, "title" : "Angular 1", 
"description" : "Intro to Angular", "credits" : 3, "term" : "fall,spring" }

和注册为

> db.enrollment.find()
{ "_id" : ObjectId("5ef771f42d98ffab4460a651"), "userID" : 1, "courseID" : "3333" }
{ "_id" : ObjectId("5ef7722d2d98ffab4460a652"), "userID" : 1, "courseID" : "6666" }

结果

{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2ca"), "user_id" : 1, "first_name" : 
"Christian", "last_name" : "Hur", "email" : "christian@uta.com", "password" : 
"abc1234", "r1" : { "_id" : ObjectId("5ef771f42d98ffab4460a651"), "userID" : 
1, "courseID" : "3333" }, "r1_id" : NumberLong(0), "r2" : [ ] }

{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2ca"), "user_id" : 1, "first_name" : 
"Christian", "last_name" : "Hur", "email" : "christian@uta.com", "password" : 
"abc1234", "r1" : { "_id" : ObjectId("5ef7722d2d98ffab4460a652"), "userID" : 
1, "courseID" : "6666" }, "r1_id" : NumberLong(1), "r2" : [ ] }

我也检查了文档,但没有找到帮助,我该如何解决这个问题?

【问题讨论】:

    标签: mongodb flask


    【解决方案1】:

    您在集合之间的 courseID 上存在类型不匹配,enrollment 中的类型为 stringcourse 中的类型为 number

    将您的 $lookup 更改为:

      {
        $lookup: {
          from: "course",
          let: {
            courseID: {
              $toInt: "$r1.courseID"
            }
          },
          pipeline: [
            {
              $match: {
                $expr: {
                  $eq: [
                    "$$courseID",
                    "$courseID"
                  ]
                }
              }
            }
          ],
          as: "r2"
        }
      }
    

    自己试试吧: Mongo Playground

    另外,既然你说你是新人,我个人建议你使用 _id 字段而不是你自己生成的 courseID/user_id。它只会让维护变得更容易。

    对于 Mongo 4.2+ 版本,这里是更新注册集合字段的方法:

    db.enrollment.updateMany(
        {},
        [
            {
                $set: {
                    courseID: {$toInt: "$courseID"}
                }
            }
        ]
    )
    

    【讨论】:

    • 好吧,在你指出之后,我才发现字符串和数字之间的不匹配。但是有什么方法可以在不干扰其他值的情况下将“注册”集合中的所有值更新为数字?
    • 我添加了关于如何更新整个集合的代码。此语法仅适用于 4.2+ 版本。如果您使用的是较低的 mongo 版本,则必须遍历每个文档并单独更新。
    猜你喜欢
    • 2018-12-11
    • 1970-01-01
    • 2020-04-13
    • 2021-01-22
    • 2021-07-13
    • 2020-06-08
    • 2020-08-20
    • 2021-04-21
    • 2021-01-13
    相关资源
    最近更新 更多