聚合框架中的组停止正常工作

时间:2012-12-13 05:21:14

标签: mongodb aggregation-framework

我讨厌这类问题,但也许你可以指出我很明显。我正在使用Mongo 2.2.2。

我有一个带有6M文档的集合(在副本集中),其中包含名为 username 的字符串字段,我有索引。该指数并非独一无二,但最近我将其独特。突然之后,查询给了我错误警报,我有重复。

db.users.aggregate(
    { $group : {_id : "$username", total : { $sum : 1 } } },
    { $match : { total : { $gte : 2 } } },
    { $sort : {total : -1} } );

返回

{
        "result" : [
                {
                        "_id" : "davidbeges",
                        "total" : 2
                },
                {
                        "_id" : "jesusantonio",
                        "total" : 2
                },
                {
                        "_id" : "elesitasweet",
                        "total" : 2
                },
                {
                        "_id" : "theschoolofbmx",
                        "total" : 2
                },
                {
                        "_id" : "longflight",
                        "total" : 2
                },
                {
                        "_id" : "thenotoriouscma",
                        "total" : 2
                }
        ],
        "ok" : 1
}

我在几个文档的样本集上测试了这个查询,它按预期工作。

2 个答案:

答案 0 :(得分:2)

10gen之一在他们的JIRA中做出回应。

这个系列有什么更新吗?如果是这样,我会尝试将{$ sort:{username:1}}添加到管道的前面。这将确保您只看到每个用户名一次,如果它是唯一的。 如果有更新,如果文档因增长而移动,则聚合可能会看到文档两次。另一种可能性是,在聚合看到文档后,文档被删除,并且使用相同的用户名插入了新文档。

因此,在分组之前按username排序有帮助。

答案 1 :(得分:0)

我认为答案可能在于你的$group没有使用索引,它只是对整个集合进行扫描。这些运算符当前可以在聚合框架中使用和索引:

$match $sort $limit $skip

如果放在它们之前它们会起作用:

$project $unwind $group

但是,$group本身不会使用索引。当你进行find()测试时,我打赌你正在使用索引,可能作为覆盖索引(你可以通过查看该查询的explain()进行验证),而不是扫描集合。基本上我的理论是你的索引没有欺骗,但你的收藏确实如此。

编辑:这可能是因为文档在聚合操作期间被更新/移动,因此被看到两次,而不是因为最初认为的集合中的欺骗。

如果您在管道中添加了一个可以使用索引但不会改变输入$group的结果的运算符,那么您可以避免此问题。