MongoDB 对大型数据集的索引列计数唯一结果进行选择计数(独立 x)

我已经阅读了几篇文章和示例,尚未找到在 MongoDB 中执行这个 SQL 查询的有效方法(MongoDB 中有数百万个 一排排文档)

第一次尝试

(例如,从这个几乎重复的问题 -相当于 SQL 的 SELECT DISTINCT?)

db.myCollection.distinct("myIndexedNonUniqueField").length

显然,我得到了这个错误,因为我的数据集是巨大的

Thu Aug 02 12:55:24 uncaught exception: distinct failed: {
"errmsg" : "exception: distinct too big, 16mb cap",
"code" : 10044,
"ok" : 0
}

第二次尝试

我决定参加一个小组

db.myCollection.group({key: {myIndexedNonUniqueField: 1},
initial: {count: 0},
reduce: function (obj, prev) { prev.count++;} } );

但是我得到了这个错误消息:

exception: group() can't handle more than 20000 unique keys

第三次尝试

我还没有尝试,但有几个建议,涉及 mapReduce

例如:。

还有

GitHub 上似乎有一个拉请求,修复了 .distinct方法,提示它应该只返回一个计数,但它仍然是打开的: https://github.com/mongodb/mongo/pull/34

但在这一点上,我认为值得在这里问一问,这个问题的最新进展是什么?我应该移动到 SQL 或另一个 NoSQL 数据库为不同的计数?还是有一个有效的方法?

更新:

MongoDB 官方文档上的这个评论并不鼓舞人心,这个评论准确吗?

Http://www.mongodb.org/display/docs/aggregation#comment-430445808

更新2:

新的聚合框架似乎回答了上面的注释... (MongoDB 2.1/2.2及以上版本,开发预览可用,不适用于生产环境)

Http://docs.mongodb.org/manual/applications/aggregation/

76962 次浏览

1)最简单的方法是通过聚合框架。这需要两个“ $group”命令: 第一个命令按不同的值进行分组,第二个命令计算所有不同的值

pipeline = [
{ $group: { _id: "$myIndexedNonUniqueField"}  },
{ $group: { _id: 1, count: { $sum: 1 } } }
];


//
// Run the aggregation command
//
R = db.runCommand(
{
"aggregate": "myCollection" ,
"pipeline": pipeline
}
);
printjson(R);

2)如果你想用 Map/Reduce 做这件事,你可以。这也是一个两阶段的过程: 在第一阶段,我们构建一个新集合,其中包含键的每个不同值的列表。在第二步中,我们对新集合执行 count ()操作。

var SOURCE = db.myCollection;
var DEST = db.distinct
DEST.drop();




map = function() {
emit( this.myIndexedNonUniqueField , {count: 1});
}


reduce = function(key, values) {
var count = 0;


values.forEach(function(v) {
count += v['count'];        // count each distinct value for lagniappe
});


return {count: count};
};


//
// run map/reduce
//
res = SOURCE.mapReduce( map, reduce,
{ out: 'distinct',
verbose: true
}
);


print( "distinct count= " + res.counts.output );
print( "distinct count=", DEST.count() );

注意,不能内联返回 map/reduce 的结果,因为这可能会超过16MB 的文档大小限制。可以将计算保存在集合中,然后计算()集合的大小,或者可以从 mapReduce ()的返回值中获得结果的数量。

db.myCollection.aggregate(
{$group : {_id : "$myIndexedNonUniqueField"} },
{$group: {_id:1, count: {$sum : 1 }}});

直接结果:

db.myCollection.aggregate(
{$group : {_id : "$myIndexedNonUniqueField"} },
{$group: {_id:1, count: {$sum : 1 }}})
.result[0].count;

下面的解决方案对我很有效

清晰(‘ user’) ; [“亚历克斯”,“英格兰”,“法国”,“澳大利亚”]

(“ country”)长度 4