通过迭代计算MongoDB集合不会产生正确的计数

时间:2016-11-25 06:01:49

标签: mongodb mongodb-query mongodb-java

使用以下代码,我将遍历MongoDB集合以计算其计数。(使用循环,限制并按_id递增排序)

忽略了计算计数的其他方法,因为我使用这种方式做其他事情(这段代码只是说明了我无法取出所有文档的事实)。

但它没有产生正确的计数。 我收藏的文件总数应为12637833, 但是使用以下代码,打印的计数是12602135。

也就是说,它们之间有大约3万个差距。

有人可以帮助解决这个问题吗?谢谢!

DBObject query = new BasicDBObject();
    DBObject sorter = new BasicDBObject("_id", 1);
    ObjectId largestObjectId = null;
    int count = 0;
    while (true) {  
        DBCursor cursor = c.find(query).sort(sorter).limit(200000);
        if (!cursor.hasNext()) {
            break;
        }
        while (cursor.hasNext()) {
            count++;
            BasicDBObject document = (BasicDBObject) cursor.next();
            if (document == null) {
                continue;
            }
            largestObjectId = (ObjectId) document.get("_id");
        }

        query = new BasicDBObject("_id", new BasicDBObject("$gt", largestObjectId));


        cursor.close();
    }

   System.out.println("Total Count is: " + count) 

1 个答案:

答案 0 :(得分:0)

文档计数的不匹配只能在一个线程读取数据而其他线程将某些内容写入数据库的环境中发生(即在一个线程写入mongodb而另一个线程执行某些操作的多线程应用程序中) 。

此外,当我们使用DBCursor迭代使用12637833记录进行收集时,并非所有记录最初都会加载到内存(JVM内存)中,而是从数据库中延迟取出。

有趣的是,在多线程应用程序中,您可以找到DBCursor长度与迭代光标和获取计数之间的差异,因为当我们在DBCursor上使用length或toArray时,将不可逆转地将DBCursor转换为数组。因此,在DBCursor中调用toArray或length之前应该采取额外的预防措施,因为它会突然增加内存中的记录。如果我们有一千万条记录,那么内存中将有一千万个元素数组。因此,在DBCursor中使用length或toArray之前,请始终使用skip()和limit()来最小化结果。