在索引列上的MongoDB select count(distinct x) – 计算大数据集的唯一结果
我已经经历了几篇文章和示例,并且还没有find一种有效的方法来在MongoDB中进行这种SQL查询(其中有数百万 行 文件)
第一次尝试
(例如,从这个几乎重复的问题 – Mongo相当于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
第三次尝试
我还没有尝试过,但有几个build议涉及到mapReduce
例如
- 这个如何在MongoDB中做出截然不同的分组? (不接受,回答作者/ OP没有testing)
- 这个由function组成的MongoDB组 (类似于第二次尝试)
- 这一个http://blog.emmettshear.com/post/2010/02/12/Counting-Uniques-With-MongoDB
- 这一个https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/trDn3jJjqtE
- 这一个http://cookbook.mongodb.org/patterns/unique_items_map_reduce/
也
似乎GitHub上有一个pull请求修复.distinct
方法提到它应该只返回一个计数,但它仍然是开放的: https : //github.com/mongodb/mongo/pull/34
但在这一点上,我认为值得在这里问一下,关于这个问题最新的是什么? 我应该迁移到SQL还是另一个NoSQL数据库来区分不同的计数? 还是有一个有效的方法?
更新:
对MongoDB官方文档的评论并不令人鼓舞,这是否准确?
http://www.mongodb.org/display/DOCS/Aggregation#comment-430445808
UPDATE2:
似乎新的聚合框架回答上述评论…(MongoDB 2.1 / 2.2及以上,开发预览可用,不生产)
http://docs.mongodb.org/manual/applications/aggregation/
1)最简单的方法是通过聚合框架。 这需要两个“$组”命令:第一个按不同的值分组,第二个按照所有不同的值进行计数
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做到这一点,你可以。 这也是一个两阶段的过程:第一阶段,我们build立一个新的集合,列出关键的每个不同的价值。 在第二个我们对新的集合做一个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的文档大小限制。 您可以将计算保存到集合中,然后count()集合的大小,或者可以从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;
以下解决scheme为我工作
db.test.distinct( '用户'); [“alex”,“英国”,“法国”,“澳大利亚”]
db.countries.distinct('country')。length 4