2016-11-25 3 views
1

С помощью следующего кода, я бы итерацию по коллекции MongoDB, чтобы вычислить его количество. (С петлевой, ограничение и сортировать по _id по возрастанию)Подсчитайте коллекцию MongoDB итерируя над ним не дает правильное количество

Игнорируйте тот факт, что существуют другие способы вычисления счета, поскольку я использую этот способ для выполнения других действий (этот код просто иллюстрирует тот факт, что я не могу извлечь все документы).

Но это не дает правильного счета. Итоговые документы моей коллекции должны быть 12637833, , но со следующим кодом, число напечатано 12602135.

То есть между ними существует около 30 тысяч разрывов.

Может ли кто-нибудь помочь, что может привести к этой проблеме? Благодаря!

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) 
+0

Это оштукатуренная коллекция? – hyades

+0

Спасибо @hyades за ответ. Да. – Tom

+0

Возможно, это связано с https://jira.mongodb.org/browse/SERVER-5931. Вместо запроса 'find' вы можете попробовать запрос агрегации' [{$ match: query}, {$ sort: {sorter}}, {$ limit: 200000}] ' – hyades

ответ

0

Несоответствие в подсчету документов может произойти только в среде, где один поток считывает данные и другой поток записывает что-то в базу данных (т.е. в многопоточном приложении, в котором один поток записывает в MongoDB и другими выполняет определенную операцию).

Кроме того, когда у нас есть DBCursor для итерации коллекции с 12637833 записями, не все записи будут загружены изначально в память (JVM-память), вместо этого он будет лениво извлечен из базы данных.

Интересно, что в многопоточном приложении вы можете найти разницу между длиной DBCursor и итерацией курсора и получением счета, поскольку, когда мы используем длину или toArray на DBCursor, бесповоротно превратите DBCursor в массив. Поэтому перед вызовом toArray или длине в DBCursor необходимо принять дополнительную меру предосторожности, так как она внезапно увеличит записи в памяти. Скажем, если у нас будет десять миллионов записей, тогда в памяти будет десятимиллионный массив элементов. Поэтому всегда используйте skip() и limit(), чтобы минимизировать результаты до использования длины или toArray в DBCursor.

 Смежные вопросы

  • Нет связанных вопросов^_^