MongoDB聚合查询等效于PostsgreSQL

时间:2012-10-03 01:38:25

标签: mongodb aggregation-framework

这个问题有两个部分。集合结构是:

_id:MongoID,
agent_id:string,
结果:字符串,
created_on:ISO DATE,
......其他领域......

第一部分:
期望输出:每个agent_id和结果组合的一个结果与count:使用PostgreSQL的等效SQL的TUPLE表示。

( "1234", "Success", 4 ),
( "1234", "Failure", 4 ),
( "4567", "Success", 3 ),
( "7896", "Failure", 2 ),
.....

SELECT agent_id, result, count(*)
FROM table
GROUP BY agent_id, result
HAVING created_on >= now()::date;

我已经提出了下面的mongo查询....我想我有一个概念或语法错误。文档说要使用$ match early in the pipeline:,但是当我自己运行查询时,$ match会限制查询,只要我添加$ group,我就会获得很多结果。此外,我似乎无法理解如何分组多个字段。如何编辑以下查询以获得上面的SQL查询结果?

db.collection.aggregate(
  { $match : 
    { created_on: 
        { $gte: new Date('08-13-2012') //some arbitrary date
    }
  }, $group:
    { _id:"$agent_id" }, 
   $project:
  {_id:0, agent_id:1, result:1}
})

第2部分) 第一个结果集是足够的,但不是最佳的。使用PostgreSQL,我可以实现如下结果集:

( "1234", { "Success", "Failure" }, { 4, 3 } ),
( "4567", { "Success", "Failure" }, { 3, 0 } ),
( "7896", { "Success", "Failure" }, { 0, 2 } )

我可以在Postgresql中使用数组数据类型和set_to_array函数(自定义函数)来完成此操作。 Pg特定的SQL是:

SELECT agent_id, set_to_array(result), set_to_array( count(*) )
FROM table
GROUP BY agent_id, result
HAVING created_on >= now()::date;

我相信mongodb中的等效数据结构如下:

[
   { "1234", [ { "success": 4 }, { "failure": 4 } ] },
   { "4567", [ { "success": 3 }, { "failure": 0 } ] },
   { "7896", [ { "success": 0 }, { "failure": 0 } ] }
]

是否有可能使用mongodb聚合框架实现这些所需的压缩结果?

1 个答案:

答案 0 :(得分:3)

你走了:

创建了一些测试数据:

  

db.test.insert({agent_id:“1234”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1234”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1234”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1234”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1234”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1234”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1234”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“成功”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“失败”,created_on:new Date()});   db.test.insert({agent_id:“1324”,结果:“失败”,created_on:new Date()});

db.test.aggregate(
  {
    $match:{ /* filter out the things you want to aggregate */
      created_on:{$gte:new Date(1000000)}
    }
  }, 
  {
    $group: {_
      _id: { /* the things you want to group on go in the _id */
        agent_id:"$agent_id", 
        result:"$result"
      }, 
      count:{$sum:1} /* simple count */
    }
  }, 
  {
    $project: { /* take the id out into the separate fields for your tuple. */
      _id:0, 
      agent_id:"$_id.agent_id", 
      result:"$_id.result", 
      count:"$count"
    }
  });

给出:

{
"result" : [
    {
        "count" : 7,
        "agent_id" : "1324",
        "result" : "Failure"
    },
    {
        "count" : 4,
        "agent_id" : "1324",
        "result" : "Success"
    },
    {
        "count" : 4,
        "agent_id" : "1234",
        "result" : "Success"
    },
    {
        "count" : 3,
        "agent_id" : "1234",
        "result" : "Failure"
    }
],
"ok" : 1
} 

添加第2部分 - 与第1部分非常相似,但计数有点复杂;基本上只有当它与您想要计算的数量匹配时才算数:

db.test.aggregate(
  {
    $match: { 
      created_on: {$gte:new Date(1000000)}
    }
  }, 
  {
    $group: {
      _id: { 
        agent_id:"$agent_id"
      }, 
      failure: {
        $sum:{
          $cond:[
            {$eq:["$result","Failure"]}, 
            1, 
            0
          ]
        }
      }, 
      success: {
        $sum: { 
          $cond:[
            {$eq:["$result","Success"]}, 
            1, 
            0
          ]
        }
      } 
    } 
  }, 
  {
    $project: {
      _id: 0, 
      agent_id: "$_id.agent_id", 
      failure: "$failure", 
      success: "$success"
    }
  });

给出:

{
"result" : [
    {
        "failure" : 7,
        "success" : 4,
        "agent_id" : "1324"
    },
    {
        "failure" : 3,
        "success" : 4,
        "agent_id" : "1234"
    }
],
"ok" : 1
}