如何在 golang 中进行 Mongodb 聚合
How to do that Mongodb aggregation in golang
我有一个这样的 MongoDB 集合:
{ "_id" : ObjectId("5a017ee061313781045889ea"), "device_id" : "1232213", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:37:37.006Z") }
{ "_id" : ObjectId("5a017f7b61313781045889eb"), "device_id" : "1111", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:40:11.204Z") }
{ "_id" : ObjectId("5a017fdd61313781045889ec"), "device_id" : "12222", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:41:49.452Z") }
{ "_id" : ObjectId("5a017ff561313781045889ed"), "device_id" : "1232213", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:42:13.658Z") }
我想按 "device_id"
区分它并按 "pubtime"
排序。
我知道 Golang 可以用管道来做。但我不知道该怎么做。我尝试了什么:
o1 := bson.M{"_id": bson.M{"device_id": "$device_id"}}
o2 := bson.M{"pubtime": bson.M{"$last": "$pubtime"}}
o3 := bson.M{"$group": []bson.M{o1, o2}}
pipe := c.Pipe([]bson.M{o3})
var result = []bson.M{}
_ = pipe.All(&result)
fmt.Println(result)
结果为空。
在MongoDB没问题:
db.collections.aggregate({"$group":
{"_id":{"device_id":"$device_id"},
"pubtime":{"$last": "$pubtime"} ,
"value":{"$last": "$value"} ,
}});
可以在 mongodb 聚合管道
中使用 $group and $first 来完成
Mongodbshell查询
db.collection.aggregate([
{$group: {_id:{device_id:"$device_id"}, pubtime:{$first:"$pubtime"}}}
]);
在mongo shell
中执行上述查询后得到的结果
{ "_id" : { "device_id" : "12222" }, "pubtime" : ISODate("2017-11-07T09:41:49.452Z") }
{ "_id" : { "device_id" : "1111" }, "pubtime" : ISODate("2017-11-07T09:40:11.204Z") }
{ "_id" : { "device_id" : "1232213" }, "pubtime" : ISODate("2017-11-07T09:37:37.006Z") }
您没有检查错误,这是您的主要问题。 Pipe.All()
returns 您优雅地丢弃的错误。不要那样做。
var result = []bson.M{}
err := pipe.All(&result)
fmt.Println(result, err)
这将打印:
[] a group's fields must be specified in an object
错误说明了一切。 $group
的值必须是例如bson.M
值,而不是 bson.M
:
的一部分
o3 := bson.M{"$group": bson.M{
"_id": bson.M{"device_id": "$device_id"},
"pubtime": bson.M{"$last": "$pubtime"},
}}
pipe := c.Pipe([]bson.M{o3})
var result = []bson.M{}
err := pipe.All(&result)
fmt.Println(result, err)
现在输出将是:
[map[_id:map[device_id:12222] pubtime:2017-11-07 10:41:49.452 +0100 CET] map[_id:map[device_id:1111] pubtime:2017-11-07 10:40:11.204 +0100 CET] map[_id:map[device_id:1232213] pubtime:2017-11-07 10:42:13.658 +0100 CET]] <nil>
所以它有效。
要使结果按 pubtime
排序,请使用 $sort
。这是最终代码:
pipe := c.Pipe([]bson.M{
{
"$group": bson.M{
"_id": bson.M{"device_id": "$device_id"},
"pubtime": bson.M{"$last": "$pubtime"},
},
},
{"$sort": bson.M{"pubtime": 1}},
})
var result = []bson.M{}
err := pipe.All(&result)
fmt.Println(result, err)
如果您希望结果按降序排列,请使用:
{"$sort": bson.M{"pubtime": -1}}
还要注意,分组的时候,如果分组_id
是一个单独的字段,不需要包装成一个对象,直接用$device_id
作为分组id即可:
"$group": bson.M{
"_id": "$device_id",
"pubtime": bson.M{"$last": "$pubtime"},
},
我有一个这样的 MongoDB 集合:
{ "_id" : ObjectId("5a017ee061313781045889ea"), "device_id" : "1232213", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:37:37.006Z") }
{ "_id" : ObjectId("5a017f7b61313781045889eb"), "device_id" : "1111", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:40:11.204Z") }
{ "_id" : ObjectId("5a017fdd61313781045889ec"), "device_id" : "12222", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:41:49.452Z") }
{ "_id" : ObjectId("5a017ff561313781045889ed"), "device_id" : "1232213", "value" : "23233", "pubtime" : ISODate("2017-11-07T09:42:13.658Z") }
我想按 "device_id"
区分它并按 "pubtime"
排序。
我知道 Golang 可以用管道来做。但我不知道该怎么做。我尝试了什么:
o1 := bson.M{"_id": bson.M{"device_id": "$device_id"}}
o2 := bson.M{"pubtime": bson.M{"$last": "$pubtime"}}
o3 := bson.M{"$group": []bson.M{o1, o2}}
pipe := c.Pipe([]bson.M{o3})
var result = []bson.M{}
_ = pipe.All(&result)
fmt.Println(result)
结果为空。
在MongoDB没问题:
db.collections.aggregate({"$group":
{"_id":{"device_id":"$device_id"},
"pubtime":{"$last": "$pubtime"} ,
"value":{"$last": "$value"} ,
}});
可以在 mongodb 聚合管道
中使用 $group and $first 来完成Mongodbshell查询
db.collection.aggregate([
{$group: {_id:{device_id:"$device_id"}, pubtime:{$first:"$pubtime"}}}
]);
在mongo shell
中执行上述查询后得到的结果{ "_id" : { "device_id" : "12222" }, "pubtime" : ISODate("2017-11-07T09:41:49.452Z") }
{ "_id" : { "device_id" : "1111" }, "pubtime" : ISODate("2017-11-07T09:40:11.204Z") }
{ "_id" : { "device_id" : "1232213" }, "pubtime" : ISODate("2017-11-07T09:37:37.006Z") }
您没有检查错误,这是您的主要问题。 Pipe.All()
returns 您优雅地丢弃的错误。不要那样做。
var result = []bson.M{}
err := pipe.All(&result)
fmt.Println(result, err)
这将打印:
[] a group's fields must be specified in an object
错误说明了一切。 $group
的值必须是例如bson.M
值,而不是 bson.M
:
o3 := bson.M{"$group": bson.M{
"_id": bson.M{"device_id": "$device_id"},
"pubtime": bson.M{"$last": "$pubtime"},
}}
pipe := c.Pipe([]bson.M{o3})
var result = []bson.M{}
err := pipe.All(&result)
fmt.Println(result, err)
现在输出将是:
[map[_id:map[device_id:12222] pubtime:2017-11-07 10:41:49.452 +0100 CET] map[_id:map[device_id:1111] pubtime:2017-11-07 10:40:11.204 +0100 CET] map[_id:map[device_id:1232213] pubtime:2017-11-07 10:42:13.658 +0100 CET]] <nil>
所以它有效。
要使结果按 pubtime
排序,请使用 $sort
。这是最终代码:
pipe := c.Pipe([]bson.M{
{
"$group": bson.M{
"_id": bson.M{"device_id": "$device_id"},
"pubtime": bson.M{"$last": "$pubtime"},
},
},
{"$sort": bson.M{"pubtime": 1}},
})
var result = []bson.M{}
err := pipe.All(&result)
fmt.Println(result, err)
如果您希望结果按降序排列,请使用:
{"$sort": bson.M{"pubtime": -1}}
还要注意,分组的时候,如果分组_id
是一个单独的字段,不需要包装成一个对象,直接用$device_id
作为分组id即可:
"$group": bson.M{
"_id": "$device_id",
"pubtime": bson.M{"$last": "$pubtime"},
},