Mongodb聚合对属于同一文档的多个值进行分组

Posted

技术标签:

【中文标题】Mongodb聚合对属于同一文档的多个值进行分组【英文标题】:Mongo DB aggregate grouping multiple values that belong to the same document 【发布时间】:2020-05-17 14:32:04 【问题描述】:

我有类似这样的文件


"_id": "5e3334cede31d9555e38dbee",
"time": 400,
"datetime": "2020-01-05T16:35:42.315Z",
"version": "2.0.30",
"hostname": "bvasilchik-lt.extron.com",
"testfile": "cards.txt",
"tests": 5,
"failures": 3,
"skips": 0,
"status": "Failed",
"__v": 0

我想创建一个结果,其中包含每个 testfile 名称使用次数最多的文档,所以如果前 10 个都是相同的 testfile 名称,我只想显示具有相同测试文件名的***文件。

我已经这样做了,但我还想包含另一个字段,该字段也显示与该分组匹配的测试数量,但我发现的唯一方法是添加 $first 或 $last 或 $max 或 $min对于测试字段,但这是不正确的,因为最高时间可能有不同数量的测试。

我也在匹配特定日期范围内的结果

const times = await Suite.aggregate([
    
        "$match": 
            datetime:  "$gte": dateRange.startDate, "$lt": dateRange.endDate, 
        
    ,
    
        "$group": 
            _id: "$testfile",
            time:  "$max" : "$time" ,
        
    ,
    
        "$sort": 
            time: order
        
    ,
    
        "$project": 
            _id: 0,
            testfile: "$_id",
            time: "$time"
        
    
])

这会产生这些结果

[
    
    "testfile": "lists.txt",
    "time": 900
    ,
    
    "testfile": "buttons.txt",
    "time": 800
    ,
    
    "testfile": "cards.txt",
    "time": 400
    ,
    
    "testfile": "popover.txt",
    "time": 300
    ,
    
    "testfile": "about-pages.neb",
    "time": 76
    
]

但我希望它返回的是

[
    
    "testfile": "lists.txt",
    "tests": 5, 
    "time": 900
    ,
    
    "testfile": "buttons.txt",
    "tests": 4,
    "time": 800
    ,
    
    "testfile": "cards.txt",
    "tests": 8,
    "time": 400
    ,
    
    "testfile": "popover.txt",
    "tests": 1,
    "time": 300
    ,
    
    "testfile": "about-pages.neb",
    "tests": 2,
    "time": 76
    
]

【问题讨论】:

【参考方案1】:

您需要在$group$project 阶段中​​添加额外的字段。

您需要对time 字段使用$max 运算符并累积tests 字段time:tests 值。在最后阶段,我们$reducetests字段取最高值


  "$group": 
    _id: "$testfile",
    time: 
      $max: "$time"
    ,
    tests: 
      "$push": 
        time: "$time",
        tests: "$tests"
      
    
  
,

  "$sort": 
    time: 1
  
,

  "$project": 
    _id: 0,
    testfile: "$_id",
    time: "$time",
    tests: 
      $reduce: 
        input: "$tests",
        initialValue: 0,
        in: 
          $add: [
            "$$value",
            
              $cond: [
                
                  $and: [
                    
                      $eq: [
                        "$time",
                        "$$this.time"
                      ]
                    ,
                    
                      $gt: [
                        "$$this.tests",
                        "$$value"
                      ]
                    
                  ]
                ,
                
                  $subtract: [
                    "$$this.tests",
                    "$$value"
                  ]
                ,
                0
              ]
            
          ]
        
      
    
  

MongoPlayground

【讨论】:

我最初尝试过,但遇到了时间最长的测试文件可能没有最多测试的问题,原因是测试已被编辑,现在它的测试比以前少或多.我想知道时间最长的测试文件并知道该测试文件中有多少测试这是一个有更多数据的示例mongoplayground.net/p/1n7v8U1UmmO 时间为“时间”的测试:76.404574 有 4 个测试,但查询结果为 5 个测试因为这是测试文件 about-pages.neb 的最大值 @BarretV 请再次检查,我已经更新了我的答案 我在 mongoplayground mongoplayground.net/p/mhIU5lvD5lC 上尝试过,但它仍然显示 about-pages.neb 的时间为 76.404574,这是正确的最高时间,但如果您查看具有该时间的文档它只有 4 个用于测试,但聚合显示值为 5 的测试。我想很难找到具有匹配时间的文档并从中获取测试的值用于聚合 非常感谢,这绝对比我目前的 MongoDB 知识先进得多,因此非常感谢您的帮助。这似乎有效,我使用数据来确保如果我添加更多它仍然是正确的,只是仔细检查并且一切都很好 @BarretV 酷。祝你好运

以上是关于Mongodb聚合对属于同一文档的多个值进行分组的主要内容,如果未能解决你的问题,请参考以下文章

《MongoDB入门教程》第22篇 聚合操作

《MongoDB入门教程》第22篇 聚合操作

《MongoDB入门教程》第22篇 聚合操作

如何对对象数据的mongodb聚合数组进行分组以对同一日期的数字求和

mongodb聚合命令

Mongodb聚合