当前位置: 首页 > 知识库问答 >
问题:

在mongodb聚合框架中执行case-statement

阎承嗣
2023-03-14

我正在评估MongoDB聚合框架在多大程度上适合我们的需求,因为我们目前运行在SQL Server之上。我很难执行特定的查询:

假设我有以下伪记录(建模为sql表中的列和mongodb集合中的完整文档)

{
   name: 'A',
   timespent: 100,
},
{
   name: 'B',
   timespent: 200,
},
{
   name: 'C',
   timespent: 300,
},
{
   name: 'D',
   timespent: 400,
},
{
   name: 'E',
   timespent: 500,
}
results{
   0-250: 2,
   250-450: 2,
   450-650: 1
}
select range, COUNT(*) as total from (
select case when Timespent <= 250 then '0-250'
when Timespent <= 450 then '200-450'
else '450-600' end as range
from TestTable) as r
group by r.range

我很难在mongodb聚合框架中找到合适的结构来执行这样的查询。我可以通过在管道中插入$match来查询单个范围的结果(即获取单个范围的结果),但我无法在单个管道查询中提取所有范围及其计数。

共有1个答案

雍志新
2023-03-14

与聚合框架中的“case”SQL语句相对应的是$cond运算符(请参见手册)。可以嵌套$cond语句来模拟“when-then”和“else”,但我选择了另一种方法,因为它更容易读取(和生成,见下文):我将使用$concat运算符编写范围字符串,然后将其用作分组键。

因此对于给定的集合

db.xx.find()
{ "_id" : ObjectId("514919fb23700b41723f94dc"), "name" : "A", "timespent" : 100 }
{ "_id" : ObjectId("514919fb23700b41723f94dd"), "name" : "B", "timespent" : 200 }
{ "_id" : ObjectId("514919fb23700b41723f94de"), "name" : "C", "timespent" : 300 }
{ "_id" : ObjectId("514919fb23700b41723f94df"), "name" : "D", "timespent" : 400 }
{ "_id" : ObjectId("514919fb23700b41723f94e0"), "name" : "E", "timespent" : 500 }

聚合(硬编码)如下所示:

db.xx.aggregate([
  { $project: {
    "_id": 0,
    "range": {
      $concat: [{
        $cond: [ { $lte: ["$timespent", 250] }, "range 0-250", "" ]
      }, {
        $cond: [ { $and: [
          { $gte: ["$timespent", 251] }, 
          { $lt:  ["$timespent", 450] } 
        ] }, "range 251-450", "" ]
      }, {
        $cond: [ { $and: [
          { $gte: ["$timespent", 451] }, 
          { $lt:  ["$timespent", 650] } 
        ] }, "range 450-650", "" ]
      }]
    }
  }},
  { $group: { _id: "$range", count: { $sum: 1 } } },
  { $sort: { "_id": 1 } },
]);

结果是:

{
    "result" : [
        {
            "_id" : "range 0-250",
            "count" : 2
        },
        {
            "_id" : "range 251-450",
            "count" : 2
        },
        {
            "_id" : "range 450-650",
            "count" : 1
        }
    ],
    "ok" : 1
}
var ranges = [ 0, 250, 450, 650 ];
var rangeProj = {
  "$concat": []
};

for (i = 1; i < ranges.length; i++) {
  rangeProj.$concat.push({
    $cond: {
      if: {
        $and: [{
          $gte: [ "$timespent", ranges[i-1] ]
        }, {
          $lt: [ "$timespent", ranges[i] ]
        }]
      },
      then: "range " + ranges[i-1] + "-" + ranges[i],
      else: ""
    }
  })
}

db.xx.aggregate([{
  $project: { "_id": 0, "range": rangeProj }
}, {
  $group: { _id: "$range", count: { $sum: 1 } }
}, {
  $sort: { "_id": 1 }
}]);

它将返回与上面相同的结果。

 类似资料:
  • 本文向大家介绍在MongoDB中执行聚合排序?,包括了在MongoDB中执行聚合排序?的使用技巧和注意事项,需要的朋友参考一下 您可以将method和$sort()运算符一起使用。为了理解这个概念,让我们用文档创建一个集合。使用文档创建集合的查询如下- 在method的帮助下显示集合中的所有文档。查询如下- 以下是输出- 这是对MongoDB聚合排序的查询。 情况1-每当您希望结果按降序排列时。查

  • 是否可以在$match中执行OR? 我的意思是这样的:

  • 我不熟悉Spring和Mongo。我正在使用Spring Batch获取一些报告。我的查询需要一些MongoItemReader不支持的聚合,所以我根据下面的stackoverflow链接扩展了该类。 如何在Spring批处理中使用MongoItemReader聚合查询 但我的聚合有点问题。我制作的聚合在mongoDB中运行良好,但无法将其转换为Spring mongo聚合。 MongoDb聚合按

  • MongoDB中的聚合框架有解释功能吗?我在文件里看不到。 我知道找到你就行了 但是在聚合框架中,我得到了一个错误

  • 问题内容: 我有一个聚合管道,其中包括一个像这样的项目: 在mongo shell中可以正常工作。如何在Spring-Mongodb中使用Aggregation框架表达这一点?我见过ProjectionOperationBuilder,ExpressionProjectionOperationBuilder类型,但没有一个示例如何使用它们……有什么建议吗? 问题答案: 如果使用通过管道支持操作员的

  • 我有一个包含联系人的集合,每个联系人文档都有和属性。 现在我想使用Java和版本3.2中的MongoDb Java驱动程序查询数据库。 谢谢。