mongodb聚合$ group然后$推送一个对象

时间:2016-02-15 20:09:43

标签: mongodb aggregation-framework

这是我的数据:

> db.bookmarks.find({"userId" : "56b9b74bf976ab70ff6b9999"}).pretty()
{
    "_id" : ObjectId("56c2210fee4a33579f4202dd"),
    "userId" : "56b9b74bf976ab70ff6b9999",
    "items" : [
        {
            "itemId" : "28",
            "timestamp" : "2016-02-12T18:07:28Z"
        },
        {
            "itemId" : "29",
            "timestamp" : "2016-02-12T18:07:29Z"
        },
        {
            "itemId" : "30",
            "timestamp" : "2016-02-12T18:07:30Z"
        },
        {
            "itemId" : "31",
            "timestamp" : "2016-02-12T18:07:31Z"
        },
        {
            "itemId" : "32",
            "timestamp" : "2016-02-12T18:07:32Z"
        },
        {
            "itemId" : "33",
            "timestamp" : "2016-02-12T18:07:33Z"
        },
        {
            "itemId" : "34",
            "timestamp" : "2016-02-12T18:07:34Z"
        }
    ]
}

我希望有类似的东西(实际上我希望_id也能成为userId):

{ 
    "_id" : "56b9b74bf976ab70ff6b9999", 
    "items" : [ 
        { "itemId": "32", "timestamp": "2016-02-12T18:07:32Z" },
        { "itemId": "31", "timestamp": "2016-02-12T18:07:31Z" },
        { "itemId": "30", "timestamp": "2016-02-12T18:07:30Z" }
    ] 
}

我现在拥有的:

> db.bookmarks.aggregate(
...     { $match: { "userId" : "56b9b74bf976ab70ff6b9999" } },
...     { $unwind: '$items' },
...     { $sort: { 'items.timestamp': -1} },
...     { $skip: 2 },
...     { $limit: 3},
...     { $group: { '_id': '$userId' , items: { $push: '$items.itemId' } } }
... ).pretty()
{ "_id" : "56b9b74bf976ab70ff6b9999", "items" : [ "32", "31", "30" ] }

我试图在mongo中读取文档并找出我可以$ push,但不知怎的,我找不到推送这样的对象的方法,这个对象在整个对象中没有定义。我也希望有时间戳..但我不知道如何修改$ group(或其他??)这样做。谢谢你的帮助!

1 个答案:

答案 0 :(得分:1)

我在MongoDB 3.2.1 shell中测试过的代码应该为您提供所需的输出格式:

> db.bookmarks.aggregate( 
{ "$match" : { "userId" : "Ursula" } }, 
{ "$unwind" : "$items" }, 
{ "$sort" : { "items.timestamp" : -1 } }, 
{ "$skip" : 2 }, 
{ "$limit" : 3 }, 
{ "$group" : { "_id" : "$userId", items: { "$push" :  { "myPlace" : "$items.itemId", "myStamp" : "$items.timestamp" } } } }  ).pretty()

运行上面的代码会产生这个输出:

{
    "_id" : "Ursula",
    "items" : [
        {
            "myPlace" : "52",
            "myStamp" : ISODate("2016-02-13T18:07:32Z")
        },
        {
            "myPlace" : "51",
            "myStamp" : ISODate("2016-02-13T18:07:31Z")
        },
        {
            "myPlace" : "50",
            "myStamp" : ISODate("2016-02-13T18:07:30Z")
        }
    ]
}

在MongoDB版本3.2.x中,您还可以在聚合管道的最后阶段使用$ out运算符,并将聚合查询的输出写入集合。这是我使用的代码:

> db.bookmarks.aggregate( 
{ "$match" : { "userId" : "Ursula" } }, 
{ "$unwind" : "$items" }, 
{ "$sort" : { "items.timestamp" : -1 } }, 
{ "$skip" : 2 }, 
{ "$limit" : 3 }, 
{ "$group" : { "_id" : "$userId", items: { "$push" :  { "myPlace" : "$items.itemId", "myStamp" : "$items.timestamp" } } } }, 
{ "$out" : "ursula" } ) 

这给了我一个名为“ursula”的集合:

> show collections
ursula

我可以查询该集合:

> db.ursula.find().pretty()
{
    "_id" : "Ursula",
    "items" : [
        {
            "myPlace" : "52",
            "myStamp" : ISODate("2016-02-13T18:07:32Z")
        },
        {
            "myPlace" : "51",
            "myStamp" : ISODate("2016-02-13T18:07:31Z")
        },
        {
            "myPlace" : "50",
            "myStamp" : ISODate("2016-02-13T18:07:30Z")
        }
    ]
}
> 

最后,这是我在聚合查询中使用的输入文档。您可以将此文档与我对聚合查询进行编码的方式进行比较,以了解我如何构建新项目数组。

> db.bookmarks.find( { "userId" : "Ursula" } ).pretty()
{
    "_id" : ObjectId("56c240ed55f2f6004dc3b25c"),
    "userId" : "Ursula",
    "items" : [
        {
            "itemId" : "48",
            "timestamp" : ISODate("2016-02-13T18:07:28Z")
        },
        {
            "itemId" : "49",
            "timestamp" : ISODate("2016-02-13T18:07:29Z")
        },
        {
            "itemId" : "50",
            "timestamp" : ISODate("2016-02-13T18:07:30Z")
        },
        {
            "itemId" : "51",
            "timestamp" : ISODate("2016-02-13T18:07:31Z")
        },
        {
            "itemId" : "52",
            "timestamp" : ISODate("2016-02-13T18:07:32Z")
        },
        {
            "itemId" : "53",
            "timestamp" : ISODate("2016-02-13T18:07:33Z")
        },
        {
            "itemId" : "54",
            "timestamp" : ISODate("2016-02-13T18:07:34Z")
        }
    ]
}