按日期对来自多个集合的文档进行分组

Posted

技术标签:

【中文标题】按日期对来自多个集合的文档进行分组【英文标题】:Group documents from multiple collections by date 【发布时间】:2021-12-17 09:09:49 【问题描述】:

我有 3 个具有基本结构的架构

meal: 
    user: 'objectID',  
    createdAt: 'date


activity: 
    user: 'objectID',
    createdAt: 'date'



role: 
    user: 'objectID',
    createdAt: 'date'
  

我想从属于用户的每个模式中获取所有文档,并按日期对它们进行分组。例如,

history: [
    
        date: 01-11-2021,
        meal: [
            ...array of meal documents on 01-11-2021
        ],
        activity: [
            ...array of meal documents on 01-11-2021
        ],
        role: [
            ...array of meal documents on 01-11-2021
        ],
    ,
    ...next date
]

【问题讨论】:

如果您可以提供有效的 JSON 样本数据和 JSON 格式的预期输出。例如 3 个数组似乎有相同的膳食数据 是否有第四个集合名为history?您可能希望按照@Takis_ 的明智建议向我们提供完整的示例数据集 【参考方案1】:

数据

db=
  "user": [
    
      "_id": 1,
      "name": "Sam"
    
  ],
  "meal": [
    
      "user": 1,
      "content": "apple",
      "createdAt": ISODate("2021-09-01T11:23:25.184Z")
    ,
    
      "user": 1,
      "content": "orange",
      "createdAt": ISODate("2021-09-01T11:23:25.184Z")
    ,
    
      "user": 1,
      "content": "pie",
      "createdAt": ISODate("2021-09-02T11:23:25.184Z")
    
  ],
  "activity": [
    
      "user": 1,
      "content": "baseball",
      "createdAt": ISODate("2021-09-01T11:23:25.184Z")
    
  ],
  "role": [
    
      "user": 1,
      "content": "admin",
      "createdAt": ISODate("2021-09-01T11:23:25.184Z")
    
  ]

聚合

db.user.aggregate([
  
    "$match": 
      _id: 1
    
  ,
  
    "$lookup": 
      "from": "meal",
      "localField": "_id",
      "foreignField": "user",
      "pipeline": [
        
          "$set": 
            "from": "meal"
          
        
      ],
      "as": "meal_docs"
    
  ,
  
    "$lookup": 
      "from": "activity",
      "localField": "_id",
      "foreignField": "user",
      "pipeline": [
        
          "$set": 
            "from": "activity"
          
        
      ],
      "as": "activity_docs"
    
  ,
  
    "$lookup": 
      "from": "role",
      "localField": "_id",
      "foreignField": "user",
      "pipeline": [
        
          "$set": 
            "from": "role"
          
        
      ],
      "as": "role_docs"
    
  ,
  
    $project: 
      user: "$name",
      items: 
        $concatArrays: [
          "$activity_docs",
          "$meal_docs",
          "$role_docs"
        ]
      
    
  ,
  
    "$unwind": "$items"
  ,
  
    $project: 
      createdAt: 
        $dateTrunc: 
          "date": "$items.createdAt",
          "unit": "day"
        
      ,
      content: "$items.content",
      from: "$items.from"
    
  ,
  
    "$group": 
      "_id": 
        "createdAt": "$createdAt",
        "from": "$from"
      ,
      "list": 
        "$push": "$$ROOT.content"
      
    
  ,
  
    "$group": 
      "_id": "$_id.createdAt",
      "documents": 
        "$push": 
          k: "$$ROOT._id.from",
          v: "$$ROOT.list"
        
      
    
  ,
  
    "$project": 
      documents: 
        $arrayToObject: "$documents"
      
    
  ,
  
    "$group": 
      "_id": 1,
      "history": 
        "$push": 
          date: "$$ROOT._id",
          activity: "$$ROOT.documents.activity",
          meal: "$$ROOT.documents.meal",
          role: "$$ROOT.documents.role"
        
      
    
  
])

mongoplayground

【讨论】:

我没看懂这个问题,但是投了赞成票,你创建了所有这些数据,并做了一个复杂的查询,希望这是她/他需要的。 @Takis_ 感谢您的支持。我也很欣赏你和@ray 经常提供有用的 cmets 和好的答案。我从中学到了很多。我也希望我的回答是@unhackit 需要的。有时我会自己为问题创建一个场景,以猜测提问者可能想要什么。 哇! @YuTing 在大多数情况下效果很好!我真的很想了解更多关于聚合的信息,mongo 文档对我来说有点复杂。我在哪里可以看?

以上是关于按日期对来自多个集合的文档进行分组的主要内容,如果未能解决你的问题,请参考以下文章

如何根据从 objectId 中提取的创建日期对 MongoDB 集合进行分组?

如何根据从 objectId 中提取的创建日期对 MongoDB 集合进行分组?

如何按创建日期而不是名称对 Cloud Firestore 集合中的文档进行排序?

猫鼬日期比较没有时间和按多个属性分组?

在Kotlin中按多个字段对集合进行排序[重复]

C# - LINQ - 按日期范围分组集合