Поиск регулярного выражения MongoDB по целочисленному значению
Я хочу, чтобы регулярное выражение искал целочисленное значение в MongoDB. Возможно ли это?
Я создаю интерфейс типа CRUD, который позволяет * для подстановочных знаков в разных полях. Я стараюсь, чтобы пользовательский интерфейс был согласован для нескольких полей, которые являются целыми числами.
Рассмотрим:
> db.seDemo.insert({ "example" : 1234 });
> db.seDemo.find({ "example" : 1234 });
{ "_id" : ObjectId("4bfc2bfea2004adae015220a"), "example" : 1234 }
> db.seDemo.find({ "example" : /^123.*/ });
>
Как вы можете видеть, я вставляю объект, и я могу найти его по значению. Если я попробую простое регулярное выражение, я не могу найти объект.
Спасибо!
Ответы
Ответ 1
Если вы хотите выполнить сопоставление шаблонов по номерам, способ сделать это в mongo - использовать выражение $where и передать шаблон.
> db.test.find({ $where: "/^123.*/.test(this.example)" })
{ "_id" : ObjectId("4bfc3187fec861325f34b132"), "example" : 1234 }
Ответ 2
Я не большой поклонник использования оператора запроса $where
из-за того, как он оценивает выражение запроса, он не использует индексы и угрозу безопасности, если запрос использует пользовательские входные данные.
Начиная с MongoDB 4.2 вы можете использовать $regexMatch|$regexFind|$regexFindAll
доступный в MongoDB 4.1. 9+, и $expr
для этого.
let regex = /123/;
-
$regexMatch
и $regexFind
db.col.find({
"$expr": {
"$regexMatch": {
"input": {"$toString": "$name"},
"regex": /123/
}
}
})
-
$regexFinAll
db.col.find({
"$expr": {
"$gt": [
{
"$size": {
"$regexFindAll": {
"input": {"$toString": "$name"},
"regex": "123"
}
}
},
0
]
}
})
В MongoDB 4.0 вы можете использовать оператор $toString
который является оберткой вокруг оператора $convert
для строкового $convert
целых чисел.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toString": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])
Если вам нужно получить весь документ, который содержит определенную подстроку, начиная с версии 3.4, вы можете использовать оператор $redact
который разрешает обработку логической переменной $cond
. $indexOfCP
.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toLower": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])
который производит:
{
"_id" : ObjectId("579c668c1c52188b56a235b7"),
"example" : 1234
}
{
"_id" : ObjectId("579c66971c52188b56a235b9"),
"example" : 12334
}
До MongoDB 3.4 вам необходимо $project
ваш документ на $project
и добавить другое вычисляемое поле, которое является строковым значением вашего числа.
Операторы $toLower
и его родственные $toUpper
соответственно преобразуют строку в строчные и прописные буквы, но у них есть небольшая неизвестная особенность, заключающаяся в том, что их можно использовать для преобразования целого числа в строку.
Оператор $match
возвращает все те документы, которые соответствуют вашему шаблону, используя оператор $regex
.
db.seDemo.aggregate(
[
{ "$project": {
"stringifyExample": { "$toLower": "$example" },
"example": 1
}},
{ "$match": { "stringifyExample": /^123.*/ } }
]
)
который дает:
{
"_id" : ObjectId("579c668c1c52188b56a235b7"),
"example" : 1234,
"stringifyExample" : "1234"
}
{
"_id" : ObjectId("579c66971c52188b56a235b9"),
"example" : 12334,
"stringifyExample" : "12334"
}
Теперь, если вам нужно получить весь документ, который содержит определенную подстроку, проще и лучше сделать это в следующей версии MongoDB (на момент написания этой статьи) с использованием оператора $redact
который допускает логику $cond
itional обработка. $indexOfCP
.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toLower": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])