MongoDB select count(distinct x) on an indexed col

我浏览了几篇文章和示例,但尚未找到在 MongoDB 中执行此 SQL 查询的有效方法(其中有数百万 rows 文档)

第一次尝试

(例如,来自这个几乎重复的问题 - Mongo equivalent of SQL's 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

例如

  • 这个how to do distinct and group in mongodb? (不接受,回答作者/OP 未测试)
  • 这个MongoDB group by Functionalities (似乎类似于第二次尝试)
  • 这个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 上有一个拉取请求修复了 .distinct 方法,提到它应该只返回一个计数,但它仍然是开放的:https://github.com/mongodb/mongo/pull/34

但在这一点上,我认为值得在这里问一下,关于这个主题的最新消息是什么?我应该转移到 SQL 还是其他 NoSQL DB 来进行不同的计数?还是有什么有效的方法?

更新:

对 MongoDB 官方文档的评论并不令人鼓舞,这是准确的吗?

http://www.mongodb.org/display/DOCS/Aggregation#comment-430445808

更新2:

似乎新的聚合框架回答了上述评论...(MongoDB 2.1/2.2 及更高版本,提供开发预览版,不适用于生产)

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

最佳答案

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 的文档大小限制。你可以将计算保存在一个集合中,然后count()这个集合的大小,或者你可以从mapReduce()的返回值中得到结果的个数。

关于MongoDB select count(distinct x) on an indexed column - 计算大型数据集的唯一结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11782566/

相关文章:

mongodb - 使用 Mongoose 从 MongoDB 文档中删除一个键

mongodb - 无法验证到 mongo, "auth fails"

javascript - node.js mongodb 通过_id node-mongodb-na

sql - mongo中的外键?

node.js - 如何在 mongodb-native findOne() 中使用变量作为字段名?

macos - mac上mongodb数据库的位置

java - Spring Data 的 MongoTemplate 和 MongoReposito

mongodb - 无法启动/启动本地 mongo db

mongodb - 如何将 mongodb 客户端连接到本地 Meteor MongoDB

mongodb - 如何使用 MongoDB 过滤子文档中的数组