MongoDB distinct 太大,超过了 16MB 的限制。

19

我有一个Mongodb集合,它只有两列:user和url。它有39274590行。表的键是{user,url}。

使用Java,我尝试列出不同的URL:

  MongoDBManager db = new MongoDBManager( "Website", "UserLog" );
  return db.getDistinct("url"); 

但是我收到了一个异常:

Exception in thread "main" com.mongodb.CommandResult$CommandFailure: command failed [distinct]: 
{ "serverUsed" : "localhost/127.0.0.1:27017" , "errmsg" : "exception: distinct too big, 16mb cap" , "code" : 10044 , "ok" : 0.0}

我该如何解决这个问题?是否有备选方案可以避免这个问题?


你是否曾经找到了这个问题的解决方案? - gmaniac
4个回答

12
在2.6版本中,您可以使用聚合命令来生成一个单独的集合:http://docs.mongodb.org/manual/reference/operator/aggregation/out/
这将避免mongodb对大多数查询的16mb限制。您可以在此处阅读有关在mongodb 2.6中处理大型数据集时使用聚合框架的更多信息:http://vladmihalcea.com/mongodb-2-6-is-out/
要使用聚合框架进行“distinct”查询,请按字段分组。
db.userlog.aggregate([{$group: {_id: '$url'} }]); 

注意:我不知道这对Java驱动程序如何起作用,祝你好运。


2
它给我用户 ID 列表,我如何得到计数? - ak3191

3
请看这个答案

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

2) 如果你想使用Map / Reduce来完成这个任务也可以。 这也是一个两阶段的过程:在第一阶段中,我们将建立一个新的集合,其中包含关键字的每个不同值列表。 在第二阶段,我们对新集合进行count()操作。

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


2
如果您使用的是MongoDB 3.0及以上版本,您可以使用带有batchSize的DistinctIterable类。
MongoCollection coll = null;
coll = mongodb.getCollection("mycollection");
DistinctIterable<String> ids = coll.distinct("id", String.class).batchSize(100);
for (String id: ids) {
    System.out.println("" + id);
}

http://api.mongodb.com/java/current/com/mongodb/client/DistinctIterable.html


0

关于 Groovy 的 3.x 版本:

import com.mongodb.client.AggregateIterable
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoCursor
import com.mongodb.client.MongoDatabase
import static com.mongodb.client.model.Accumulators.sum
import static com.mongodb.client.model.Aggregates.group
import static java.util.Arrays.asList
import org.bson.Document

//other code

AggregateIterable<Document> iterable = collection.aggregate(
    asList(
        group("\$" + "url", sum("count", 1))
    )
).allowDiskUse(true)

MongoCursor cursor = iterable.iterator()

while(cursor.hasNext()) {
    Document doc = cursor.next()
    println(doc.toJson())
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接