MongoDB: используйте позиционный оператор $ для запросов

У меня есть коллекция с записями, которые выглядят так:

{
    "userid": 1, 
    "contents": [ 
            { "tag": "whatever", "value": 100 }, 
            {"tag": "whatever2", "value": 110 } 
    ] 
}

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

Вот точнее, что я хотел бы сделать:

collection.find({'contents.tag':"whatever"},{'contents.$.value':1})

В результате я ожидаю sth только со значением, соответствующим записи в массиве, который соответствует запросу, что в данном случае равно 100.

Вы знаете, что случилось? Я подумал, что, возможно, оператор $ можно использовать только для обновления, а не для запросов. Кто-нибудь в курсе?

Спасибо !


person Johanisma    schedule 08.06.2011    source источник
comment
Просто для того, чтобы вернуть только ваше поле значения, будет достаточно collection.find({'contents.tag':'whatever'},{'contents.value':1}) и не нужен позиционный оператор. Тем не менее (как уже упоминал Райан в своем ответе) необходимо вытащить поле из возвращаемого массива (который также будет включать _id документа) на стороне приложения. Недостатком является тот факт, что findOne или limit(1) относительно вашего вложенного массива не будут работать, что не будет проблемой, если вы не ожидаете более 1 результата.   -  person proximus    schedule 08.06.2011


Ответы (4)


Да, вы правы - позиционный оператор используется для обновления объекта.

Решение на данный момент состоит в том, чтобы вернуть массив и вытащить поле из вашего приложения.

Существует открытый запрос на улучшение этой функции (в запросах):

https://jira.mongodb.org/browse/SERVER-828

Для получения дополнительной информации о позиционном операторе см.:

http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator< /а>

person Ryan    schedule 08.06.2011
comment
Да спасибо за ответ. Я думаю, мне придется сделать это на стороне приложения сейчас! Это довольно странно, потому что, если они реализованы для обновления, это не должно сильно отличаться для поиска... В любом случае, надеюсь, что эта функция скоро появится! - person Johanisma; 09.06.2011
comment
Согласен... пожалуйста, проголосуйте за проблему в Jira, чтобы помочь включить ее в продукт. - person Ryan; 10.06.2011
comment
Видимо не реализовано :(, предлагают использовать $elemMatch . - person MaicolBen; 27.03.2014

Вам нужен оператор $elemMatch. .

person Aidamina    schedule 24.06.2012
comment
Не могли бы вы подробнее рассказать о том, как в этом случае можно использовать $elemMatch для возврата только части совпадающего объекта в массиве? - person gaurav5430; 29.08.2017

Это может быть излишним, но я думаю, вы можете использовать для этого уменьшение карты.

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

Если вам приходится часто выполнять подобные запросы, возможно, стоит дублировать данные.

Тем не менее, я надеюсь, что SERVER-828 скоро будет реализован!

person Laura    schedule 23.08.2011

Вместо этого создайте запрос с $in и добавьте равное значение в массив, это может решить вашу проблему.

$users_array = array(xxxxxxxx,yyyyyy);     
$user = Db::find('fb_users', array(
                            'facebook_id' => array(
                                '$in' => array($users_array)
                            )
                        ));
person Liad Livnat    schedule 24.07.2013