2015-02-23 3 views
11

Я знаю, что MongoDB поддерживает синтаксис find{array.0.field:"value"}, но я специально хочу сделать это для последнего элемента в массиве, что означает, что я не знаю индекса. Для этого есть какой-то оператор, или мне не повезло?MongoDB - Запросить последний элемент массива?

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

+1

Как выглядят ваши документы? –

+0

Ну, массив, который я пытаюсь проверить, фактически вложен в другой массив, но я не думаю, что это должно иметь какой-то эффект. В основном, что я хочу сделать, в моем селекторе поиска только возвращать документы, где определенное поле в последнем элементе массива соответствует определенному значению. –

+0

Вы должны изучить [агрегацию] (http://docs.mongodb.org/manual/reference/operator/aggregation/), а затем играть с '$ unwind',' $ project', '$ match' и' $ group' –

ответ

10

Я отправил в официальную группу Mongo Google here и получил ответ от их сотрудников. Похоже, что то, что я ищу, невозможно. Я собираюсь использовать другой подход к схеме.

5

$ slice.

db.collection.find({}, { array_field: { $slice: -1 } }) 

Редактирование: Вы можете использовать { <field>: { $elemMatch: { <query1>, <query2>, ... } } }, чтобы найти соответствие.

Но он не даст точно то, что вы ищете. Я не думаю, что это возможно в mongoDB.

+0

Это просто возвращает последний элемент, не так ли? Это не то, что я пытаюсь сделать.Я хочу, чтобы мой find selector возвращал документы, в которых последний элемент массива соответствует определенному значению. –

+0

Добавлено обновление после редактирования. – Kaushal

4

Вы можете использовать $position: 0 всякий раз, когда вы $push, а затем всегда запрашиваете array.0, чтобы получить последний добавленный элемент. Конечно, тогда вы не сможете получить новый «последний» элемент.

+0

Я думал об этом, но мое приложение обращается к Mongo с использованием Spring Data, которое в то время не поддерживало нажатие на фронт массива. Не уверен, что это происходит сейчас. –

6

Не уверен, что о производительности, но это работает хорошо для меня:

db.getCollection('test').find(
    { 
    $where: "this.someArray[this.someArray.length - 1] === 'pattern'" 
    } 
) 
+0

$ где очень медленно, потому что он работает javascript – eagleeye

+0

Большое спасибо! Может быть, это не самое эффективное решение, но для меня это как шарм. Не так медленно для моих данных, возможно, это различие в производительности ощутимо только в больших наборах данных. –

9

В 3.2 это возможно. Первый проект, так что myField содержит только последний элемент, а затем сопоставляется с myField.

db.collection.aggregate([ 
    { $project: { id: 1, myField: { $slice: [ "$myField", -1 ] } } }, 
    { $match: { myField: "myValue" } } 
]); 
+0

Да в mongodb 3.2 работает. – Kiran

+0

в 3.2 существует оператор $ arrayElemAt, который работает с отрицательными индексами. поэтому вместо этого может быть '{$ project: {id: 1, myField: {$ arrayElemAt: [" $ myField ", -1]}}}'. Я не знаю, эффективен ли только один элемент с одним элементом – makhdumi

+0

Это выводит именно то, что нужно. –

0

Вы можете использовать $expr (3,6 Монго версии оператора), чтобы использовать функции агрегации в обычном запросе.

query operators vs aggregation comparison operators.

Для скалярных массивов

db.col.find({$expr:{$gt:[{$arrayElemAt:["array", -1]}, value]}}) 

Для встроенных массивов - Использование $let выражения для проецирования последнего элемента с точечной нотации для доступа к значению поля.

db.col.find({$expr:{$gt:[{$let:{vars:{obj:{"$arrayElemAt": ["$array", 0]}},in: "$$obj.field"}}, value]}}) 

Пружина @Query код

@Query("{$expr:{$gt:[{$arrayElemAt:[\"array\", -1]}, ?0]}}") 
ReturnType MethodName(ArgType arg); 
0

версия 3.6 агрегации использование для достижения того же.

db.getCollection('deviceTrackerHistory').aggregate([ 
    { 
    $match:{clientId:"12"} 
    }, 
    { 
    $project: 
     { 
     deviceId:1, 
     recent: { $arrayElemAt: [ "$history", -1 ] } 
     } 
    } 
]) 
Смежные вопросы