Как выбрать вложенные документы с помощью MongoDB
У меня есть коллекция с вложенным документом теги , такие как:
Collection News :
title (string)
tags: [tag1, tag2...]
Я хочу выбрать все теги, которые начинаются с шаблона, но возвращают только соответствующие теги.
Я уже использую регулярное выражение, но оно возвращает все новости, содержащие соответствующий тег, вот запрос:
db.news.find( {"tags":/^proga/i}, ["tags"] ).sort( {"tags":1} ).
limit( 0 ).skip( 0 )
Мой вопрос: как я могу получить все теги (только), которые соответствуют шаблону? (Конечная цель - создать поле автозаполнения)
Я также пытался использовать distinct, но не сделал этого найдите способ сделать различие с помощью find, он всегда возвращает мне все теги:(
Спасибо, что уделили мне время
2 answers
Встроенные документы не являются коллекциями. Посмотрите на свой запрос: db.новости. find вернет документы из коллекции news
. tags
не является коллекцией и не может быть отфильтрован.
Есть запрос на функцию для этой "функции виртуальной коллекции" (СЕРВЕР-142), но не ожидайте увидеть это слишком скоро, потому что это "запланировано, но не запланировано".
Вы можете выполнить фильтрацию на стороне клиента или переместить теги в отдельную коллекцию. Путем извлечения только подмножество полей - только поле tags
- это должно быть достаточно быстро.
Подсказка: Ваше регулярное выражение использует флаг /i
, что делает невозможным использование индексации. Ваши строки бд должны быть нормализованы по регистру (например, все в верхнем регистре)
Немного опоздал на вечеринку, но, надеюсь, поможет другим, кто ищет решение. Я нашел способ сделать это, используя структуру агрегации и объединив $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. Если кому-нибудь нужна версия узла, оставьте комментарий ниже, и я буду обязан.