使用聚合框架将所有对象分组

时间:2012-10-11 11:17:01

标签: mongodb aggregation-framework

我在MongoDB中有一组看起来像这样的对象

    { "event_type": "event1", "created_at": some_date, ...more_fields... },
    { "event_type": "event2", "created_at": some_date, ...other_fields... },
    { "event_type": "event1", "created_at": some_date, ...more_fields... }

现在我希望上面的数据包含按某个字段分组的所有字段(可能不会出现在所有对象中),并按最高的created_at日期排序。我尝试使用聚合框架执行此操作,并使用以下查询:

  collection.aggregate([
    { "$group" => {
        :_id       => "$somefield",
        :last_time => { "$max"  => "$created_at" },
        :events    => { "$push" => { ... } }
      }
    },
    { "$match" => { "_id" => { "$ne" => nil } } },
    { "$sort" => { "last_time" => -1 } }
  ])

我面临的问题与线

有关
 :events    => { "$push" => { ... } }

如果我输入某些特定字段,那么它可以工作,但我不知道该集合包含哪些确切的字段。但我想要像这样返回整个对象:

    {
        "event_type": "event1", "last_time": some_date, "events": [
            { "event_type": "event1", "created_at": some_date, ...more_fields... },
            { "event_type": "event1", "created_at": some_date, ...more_fields... },
            ...
        ]
    }

3 个答案:

答案 0 :(得分:1)

假设您想要推送对象中的所有字段,而不确切知道这些字段是什么,那么您不能将它们包装在已知的字段父级中并推送它吗?

{ events: {
    "event_type": "event1", "created_at": some_date, ...more_fields... 
  }
},

然后你只需要推送“事件”。

答案 1 :(得分:0)

如果您先进行匹配,则可以使用索引(如果“某些字段”存在)

你是否需要预测要为每个聚合值创建数组的子文档?我没有对此进行测试,但可能希望能指出正确的方向吗?

之类的东西?

db.collection.aggregate( 
{ $match : { "some_field" : { $ne:null} } },  
{ $project : 
    { 
        event_type :"event_type", 
        created_at: "created_at",
        event: 
        {
            another_att: "attrib1",
            another_att2: "attrib2"
        }
     },
{ $group : 
    { 
        _id: "$event_type",
        lasttime : { $max: "$created_at"},
        theevents: { $addToSet : "$event" }
    }
 })

答案 2 :(得分:0)

使用群组功能可以更轻松地解决此问题:

options = {
  key:      "field_to_group_by",
  cond:     { ..some filter criteria.. },
  initial:  { :events  => [] },
  reduce:   "function(obj, agg) { agg.events.push(obj); }"
}
collection.group(options)

这不会按照我想要的顺序返回项目,但可以在客户端上进行排序。