web-dev-qa-db-ja.com

整数値でのMongoDB正規表現検索

MongoDBで整数値を正規表現で検索したい。これは可能ですか?

さまざまなフィールドでワイルドカードを使用できる*を許可するCRUDタイプのインターフェイスを構築しています。整数であるいくつかのフィールドのUIの一貫性を維持しようとしています。

考えてみましょう:

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

ご覧のとおり、オブジェクトを挿入すると、値で見つけることができます。単純な正規表現を試してみると、実際にはオブジェクトが見つかりません。

ありがとう!

23
Gary Richardson

数値のパターンマッチングを実行する場合、mongoでそれを実行する方法は、$ where式を使用して、パターンマッチを渡すことです。

> db.test.find({ $where: "/^123.*/.test(this.example)" })
{ "_id" : ObjectId("4bfc3187fec861325f34b132"), "example" : 1234 }
42
dalton

$where クエリ演算子は、クエリ式の評価方法、インデックスを使用しないため、クエリでユーザー入力を使用する場合のセキュリティリスクがあるため、私は大ファンではありません。データ。

MongoDB 4.2以降、MongoDB4.1.9以降で利用可能な$regexMatch|$regexFind|$regexFindAll$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演算子をstringify整数にラッパーする$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 して、数値の文字列値である別の計算フィールドを追加する必要があります。

$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"
}

さて、特定の部分文字列を含むすべてのドキュメントを取得することが必要な場合、これを行うためのより簡単でより良い方法は、 $redact$cond 基本的な論理処理を許可する演算子。$indexOfCP

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