2015-12-27 4 views
5

У меня есть 20 000 + документов в моем mongodb. Я только что узнал, что вы не можете запросить их всех за один раз.Ограничение результата запроса в MongoDB

Так что мой вопрос заключается в следующем:

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

Например, если мой find() запрос привел к 8 документов:

[{doc1}, {doc2}, {doc3}, {doc4}, {doc5}, {doc6}, {doc7}, {doc 8}] 

команды limit(2, 3) будет дает [doc3, doc4, doc5]

И еще мне нужно, чтобы получить общее количество для всего этого результата (без ограничения), например: length() даст 8 (общее количество документов, полученных от find())

Любое предложение? Благодаря

ответ

4

Я полагаю, у вас есть следующие документы в вашей коллекции.

{ "_id" : ObjectId("56801243fb940e32f3221bc2"), "a" : 0 } 
{ "_id" : ObjectId("56801243fb940e32f3221bc3"), "a" : 1 } 
{ "_id" : ObjectId("56801243fb940e32f3221bc4"), "a" : 2 } 
{ "_id" : ObjectId("56801243fb940e32f3221bc5"), "a" : 3 } 
{ "_id" : ObjectId("56801243fb940e32f3221bc6"), "a" : 4 } 
{ "_id" : ObjectId("56801243fb940e32f3221bc7"), "a" : 5 } 
{ "_id" : ObjectId("56801243fb940e32f3221bc8"), "a" : 6 } 
{ "_id" : ObjectId("56801243fb940e32f3221bc9"), "a" : 7 } 

С MongoDB 3.2 вы можете использовать метод .aggregate() и оператор $slice.

db.collection.aggregate([ 
    { "$group": { 
     "_id": null, 
     "count": { "$sum": 1 }, 
     "docs": { "$push": "$$ROOT" } 
    }}, 
    { "$project": { 
     "count": 1, 
     "_id": 0, 
     "docs": { "$slice": [ "$docs", 2, 3 ] } 
    }} 
]) 

Который возвращает:

{ 
     "count" : 8, 
     "docs" : [ 
       { 
         "_id" : ObjectId("56801243fb940e32f3221bc4"), 
         "a" : 2 
       }, 
       { 
         "_id" : ObjectId("56801243fb940e32f3221bc5"), 
         "a" : 3 
       }, 
       { 
         "_id" : ObjectId("56801243fb940e32f3221bc6"), 
         "a" : 4 
       } 
     ] 
} 

Вы можете сортировать документ до группировки с помощью оператора $sort.


От MongoDB 3.0 назад Вы должны сначала $group ваших документов и использовать оператор $sum аккумулятора для возврата «счетчик» документы; также на том же групповом этапе вам нужно использовать переменную $push и $$ROOT, чтобы вернуть массив всех ваших документов. Следующим этапом в конвейере будет этап $unwind, где вы денормализуете этот массив. Оттуда используйте использование операторов $skip и $limit, соответственно пропустите первые 2 документа и передайте 3 документа на следующий этап, который является еще одним этапом $group.

db.collection.aggregate([ 
    { "$group": { 
     "_id": null, 
     "count": { "$sum": 1 }, 
     "docs": { "$push": "$$ROOT" } 
    }}, 
    { "$unwind": "$docs" }, 
    { "$skip": 2 }, 
    { "$limit": 3 }, 
    { "$group": { 
     "_id": "$_id", 
     "count": { "$first": "$count" }, 
     "docs": { "$push": "$docs" } 
    }} 
]) 

Как @JohnnyHK отметил в этом comment

$group будет читать все документы и построить 20k массив элементов с ними только, чтобы получить три документы.

Вы должны затем запустить два запроса с использованием find()

db.collection.find().skip(2).limit(3) 

и

db.collection.count() 
+3

Хорошие идеи, но что '$ group' собирается прочитать все документы и собрать массив элементов 20k с ними, чтобы получить три документа. Трудно поверить, что это было бы более эффективно, чем два запроса. – JohnnyHK

7

добавить .skip(2).limit(3) к концу вашего запроса

+0

Ах, спасибо за такой быстрый ответ. Итак, как я получаю общий результат? Я имею в виду, я хочу знать, сколько документов count form find() не запрашивает один и тот же параметр поиска дважды? – DennyHiu

+0

Я не уверен, что вы имеете в виду. вы хотите подсчитать, сколько результатов вы получили, ограничив набор результатов до 3? –

+0

Нет, я строю datatable (jquery datatable), и для этого требуется что-то вроде: var total = db.transaction.find(). Length; и var data = db.transaction.find(). skip (2) .limit (3). TOTAL и DATA - другая вещь. – DennyHiu