Как выбрать вложенные документы с помощью MongoDB


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

Collection News :
   title (string)
   tags: [tag1, tag2...]

Я хочу выбрать все теги, которые начинаются с шаблона, но возвращают только соответствующие теги.

Я уже использую регулярное выражение, но оно возвращает все новости, содержащие соответствующий тег, вот запрос:

db.news.find( {"tags":/^proga/i}, ["tags"] ).sort( {"tags":1} ).
    limit( 0 ).skip( 0 )

Мой вопрос: как я могу получить все теги (только), которые соответствуют шаблону? (Конечная цель - создать поле автозаполнения)

Я также пытался использовать distinct, но не сделал этого найдите способ сделать различие с помощью find, он всегда возвращает мне все теги:(

Спасибо, что уделили мне время

Author: Community, 2012-01-14

2 answers

Встроенные документы не являются коллекциями. Посмотрите на свой запрос: db.новости. find вернет документы из коллекции news. tags не является коллекцией и не может быть отфильтрован.

Есть запрос на функцию для этой "функции виртуальной коллекции" (СЕРВЕР-142), но не ожидайте увидеть это слишком скоро, потому что это "запланировано, но не запланировано".

Вы можете выполнить фильтрацию на стороне клиента или переместить теги в отдельную коллекцию. Путем извлечения только подмножество полей - только поле tags - это должно быть достаточно быстро.

Подсказка: Ваше регулярное выражение использует флаг /i, что делает невозможным использование индексации. Ваши строки бд должны быть нормализованы по регистру (например, все в верхнем регистре)

 10
Author: mnemosyn, 2012-01-14 13:38:29

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

    $ops = array(
        array('$match' => array(
                'collectionColumn' => 'value',
            )
        ),
        array('$project' => array(
                'collection.subcollection' => 1
            )
        ),
        array('$unwind' => '$subCollection'),
        array('$match' => array(
                subCollection.subColumn => 'subColumnValue'
            )
        )
    );

Первое совпадение и проект просто используются для фильтрации, чтобы сделать это быстрее, затем функция "размотка при вложенной коллекции" выплевывает каждый элемент вложенной коллекции по элементам, которые затем можно отфильтровать с помощью финальный матч.

Надеюсь, это поможет.

ОБНОВЛЕНИЕ (от Райана Уила):

Затем вы можете $group вернуть данные в исходную структуру. Это все равно, что иметь $elemMatch, который возвращает более одного вложенного документа:

array('$group' => array(
        '_id' => '$_id',
        'subcollection' => array(
            '$push' => '$subcollection'
        )
    )
);

Я перевел это с узла на PHP, поэтому я не тестировал на PHP. Если кому-нибудь нужна версия узла, оставьте комментарий ниже, и я буду обязан.

 13
Author: Marogian, 2014-05-25 06:34:43