根据学生 ID 聚合多个集合

Posted

技术标签:

【中文标题】根据学生 ID 聚合多个集合【英文标题】:Aggregate multiple collections based on student 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 你能粘贴给定输入的预期输出吗? 【参考方案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

以上是关于根据学生 ID 聚合多个集合的主要内容,如果未能解决你的问题,请参考以下文章

从聚合管道中的集合中减去子文档

链式查找聚合 mongoDB 多个集合

是否可以在 mongodb 上聚合多个条件

Mongodb聚合计数数组/集合大小

使用 MongoDB 聚合将集合合并到固定大小

如何使用带有_id数组的动态集合的聚合来获取数据