MongoDB在索引列上选择count(distinct x)-计算大型数据集的唯一结果



我已经阅读了几篇文章和示例,还没有找到在MongoDB中进行SQL查询的有效方法(其中有数百万

文档)

第一次尝试

(例如,这个几乎重复的问题——Mongo相当于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

例如

  • 这一个如何在mongodb中进行区别和分组?(未被接受,答案作者/OP未测试)
  • 这是一个按功能划分的MongoDB组(看起来类似于第二次尝试)
  • 这个http://blog.emmettshear.com/post/2010/02/12/Counting-Uniques-With-MongoDB
  • 这个https://groups.google.com/forum/?fromgroups#!主题/mongodb用户/trDn3jJjqtE
  • 这个http://cookbook.mongodb.org/patterns/unique_items_map_reduce/

GitHub上似乎有一个修复.distinct方法的pull请求,提到它应该只返回一个计数,但它仍然是打开的: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/

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来实现这一点,你可以。这也是一个分为两个阶段的过程:在第一阶段,我们构建一个新的集合,其中包含键的每个不同值的列表。在第二个步骤中,我们对新集合进行计数()。

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;

以下解决方案适用于我的

db.test.dinclusive('user');["亚历克斯"、"英格兰"、"法国"、"澳大利亚"]

数据库.国家/地区.不同("国家/地区").长度4

db.myCollection.aggregate([
    {$group: {_id: "$myIndexedNonUniqueField"}},
    {$count: "count"}
]).next().count;

这使用MongoDB聚合功能来检索总数。它使用$group$count聚合管道阶段首先按唯一字段进行分组,然后将不同分组的总数作为一个名为count的字段返回。它使用next()检索结果游标的第一个(也是唯一一个)元素,并从该项检索count属性。

聚合结果:

[ { count: 227807 } ]

最新更新