Ответ 1
В настоящее время оператор $slice
недоступен в операции $project
конвейера агрегации.
Итак, что вы можете сделать,
Сначала $unwind
, массив my_field
, а затем сгруппируйте их вместе и возьмите элемент $first
группы.
db.my_collection.aggregate([
{$unwind:"$my_field"},
{$group:{"_id":"$_id","resp":{$first:"$my_field"}}},
{$project:{"_id":0,"resp":1}}
])
Или используя команду find()
, где вы можете использовать оператор $slice в части projection
.
db.my_collection.find({},{"my_field":{$slice:1}})
Обновить: на основе ваших комментариев. Скажем, вы хотите только элемент second
в массиве, для записи с идентификатором, id
.
var field = 2;
var id = ObjectId("...");
Затем команда ниже агрегации дает вам 2-й элемент в массиве my_field
записи с _id
, id
.
db.my_collection.aggregate([
{$match:{"_id":id}},
{$unwind:"$my_field"},
{$skip:field-1},
{$limit:1}
])
Вышеупомянутая логика не может применяться для большей записи, так как она будет включать оператор $group
после $unwind
. Оператор $group
создает одну запись для всех записей в этой конкретной группе, что делает операторы $limit
или $skip
, примененные на последующих этапах, неэффективными.
Небольшая вариация в запросе find()
выше привела бы к ожидаемому результату.
db.my_collection.find({},{"my_field":{$slice:[field-1,1]}})
Кроме того, всегда есть способ сделать это на стороне клиента, хотя и немного дорого, если количество записей очень велико:
var field = 2;
db.my_collection.find().map(function(doc){
return doc.my_field[field-1];
})
Выбор из указанных выше параметров зависит от размера ваших данных и дизайна приложения.