Как выбрать субдокументы с помощью MongoDB
У меня есть коллекция с такими поддокументами, как:
Collection News :
title (string)
tags: [tag1, tag2...]
Я хочу выбрать все теги, которые начинают с шаблона, но возвращают только теги соответствия.
Я уже использую регулярное выражение, но он возвращает все новости, содержащие соответствующий тег, вот запрос:
db.news.find( {"tags":/^proga/i}, ["tags"] ).sort( {"tags":1} ).
limit( 0 ).skip( 0 )
Мой вопрос: как я могу получить все теги (только), которые соответствуют шаблону?
(Конечная цель - создать поле автозаполнения)
Я также пробовал использовать разные, но я не нашел способ сделать отчетливым с помощью find, он всегда возвращает мне все теги: (
Спасибо за ваше время
Ответы
Ответ 1
Встроенные документы не являются коллекциями. Посмотрите на свой запрос: db. news.find вернет документы из коллекции news
. tags
не является коллекцией и не может быть отфильтрован.
Есть запрос функции для этой "функции виртуальной коллекции" (SERVER-142), но не ожидайте увидеть это слишком рано, потому что он "запланирован, но не запланирован".
Вы можете выполнить фильтрацию на стороне клиента или переместить теги в отдельную коллекцию. извлекает только подмножество полей - только поле tags
- это должно быть достаточно быстро.
Совет. В вашем регулярном выражении используется флаг /i
, что делает невозможным использование индексации. Строки вашего db должны быть нормализованы (например, весь верхний регистр)
Ответ 2
Немного поздно для вечеринки, но, надеюсь, поможет другим, которые ищут решение. Я нашел способ сделать это, используя структуру агрегации и объединив $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'
)
)
);
Первое совпадение и проект просто используются, чтобы отфильтровать, чтобы сделать это быстрее, затем разматывание на субколлекции выплескивает каждый элемент субколлекции по элементу, который затем может быть отфильтрован с использованием финального соответствия.
Надеюсь, что это поможет.
ОБНОВЛЕНИЕ (от Ryan Wheale):
Вы можете вернуть $group
данные в свою первоначальную структуру. Это похоже на $elemMatch
, который возвращает более одного поддокумента:
array('$group' => array(
'_id' => '$_id',
'subcollection' => array(
'$push' => '$subcollection'
)
)
);
Я перевел это с Node на PHP, поэтому я не тестировал его на PHP. Если кто-то хочет версию Node, оставьте комментарий ниже, и я обяжусь.