在Mongodb中的聚合查询返回特定字段

16

文档示例:

{
    "_id" : ObjectId("53329dfgg43771e49538b4567"),
    "u" : {
        "_id" : ObjectId("532a435gs4c771edb168c1bd7"),
        "n" : "Salman khan",
        "e" : "salman@gmail.com"
    },
    "ps" : 0,
    "os" : 1,
    "rs" : 0,
    "cd" : 1395685800,
    "ud" : 0
}

查询:

db.collectiontmp.aggregate([
            {$match: {os:1}},
            {$project : { name:{$toUpper:"$u.e"} , _id:0 } },
            {$group: { _id: "$u._id",total: {$sum:1} }},
            {$sort: {total: -1}}, { $limit: 10 }
             ]);

我需要从上述查询中获取以下内容:

  1. u._id 进行分组
  2. 返回记录的总数和电子邮件,格式如下:

    { "result": [ { "email": "", "total": "" }, { "email": "", "total": "" } ], "ok": 1 }

1个回答

26

你在这里做的第一件错误的事情是不了解$project的工作原理。例如,$project$group等类似管道阶段仅输出“明确”标识的字段。因此,只有您要输出的字段才可用于后续管道阶段。

具体而言,在这里,您仅“投影”文档中“u”字段的一部分,因此删除了其他数据的可用性。现在这里唯一存在的字段是“name”,这是您“投影”的字段。

也许您真正想做的是这样的:

db.collectiontmp.aggregate([
    { "$group": {
        "_id": {
           "_id": "$u._id",
           "email": { "$toUpper": "$u.e" }
        },
        "total": { "$sum": 1 },
    }},
    { "$project": {
        "_id": 0,
        "email": "$_id.email",
        "total": 1
    }},
    { "$sort": { "total": -1 } },
    { "$limit": 10 }
])

甚至更多的可能性:

db.collectiontmp.aggregate([
    { "$group": {
        "_id": "$u._id",
        "email": { "$first": { "$toUpper": "$u.e" } }
        "total": { "$sum": 1 },
    }},
    { "$project": {
        "_id": 0,
        "email": 1,
        "total": 1
    }},
    { "$sort": { "total": -1 } },
    { "$limit": 10 }
])

这将为您提供所需的输出。

请记住,由于这是一个“管道”,因此仅来自前一阶段的“输出”可用于“下一个”阶段。这不是类似于SQL中的声明性语句,而是一个“管道”,没有文档的“全局”概念。

因此,请考虑Unix管道“|”命令,或者查找相关信息。那么你的想法就会落到实处。


@Anubhav 在我解释如何省略字段时,我无意中忽略了这个。$match 通常应该是你的第一个阶段,因为这是可以使用索引的地方。如果需要,稍后添加其他过滤器以进行额外的筛选。 - Neil Lunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接