MongoDB Regex Поиск по целочисленному значению - PullRequest
18 голосов
/ 26 мая 2010

Я хочу, чтобы регулярное выражение поиска целочисленного значения в MongoDB. Возможно ли это?

Я создаю интерфейс типа CRUD, который позволяет * подстановочные знаки в различных полях. Я пытаюсь сохранить согласованность пользовательского интерфейса для нескольких полей, которые являются целыми числами.

Рассмотрим:

> db.seDemo.insert({ "example" : 1234 });
> db.seDemo.find({ "example" : 1234 });
{ "_id" : ObjectId("4bfc2bfea2004adae015220a"), "example" : 1234 }
> db.seDemo.find({ "example" : /^123.*/ });
> 

Как видите, я вставляю объект и могу найти его по значению. Если я попробую простое регулярное выражение, я не смогу найти объект.

Спасибо!

Ответы [ 2 ]

40 голосов
/ 26 мая 2010

Если вы хотите выполнить сопоставление с образцом для чисел, способ сделать это в монго - использовать выражение $ where и передать сопоставление с образцом.

> db.test.find({ $where: "/^123.*/.test(this.example)" })
{ "_id" : ObjectId("4bfc3187fec861325f34b132"), "example" : 1234 }
8 голосов
/ 30 июля 2016

Я не большой поклонник использования оператора запроса $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, до stringify integer.

db.seDemo.aggregate([ 
    { "$redact": { 
        "$cond": [ 
            { "$gt": [ 
                { "$indexOfCP": [ 
                    { "$toString": "$example" }, 
                    "123" 
                ] }, 
                -1 
            ] }, 
            "$$KEEP", 
            "$$PRUNE" 
        ] 
    }}
])

Если вам нужно получить весь документ, который содержит определенную подстроку, начиная с версии 3.4, вы можете использовать оператор $redact, который позволяет использовать $cond itional логическая обработка. $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 вашего документа и добавить другое вычисляемое поле, которое является строковым значением вашего числа.

Операторы $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* Оператор 1076 *, который допускает обработку логической обработки $cond. $indexOfCP.

db.seDemo.aggregate([ 
    { "$redact": { 
        "$cond": [ 
            { "$gt": [ 
                { "$indexOfCP": [ 
                    { "$toLower": "$example" }, 
                    "123" 
                ] }, 
                -1 
            ] }, 
            "$$KEEP", 
            "$$PRUNE" 
        ] 
    }}
])
...