【问题标题】:Group all objects using aggregation framework使用聚合框架对所有对象进行分组
【发布时间】:2012-10-11 11:17:00
【问题描述】:

我在 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... },
            ...
        ]
    }

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

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

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

    那么你只需要推送“事件”。

    【讨论】:

    • 这可行,但我宁愿不必更改数据的形状。我最终通过一个简单的群组通话并在客户端进行排序。
    【解决方案2】:

    如果您先进行匹配,您将能够使用索引(如果“somefield”上存在索引)

    您是否需要投影要为每个聚合值创建数组的子文档?我还没有对此进行测试,但可能会为您指明正确的方向?

    类似的东西?

    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" }
        }
     })
    

    【讨论】:

      【解决方案3】:

      使用组功能更容易解决这个问题:

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

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

      【讨论】:

      • 你不能在 group() 上添加 .Sort() 吗?
      猜你喜欢
      • 2018-03-19
      • 2017-04-24
      • 2017-02-14
      • 1970-01-01
      • 2016-04-18
      • 2019-08-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      相关资源
      最近更新 更多