Как выбрать поддокументы с MongoDB - PullRequest
11 голосов
/ 14 января 2012

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

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

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

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

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

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

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

Спасибо за ваше время

Ответы [ 2 ]

13 голосов
/ 04 января 2013

Немного опоздал на вечеринку, но, надеюсь, поможет другим, кто ищет решение.Я нашел способ сделать это, используя структуру агрегации и комбинируя $ 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'
        )
    )
);

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

10 голосов
/ 14 января 2012

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

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

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

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

...