具有聚合和分组的mgo

时间:2017-09-15 16:34:42

标签: go aggregation mgo

我正在尝试使用golang mgo执行查询 为了从连接中有效地获取不同的值,我知道这可能不是在Mongo中使用的最佳范例。

这样的事情:

pipe := []bson.M{

    {
        "$group": bson.M{
            "_id":  bson.M{"user": "$user"},

        },
    },

    {
        "$match": bson.M{
            "_id":  bson.M{"$exists": 1},
            "user": bson.M{"$exists": 1},
            "date_updated": bson.M{
                "$gt": durationDays,
            },
        },

    },

    {
        "$lookup": bson.M{
            "from":         "users",
            "localField":   "user",
            "foreignField": "_id",
            "as":           "user_details",
        },
    },
    {
        "$lookup": bson.M{
            "from":         "organizations",
            "localField":   "organization",
            "foreignField": "_id",
            "as":           "organization_details",
        },
    },

}

err := d.Pipe(pipe).All(&result)

如果我注释掉$group部分,查询将按预期返回连接。

如果我按原样运行,我会NULL

如果我将$group移动到管道的底部,我会得到一个Null值的数组响应

是否可以使用$group进行汇总(目标是模拟DISTINCT)?

1 个答案:

答案 0 :(得分:2)

您获得NULL的原因是您的$match过滤器在$group阶段后过滤掉所有文档。

$group的第一阶段之后,文档仅如下例所示:

  {"_id": { "user": "foo"}},
  {"_id": { "user": "bar"}},
  {"_id": { "user": "baz"}}

它们不再包含其他字段,即userdate_updatedorganization。如果您想保留其值,可以使用Group Accumulator Operator。根据您的使用情况,您也可以使用Aggregation Expression Variables

作为使用mongo shell的示例,让我们使用基本上选择第一次出现的$first operator。这可能对organization有意义,但对date_updated没有意义。请选择更合适的累加器运算符。

{"$group": { 
          "_id":"$user", 
          "date_updated": {"$first":"$date_updated"}, 
          "organization": {"$first":"$organization"}
         }
}

请注意,上述内容也会将{"_id":{"user":"$user"}}替换为更简单的{"_id":"$user"}

接下来,我们将添加$project stage,将我们的_id字段的结果从组操作重命名回user。也可随身携带其他领域而无需修改。

{"$project": {
              "user": "$_id", 
              "date_updated": 1, 
              "organization": 1
             }
 }

只需列出date_updated过滤器即可简化您的$match stage。首先,我们可以删除_id,因为它与管道中的这一点不再相关,如果您希望确保只处理user值的文档,则应放置$match$group之前。有关详情,请参阅Aggregation Pipeline Optimization

所以,所有这些组合将看起来如下:

[
 {"$group":{ 
             "_id": "$user", 
             "date_updated": { "$first": "$date_updated"}, 
             "organization": { $first: "$organization"} 
           }
 },
 {"$project":{ 
               "user": "$_id", 
               "date_updated": 1, 
               "organization": 1
             }
 }, 
 {"$match":{
          "date_updated": {"$gt": durationDays } }
 }, 
 {"$lookup":{
             "from": "users", 
             "localField": "user", 
             "foreignField": "_id", 
             "as": "user_details"
            }
 }, 
 {"$lookup":{
            "from": "organizations", 
            "localField": "organization", 
            "foreignField": "_id", 
            "as": "organization_details"
            }
 }
]

(我知道你已经知道了)最后,基于上面的usersorganizations集合的数据库模式,根据您的应用程序用例,您可能会重新考虑嵌入一些值。您可能会发现6 Rules of Thumb for MongoDB Schema Design很有用。