【问题标题】:Aggregate multiple collections based on student Id根据学生 ID 聚合多个集合
【发布时间】:2019-04-24 06:49:48
【问题描述】:

我正在尝试根据学生 ID 在 MongoDB 中聚合 2 个集合。一个集合包含学生个人信息,另一个集合包含学生日志。问题是数据在数组中,这就是我认为我的聚合不起作用的原因。任何帮助将不胜感激。

学生收藏

{
    "_id" : ObjectId("(Object ID here"),
    "data" : [ 
        {
            "name" : "John",
            "id" : 1
        }, 
        {
            "name" : "Sandy",
            "id" : 2
        }
    ]
}

日志收集

{
    "_id" : ObjectId("(Object ID here"),
    "logs" : [ 
        {
            "studentId" : 1,
            "activity" : "11112,334,123"
        }, 
        {
            "studentId" : 2,
            "activity" : "11112,334,123"
        }
    ]
}

这是我尝试过的:

dbo.collection("student").aggregate([
    { "$lookup": {
        "localField": "data.id",
        "from": "logs",
        "foreignField": "logs.studentId",
        "as": "studentInfo"
    }
    }]).toArray(function(err, results) {
        console.log(results);
    });

预期结果:

studentinfo: {
    id: 1,
    name: "John",
    activity" : "11112,334,123"
}

【问题讨论】:

  • 你使用的是什么版本的mongodb?你想要什么输出?
  • 有什么理由这样存储数据?通常每个学生都是自己的文件
  • @AnthonyWinzlet 我想获得学生日志和个人信息的联合结果
  • @Bajal true 但这是一个更大的应用程序的一部分,学生目前没有那么多信息
  • @HeelMega 你能粘贴给定输入的预期输出吗?

标签: arrays mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

您可以在 mongodb 3.6

中使用以下聚合

所以基本上你的外部字段是一个数组,你需要将$lookup与管道一起使用到$unwind$lookup管道内的外部数组并匹配相应的ids

db.students.aggregate([
  { "$lookup": {
    "from": "logs",
    "let": { "dataId": "$data.id" },
    "pipeline": [
      { "$unwind": "$logs" },
      { "$match": { "$expr": { "$in": ["$logs.studentId", "$$dataId"] }}},
      { "$replaceRoot": { "newRoot": "$logs" }}
    ],
    "as": "students"
  }}
])

或者使用它来合并两个数组

db.students.aggregate([
  { "$lookup": {
    "from": "logs",
    "let": { "dataId": "$data.id" },
    "pipeline": [
      { "$unwind": "$logs" },
      { "$match": { "$expr": { "$in": ["$logs.studentId", "$$dataId"] }}},
      { "$replaceRoot": { "newRoot": "$logs" }}
    ],
    "as": "students"
  }},
  { "$project": {
    "students": {
      "$map": {
        "input": "$students",
        "in": {
          "studentId": "$$this.studentId",
          "activity": "$$this.activity",
          "name": { "$arrayElemAt": ["$data.name", { "$indexOfArray": ["$data.id", "$$this.studentId"] }]}
        }
      }
    }
  }}
])

输出

[
  {
    "students": [
      {
        "activity": "11112,334,123",
        "name": "John",
        "studentId": 1
      },
      {
        "activity": "11112,334,123",
        "name": "Sandy",
        "studentId": 2
      }
    ]
  }
]

【讨论】:

  • 第一个查询中的dataId来自哪里?
  • dataId 是我们在let 表达式中取的变量。哪个是你的localField
猜你喜欢
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 2021-09-13
  • 1970-01-01
  • 2020-04-25
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多