2016-10-27 2 views
3

У меня есть следующий запрос.

db.getCollection('logs').find({'uid.$id': { 
    '$in': [ 
     ObjectId("580e3397812de36b86d68c04"), 
     ObjectId("580e33a9812de36b86d68c0b"), 
     ObjectId("580e339a812de36b86d68c09"), 
     ObjectId("580e339a812de36b86d68c08"), 
     ObjectId("580e33a9812de36b86d68c0a"), 
     ObjectId("580e33bd812de36b86d68c11"), 
     ObjectId("580e33c0812de36b86d68c13") 
    ]}, levelno: { '$gte': 10 } 
}).sort({_id: 1}) 

Это должно вернуть 1847 документов. Однако при выполнении этого я получаю только 1000 документов, то есть batchSize курсора, а затем курсор закрывается (установка cursorId на 0), как если бы все документы были возвращены.

Если я выберу сортировку, тогда я получу все документы 1847 года.

Так что мой вопрос в том, почему он бесшумно терпит неудачу при использовании сортировки с оператором $in?

EDIT

Использование explain дает следующие выходные данные

{ 
    "queryPlanner" : { 
     "plannerVersion" : 1, 
     "namespace" : "session.logs", 
     "indexFilterSet" : false, 
     "parsedQuery" : { 
      "$and" : [ 
       { 
        "levelno" : { 
         "$gte" : 10 
        } 
       }, 
       { 
        "uid.$id" : { 
         "$in" : [ 
          ObjectId("580e3397812de36b86d68c04"), 
          ObjectId("580e339a812de36b86d68c08"), 
          ObjectId("580e339a812de36b86d68c09"), 
          ObjectId("580e33a9812de36b86d68c0a"), 
          ObjectId("580e33a9812de36b86d68c0b"), 
          ObjectId("580e33bd812de36b86d68c11"), 
          ObjectId("580e33c0812de36b86d68c13") 
         ] 
        } 
       } 
      ] 
     }, 
     "winningPlan" : { 
      "stage" : "SORT", 
      "sortPattern" : { 
       "_id" : 1 
      }, 
      "inputStage" : { 
       "stage" : "SORT_KEY_GENERATOR", 
       "inputStage" : { 
        "stage" : "FETCH", 
        "inputStage" : { 
         "stage" : "IXSCAN", 
         "keyPattern" : { 
          "uid.$id" : 1, 
          "levelno" : 1, 
          "_id" : 1 
         }, 
         "indexName" : "uid.$id_1_levelno_1__id_1", 
         "isMultiKey" : false, 
         "isUnique" : false, 
         "isSparse" : false, 
         "isPartial" : false, 
         "indexVersion" : 1, 
         "direction" : "forward", 
         "indexBounds" : { 
          "uid.$id" : [ 
           "[ObjectId('580e3397812de36b86d68c04'), ObjectId('580e3397812de36b86d68c04')]", 
           "[ObjectId('580e339a812de36b86d68c08'), ObjectId('580e339a812de36b86d68c08')]", 
           "[ObjectId('580e339a812de36b86d68c09'), ObjectId('580e339a812de36b86d68c09')]", 
           "[ObjectId('580e33a9812de36b86d68c0a'), ObjectId('580e33a9812de36b86d68c0a')]", 
           "[ObjectId('580e33a9812de36b86d68c0b'), ObjectId('580e33a9812de36b86d68c0b')]", 
           "[ObjectId('580e33bd812de36b86d68c11'), ObjectId('580e33bd812de36b86d68c11')]", 
           "[ObjectId('580e33c0812de36b86d68c13'), ObjectId('580e33c0812de36b86d68c13')]" 
          ], 
          "levelno" : [ 
           "[10.0, inf.0]" 
          ], 
          "_id" : [ 
           "[MinKey, MaxKey]" 
          ] 
         } 
        } 
       } 
      } 
     }, 
     "rejectedPlans" : [ 
      { 
       "stage" : "SORT", 
       "sortPattern" : { 
        "_id" : 1 
       }, 
       "inputStage" : { 
        "stage" : "SORT_KEY_GENERATOR", 
        "inputStage" : { 
         "stage" : "FETCH", 
         "inputStage" : { 
          "stage" : "IXSCAN", 
          "keyPattern" : { 
           "levelno" : 1, 
           "_id" : 1, 
           "uid.$id" : 1 
          }, 
          "indexName" : "levelno_1__id_1_uid.$id_1", 
          "isMultiKey" : false, 
          "isUnique" : false, 
          "isSparse" : false, 
          "isPartial" : false, 
          "indexVersion" : 1, 
          "direction" : "forward", 
          "indexBounds" : { 
           "levelno" : [ 
            "[10.0, inf.0]" 
           ], 
           "_id" : [ 
            "[MinKey, MaxKey]" 
           ], 
           "uid.$id" : [ 
            "[ObjectId('580e3397812de36b86d68c04'), ObjectId('580e3397812de36b86d68c04')]", 
            "[ObjectId('580e339a812de36b86d68c08'), ObjectId('580e339a812de36b86d68c08')]", 
            "[ObjectId('580e339a812de36b86d68c09'), ObjectId('580e339a812de36b86d68c09')]", 
            "[ObjectId('580e33a9812de36b86d68c0a'), ObjectId('580e33a9812de36b86d68c0a')]", 
            "[ObjectId('580e33a9812de36b86d68c0b'), ObjectId('580e33a9812de36b86d68c0b')]", 
            "[ObjectId('580e33bd812de36b86d68c11'), ObjectId('580e33bd812de36b86d68c11')]", 
            "[ObjectId('580e33c0812de36b86d68c13'), ObjectId('580e33c0812de36b86d68c13')]" 
           ] 
          } 
         } 
        } 
       } 
      }, 
      { 
       "stage" : "FETCH", 
       "filter" : { 
        "$and" : [ 
         { 
          "levelno" : { 
           "$gte" : 10 
          } 
         }, 
         { 
          "uid.$id" : { 
           "$in" : [ 
            ObjectId("580e3397812de36b86d68c04"), 
            ObjectId("580e339a812de36b86d68c08"), 
            ObjectId("580e339a812de36b86d68c09"), 
            ObjectId("580e33a9812de36b86d68c0a"), 
            ObjectId("580e33a9812de36b86d68c0b"), 
            ObjectId("580e33bd812de36b86d68c11"), 
            ObjectId("580e33c0812de36b86d68c13") 
           ] 
          } 
         } 
        ] 
       }, 
       "inputStage" : { 
        "stage" : "IXSCAN", 
        "keyPattern" : { 
         "_id" : 1 
        }, 
        "indexName" : "_id_", 
        "isMultiKey" : false, 
        "isUnique" : true, 
        "isSparse" : false, 
        "isPartial" : false, 
        "indexVersion" : 1, 
        "direction" : "forward", 
        "indexBounds" : { 
         "_id" : [ 
          "[MinKey, MaxKey]" 
         ] 
        } 
       } 
      } 
     ] 
    }, 
    "ok" : 1 
} 
+0

