2014-09-04 3 views
0

После конвейера агрегации я получаю список объектов, но нет способа получить N-й объект.Как получить доступ к определенному элементу после агрегации в mongodb?

См:

http://docs.mongodb.org/manual/reference/operator/aggregation/group/#retrieve-distinct-values 

Док имеет выход так:

{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") } 
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") } 
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") } 
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") } 
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") } 

Это группа объектов, но нет в списке, так что вы не можете делать такие вещи, как :

Результаты [1], чтобы получить второй объект. Как вы должны взаимодействовать с этой группой?

ответ

0

Прежде всего, если вы используете функцию db.collection.distinct(<fieldname>), вы можете получить различные значения поля в виде массива:

> db.animals.distinct("call") 
["moo", "baa", "woof", "meow", "quack"] 

, а затем вы можете разыменования результата, так как это массив.

> calls = db.animals.distinct("call") 
> calls[3] 
"meow" 

Агрегирование для различных значений свободно от большого ограничения db.collection.distinct() в том, что она возвращает курсор над различными значениями вместо большого массива, а это значит, что нет никакого предела 16MB BSON и отчетливая функция может использовать индексы для покрытия операции. Поэтому используйте подход агрегирования, когда у вас есть gazillion различные значения, но в противном случае используйте определенную функцию. Пока вы можете вызвать .toArray() на курсор и получить все результаты в массиве, если у вас так много результатов, что вы не могли использовать db.collection.distinct(), тогда это плохая идея. Вы должны перебрать курсор и выбрать те значения, которые вы хотите, и делать вещи с ними:

> var k = 0 
> var calls = db.animals.aggregate(<pipeline for distinct animal calls>) 
> while (calls.hasNext()) { 
    var call = calls.next() 
    k++ 
    if (k == 96) doStuff(call) 
} 

Вы можете вставить $skip этап в трубопроводе, чтобы сервер сразу перейти к первому результату, который вы хотите, если вы также включили $sort, чтобы исправить заказ, в котором будут возвращены результаты. Если вы знаете, что хотите только до определенной суммы, вы также можете использовать $limit, а затем можно будет снова использовать подход .toArray().

0

Перед тем как MongoDB 2.6 результаты агрегированного метода были возвращены как единый документ с результатами, помещенными в массив. Это изменилось с учетом больших наборов результатов, которые превысят предел BSON на 16 МБ, который был ограничен этой формой. Курсор, который возвращается теперь, фактически является опцией, но включен по умолчанию в оболочке.

Если ваши результаты невелики, на самом деле существует «вспомогательный» метод для .toArray(), который просто делает то, что вы хотите, поворачивая результаты курсора в массив. Это делает курсор итерацию под капотом, но в основном просто скрывает, что от вас:

var results = db.collection.aggregate(pipeline).toArray() 

Тогда просто доступ к элементу, это массив так n-1:

var result = results[8]; 

Подобные методы доступны для большинства водителей, или иначе в драйвере не включается опция «курсор».

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