dqwh2717 2017-11-15 05:27
浏览 1111
已采纳

如何在golang中进行Mongodb聚合

I have a MongoDB collection like this:

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

I want to distinct it by "device_id" AND sort it by "pubtime".

I know that Golang could use pipe to do it. But I don't know how to do it. What I tried:

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)

The result is empty.

It is ok in MongoDB:

db.collections.aggregate({"$group":
                        {"_id":{"device_id":"$device_id"},
                        "pubtime":{"$last": "$pubtime"} ,
                       "value":{"$last": "$value"} ,
                        }});
  • 写回答

2条回答 默认 最新

  • douqiangchuai7674 2017-11-15 08:44
    关注

    You're not checking the errors, that's your main problem. Pipe.All() returns an error which you gracefully discard. Don't do that.

    var result = []bson.M{}
    err := pipe.All(&result)
    fmt.Println(result, err)
    

    This will print:

    [] a group's fields must be specified in an object
    

    The error says it all. The value of $group must be e.g. a bson.M value, and not a slice of 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)
    

    Now the output will be:

    [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>

    So it works.

    And to make the results sorted by pubtime, use $sort. Here's the final code:

    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)
    

    If you want the results sorted in descending order, then use:

    {"$sort": bson.M{"pubtime": -1}}
    

    Also note that when grouping, if the group _id is a single field, you don't need to wrap it into an object, you can simply use $device_id as the group id:

    "$group": bson.M{
        "_id":     "$device_id",
        "pubtime": bson.M{"$last": "$pubtime"},
    },
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 安装svn网络有问题怎么办
  • ¥15 Python爬取指定微博话题下的内容,保存为txt
  • ¥15 vue2登录调用后端接口如何实现
  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 latex怎么处理论文引理引用参考文献