@JohnnyHK I» ve добавил индекс 'uid. $ id_1_levelno_1__id_1', но не имеет никакого отношения к возвращенному количеству документов. – XeniaSis

+0

. Я добавил вывод на вопрос – XeniaSis

+0

, похоже, также связан с https: //jira.mongodb.org/browse/SERVER-7267, но они говорят, что исправлено – XeniaSis

ответ

0

То, что происходит в том, что этот отсортированный запрос должен быть выполнен в памяти, как это не поддерживается индексом, и это ограничивает результаты до 32 МБ. Это поведение документировано here, с JIRA об адресе этого here.

Кроме того, вы не можете определить индекс для поддержки этого запроса, как вы сортировка на поле, которое не является частью запроса, и ни один из этих случаев применяются:

Если ключи сортировки соответствуют индексным ключам или префиксу индекса, MongoDB может использовать индекс для сортировки результатов запроса. A префикс Компонентный индекс - это подмножество, состоящее из одного или нескольких ключей на начальном этапе шаблона ключа индекса .

...

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

Вы должны быть в состоянии обойти ограничение, используя структуру агрегации, которые могут быть проинструктированы использовать временные файлы для своих выходов трубопровода стадии при необходимости через allowDiskUse: true варианта:

db.getCollection('logs').aggregate([ 
    {$match: {'uid.$id': { 
     '$in': [ 
      ObjectId("580e3397812de36b86d68c04"), 
      ObjectId("580e33a9812de36b86d68c0b"), 
      ObjectId("580e339a812de36b86d68c09"), 
      ObjectId("580e339a812de36b86d68c08"), 
      ObjectId("580e33a9812de36b86d68c0a"), 
      ObjectId("580e33bd812de36b86d68c11"), 
      ObjectId("580e33c0812de36b86d68c13") 
     ]}, levelno: { '$gte': 10 } 
    }}, 
    {$sort: {_id: 1}} 
], { allowDiskUse: true }) 
0

Вы можете использовать objsLeftInBatch() метод, чтобы определить, сколько объект остается в партии и перебирать его.

Вы можете изменить размер и ограничение размера курсора штучного cursor.batchSize(size) и cursor.limit(limit)

+0

Я действительно не ищу решение, я просто хочу понять, почему это не работает, как ожидалось – XeniaSis

+0

Сервер MongoDB возвращает результаты запроса пакетами. Размер партии не будет превышать максимальный размер документа BSON. Для большинства запросов в первой партии достаточно документов, превышающих 1 мегабайт. Последующий размер партии составляет 4 мегабайта. Чтобы переопределить размер пакета по умолчанию, вы используете такие методы, как batchsize и limit –