2014-05-13 78 views
1

你好我是mongodb的新手,并尝试将不同类型的对象(int)转换为键值对。MongoDB聚合组数组键值:总和值

我有收集这样的:

{ 
    "_id" : ObjectId("5372a9fc0079285635db14d8"), 
    "type" : 1, 
    "stat" : "foobar" 
}, 
{ 
    "_id" : ObjectId("5372aa000079285635db14d9"), 
    "type" : 1, 
    "stat" : "foobar" 
}, 
{ 
    "_id" : ObjectId("5372aa010079285635db14da"), 
    "type" : 2, 
    "stat" : "foobar" 
},{ 
    "_id" : ObjectId("5372aa030079285635db14db"), 
    "type" : 3, 
    "stat" : "foobar" 
} 

我想结果是这样的:

{ 
    "type1" : 2, "type2" : 1, "type3" : 1, 
    "stat" : "foobar" 
} 

目前正在汇聚组,然后按类型值数组

db.types.aggregate(
    {$group : { 
     _id : "$stat", 
     types : {$push : "$type"} 
    }} 
) 

但不知道如何总结不同的类型s并将其转换为关键值

/* 0 */ 
{ 
    "result" : [ 
     { 
      "_id" : "foobar", 
      "types" : [ 
       1, 
       2, 
       2, 
       3 
      ] 
     } 
    ], 
    "ok" : 1 
} 
+0

:// JIRA .mongodb.org/browse/SERVER-5947,因为目前不可能。 –

+0

嗨,Asya,我投了这张杰拉票。 –

回答

5

为了您的实际形式,因此,假设你确实知道可能的值“类型”,那么你可以用两个$group阶段,有的采用$cond运营商的做到这一点:

db.types.aggregate([ 
    { "$group": { 
     "_id": { 
      "stat": "$stat", 
      "type": "$type" 
     }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$group": { 
     "_id": "$_id.stat", 
     "type1": { "$sum": { "$cond": [ 
      { "$eq": [ "$_id.type", 1 ] }, 
      "$count", 
      0 
     ]}}, 
     "type2": { "$sum": { "$cond": [ 
      { "$eq": [ "$_id.type", 2 ] }, 
      "$count", 
      0 
     ]}}, 
     "type3": { "$sum": { "$cond": [ 
      { "$eq": [ "$_id.type", 3 ] }, 
      "$count", 
      0 
     ]}} 
    }} 
]) 

其中给出确切:

{ "_id" : "foobar", "type1" : 2, "type2" : 1, "type3" : 1 } 

其实我更喜欢更具活力为米有两个$group阶段,但:

db.types.aggregate([ 
    { "$group": { 
     "_id": { 
      "stat": "$stat", 
      "type": "$type" 
     }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$group": { 
     "_id": "$_id.stat", 
     "types": { "$push": { 
      "type": "$_id.type", 
      "count": "$count" 
     }} 
    }} 
]) 

不相同的输出,但功能和灵活的价值观:

{ 
    "_id" : "foobar", 
    "types" : [ 
      { 
        "type" : 3, 
        "count" : 1 
      }, 
      { 
        "type" : 2, 
        "count" : 1 
      }, 
      { 
        "type" : 1, 
        "count" : 2 
      } 
    ] 
} 

否则,如果你需要相同的输出格式,但需要灵活的领域,那么你可以随时使用mapReduce,但它不完全相同的输出。

db.types.mapReduce(
    function() { 

     var obj = { }; 

     var key = "type" + this.type; 
     obj[key] = 1; 

     emit(this.stat, obj); 

    }, 
    function (key,values) { 

     var obj = {}; 

     values.forEach(function(value) { 
      for (var k in value) { 
       if (!obj.hasOwnProperty(k)) 
        obj[k] = 0; 
       obj[k]++; 
      } 
     }); 

     return obj; 

    }, 
    { "out": { "inline": 1 } } 
) 

而且在典型的MapReduce风格:

"results" : [ 
      { 
        "_id" : "foobar", 
        "value" : { 
          "type1" : 2, 
          "type2" : 1, 
          "type3" : 1 
        } 
      } 
    ], 

但这些都是你的选择

如果你想能够值这个JIRA票HTTPS映射到按键,投票
+0

我对条件使用了你的建议,它以所需的格式生成结果,并且完美地工作。我的集合稍微复杂一点,我将拥有大量文档。查询中的这些条件是否会导致性能问题? –

+0

@PoisoneR这里的答案有问题吗?有几种方法可以显示,但没有什么可以“动态”重命名这些字段,除了mapReduce方法之外,由于目前的工作方式,这种方法并不完全相同。但所显示的方式是目前的做法或至少接近结果。所以它不存在另一个答案,但是这个问题仍然存在,并且没有被接受。为什么?性能是相对的,但聚合框架比mapReduce更快。现代的MongoDB有选择允许内存使用。 –

+0

我忘了标记答案为接受。这是工作。只是想知道性能如何受到几个$ group和$项目阶段的影响。谢谢。 –

1

这对您来说足够接近吗?

{ "_id" : "foobar", "types" : [ { "type" : "type3", "total" : 1 }, { "type" : "type2", "total" : 1 }, { "type" : "type1", "total" : 2 } ] } 

这些类型是在一个数组中,但它似乎让你得到你正在寻找的数据。代码是:

db.types.aggregate(
    [{$group : { 
     _id : "$stat", 
     types : {$push : "$type"} 
    }}, 
    {$unwind:"$types"}, 
    {$group: { 
     _id:{stat:"$_id", 
     types: {$substr: ["$types", 0, 1]}}, 
     total:{$sum:1}}}, 
    {$project: { 
     _id:0, 
     stat:"$_id.stat", 
     type: { $concat: [ "type", "$_id.types" ] }, 
     total:"$total" }}, 
    {$group: { 
     _id: "$stat", 
     types: { $push: { type: "$type", total: "$total" } } }} 
    ] 
) 
+0

即使我更喜欢数组形式,结果也是可以实现的。但主要是在这里,为什么所有的阶段?我添加了一个响应来显示,无论您的方法是什么,您只需要两个。 –

+0

表示同意,并没有完成它 - 已经玩弄了$ concat来匹配OP期望的格式,并在优化之前等待反馈。 –

+0

我认为这个结果不会对我的问题有好处。我想在html模板中显示表格数据,而这个结果将代表一行。 –