Обновленный ответ:
Как я понял, вы хотели реализовать функцию поиска, тогда вы можете посмотреть текстовый индекс в MongoDB, который специально реализован для текстовый поиск. Из моего опыта реализации текстовых поисков, таких как нечеткий / частичный / полный текст / диакритический знак / нечувствительный к регистру текстовый поиск очень полезен.
Так что я бы предложил, так как вы ' при поиске по двум полям f
& l
- я бы порекомендовал объединить два в одно поле fl
и создать для него текстовый индекс таким образом, чтобы ваши запросы предназначались для одного поля, которое более эффективно для поисковых запросов. Проверьте ниже рекомендации:
Шаг 1: В случае, если вы не создали объединенное поле, вы можете сделать это сейчас с помощью этого запроса к MongoDB v >=4.2
(В более низкой версии вам нужно найти способ выполните либо Read Coll & update field
или use aggregation + $out
):
db.collection.update({},[{$addFields : {'fl': { $concat: [ "$f", " ", "$l" ] }}}],{multi:true})
Шаг 2: Создание текстового индекса в поле fl
:
db.collection.createIndex( { fl: "text" } )
Шаг 3: Вы можете выполнять поиск, как показано ниже, Дополнительная проекция {fl :0}
для удаления fl
поля в ответ.
db.collection.find( { $text: { $search: "Paul Green" } }, {fl :0} )
Примечание: Теперь вы можете получить все документы, в которых f
или l
имеет Paul или Green или PAUL или GREEN или PAUL GREEN или Greèn или PAU или Pau или Gre или GRE , так что большая часть этого разбирается. Если вы не изучаете текстовый поиск, вы по-прежнему изучаете следующий подход.
Фактический ответ:
Обычно, когда вы хотите проверить существующее входное значение в строковом поле - вы бы использовали выражения регулярных выражений для получения отфильтрованных документов.
Но если вы хотите передать строку 'Paul Green'
и проверить, что поле является подстрокой ввода, то обычное регулярное выражение вам не поможет. Но если вы используете MongoDB версии 4.2
, вы можете сделать несколько вещей, как показано ниже:
Запрос 1:
db.collection.aggregate([
/** Add a field which will be true if any of the field 'f' or 'l' is a sub-string of input (Case-insensitive) */
{
$addFields: {
result: {
$or: [
{ $regexMatch: { input: "Paul Green", regex: "$f", options: "i" } }, /** Usually input is field & regex is actual input value, we tricked it for our requirement */
{ $regexMatch: { input: "Paul Green", regex: "$l", options: "i" } }
]
}
}
},
/** Filter for all docs where result field is true (Which leave docs where 'f' or 'l' is sub-string) */
{ $match: { result: true } },
/** Remove added field result */
{ $project: { result: 0 } }
]);
Тест: MongoDB-Playground
Примечание: Вышеупомянутый запрос будет работать, даже если отправить входную строку, например 'PaulGreen'
, но недостатком будет то, что он не даст вам результаты как Вы хотите сделать: поиск, как pele даст мне pelè , потому что, если вы хотите получить такие данные, вам нужно использовать параметры сортировки, которые нельзя использовать, если мы используем $ regexMatch . Итак, основываясь на ваших данных, вы можете сделать следующее:
Запрос 2:
Разделить строку на основе пробелов ['Paul', 'Green'] & передать запрос:
db.collection.aggregate(
/** Filter docs if any of the word exists in any of the fields 'f' or 'l' */
[
{
$match: {
$or: [
{ f: { $in: ["Paul", "Green"] } },
{ l: { $in: ["Paul", "Green"] } }
]
}
}
],
{ collation: { locale: "fr", strength: 1 } } // Applied collation ignores case & diacritics
);
Примечание: Вышеупомянутый запрос может в основном выполнить вашу работу с версиями MongoDB> 3.4
, но не будет работать, если вы хотите выполнить поиск что-то вроде 'PaulGreen'
, По какой-то причине сортировка этого запроса не работает на площадке mongodb - пожалуйста, проверьте его на реальной базе данных.