У меня есть этот документ Mongo
{
_id: ObjectId('6616851ed50d6d1451fa8176'),
phone: "+7(926)458-54-52",
name: "Aboba"
}
Я хочу найти этот документ, если пользователь вводит 7926, но мой фильтр фильтрует и другое поле.
Я фильтрую по регулярному выражению телефона или имени, но телефон содержит «+» и «()», поэтому, если пользовательский ввод равен 7926, он не будет найден.
Как я могу это решить?
Мое регулярное выражение:
{'$regex': f'\\w*{request_value}\\w*', '$options': 'i'}
Я фильтрую так:
{$or: [name: regex, phone: regex}

Вы можете создать очищенную строку с именем phoneForSearch, сначала удалив все специальные символы. Затем используйте поиск по регулярному выражению на phoneForSearch.
db.collection.aggregate([
{
"$set": {
"phoneForSearch": {
"$reduce": {
"input": {
"$regexFindAll": {
"input": "$phone",
"regex": "\\d+"
}
},
"initialValue": "",
"in": {
"$concat": [
"$$value",
"$$this.match"
]
}
}
}
}
},
{
"$match": {
$expr: {
$or: [
// phone search
{
$ne: [
-1,
{
"$indexOfCP": [
"$phoneForSearch",
//user input here
"7926"
]
}
]
},
// name search
{
"$regexMatch": {
"input": "$name",
// name regex here
"regex": "^abo",
"options": "i"
}
}
]
}
}
}
])
Рекомендуется «разбить» поле phone на отдельные поля, чтобы его было легче обрабатывать и форматировать следующим образом:
[
{
_id: ObjectId("6616851ed50d6d1451fa8176"),
phone: {
countryCode: "7",
areaCode: "926",
number: "4585452"
},
name: "Aboba"
}
]
+1 к созданию очищенного строкового поля. В вашей ситуации я бы использовал этот ответ. Создайте это поле для всех документов отдельно, а также для новых вставок и обновлений. А затем используйте для этого регулярное выражение.
Ответ анероида @Zessshi должен быть тем, который непосредственно касается вашего вопроса, и я рад, что это принятое решение. Я просто хочу подчеркнуть использование создания вспомогательного поля поиска (то есть очищенного phoneForSearch в моем ответе). Если вы часто выполняете такой поиск, вы можете рассмотреть возможность материализации поля (т. е. сохранить его в базе данных) и проиндексировать его. Таким образом, вы можете получить потенциальный выигрыш в производительности.
Во-первых, я согласен с ответом Рэя.
создайте очищенную строку с именем
phoneForSearch
Это позволит вам также лучше индексировать и искать по нему.
Однако, если вы действительно хотите просто игнорировать специальные символы, вы можете сделать что-то вроде этого:
Для номеров телефонов отделяйте каждую цифру знаком \D*, который означает «одна или несколько нецифр». Сначала добавьте \D между всеми цифрами в вашем приложении/коде, а затем выполните поиск, используя его в качестве регулярного выражения. Таким образом, поиск 7926 по нечистому номеру телефона можно выполнить следующим образом:
db.collection.find({
phone: {
$regex: "\\D*7\\D*9\\D*2\\D*6\\D*",
$options: "i"
}
})
Это также соответствует другим нечисловым значениям, например:
+7(926)458-54-52
+7===+++|||9....2++++6458-54-52
+7ssss9xxxx2yyyy6dddd-458-54-52
+7===+++|||9....2++++6458-54-52
вот почему лучше НЕ делать что-то подобное. Игровая площадка Монго
И если вы хотите обработать эту вставку \D в Mongo, вы можете сделать это следующим образом:
(обновление)
Это все, что мне удалось сделать с вставкой \D в регулярное выражение поиска по телефону, но это не работает, когда шаблон регулярного выражения является именем поля: $regex: "$phone_search_regex". mongoplayground.net/p/RxZZPGYPM89
\\w*{request_value}\\w*Итак, нет возможности не исключать специальные символы из этого регулярного выражения, да? Его можно дополнить дополнительными полями?