Mongodbで大文字と小文字を区別しないクエリを作成するにはどうすればよいですか?


95
var thename = 'Andrew';
db.collection.find({'name':thename});

大文字と小文字を区別しないクエリを実行するにはどうすればよいですか?「アンドリュー」でも結果を見つけたい。



正規表現を含む回答を使用しようとするすべての人への注意:正規表現はサニタイズする必要があります。
ショーン

回答:


128

Chris Fulstowのソリューションは機能します(+1)が、特にコレクションが非常に大きい場合は、効率的でない可能性があります。ルート化されていない正規表現(^正規表現を文字列の先頭に固定する、で始まらiないもの)、および大文字と小文字を区別しないフラグを使用するものは、インデックスが存在する場合でも使用しません。

検討する可能性のある別のオプションは、データを非正規化して、nameフィールドの小文字バージョン(たとえば、)を格納することname_lowerです。次に、次のような大文字と小文字を区別しない完全一致について、効率的に(特にインデックスが付けられている場合)クエリを実行できます。

db.collection.find({"name_lower": thename.toLowerCase()})

または、次のようにプレフィックス一致(ルート化された正規表現)を使用します。

db.collection.find( {"name_lower":
    { $regex: new RegExp("^" + thename.toLowerCase(), "i") } }
);

これらのクエリは両方とも、のインデックスを使用しますname_lower


1
素晴らしい答えです。数百万のドキュメントをスキャンする必要があると、私の正規表現のアプローチは本当に遅くなります。
クリスフルストウ2011

35
「アンドリュー」を探しているときに「アンドリュー何か」が見つかる可能性があるため、これは実際には完全には正しくありません。したがって、正規表現を次のnew RegExp('^'+ username + '$', "i")ように調整して、完全に一致させます。
タリオン2014年

9
MongoDB Webサイトによると、大文字と小文字を区別しない正規表現はインデックス効率が良くありません。「$ regexは、正規表現に文字列の先頭(^)のアンカーがあり、大文字と小文字が区別される一致である場合にのみ、インデックスを効率的に使用できます」
Ryan Schumacher

2
Mongooseでは、これは私のために機能しました:User.find({'username':{$ regex:new RegExp( '^' + username.toLowerCase()、 'i')}}、function(err、res){if(err )throw err; next(null、res);});
ChrisRich 2014年

5
正規表現を使用する場合は、名前をエスケープすることを忘れないでください。注射でmongodbの美しさを引き継ぐことは望んでいません。このコードをログインページに使用し、ユーザー名がであったと想像してみてください".*"
トビアス

91

あなたは、大文字と小文字を区別しない使用する必要があるだろう正規表現など、この1のために

db.collection.find( { "name" : { $regex : /Andrew/i } } );

thename変数から正規表現パターンを使用するには、新しいRegExpオブジェクトを作成します。

var thename = "Andrew";
db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );

更新:完全に一致させるには、正規表現を使用する必要があります"name": /^Andrew$/i。YannickLに感謝します。


7
Node.jsマングースを使用してこれを行う方法を知っていますか?
user847495 2011

1
これは大規模なコレクションでどれほどうまく機能するのだろうか。ある種の機能の利点を失うことになります
Wilfred Springer

5
これは間違っています。等しいだけでなく、の「アンドリュー」を含むすべてのドキュメントに一致しますname
ジョナサンクレミン2014

14
:あなたが正しい答え投稿する必要があり、ヘルプの人々に@JonathanCremin{ "name": /^Andrew$/i }
ヤニックLoriot

@YannickL。常識的なことをするための1+。探していたものではなく、通りかかったところです。
lpc_dark 2015

39

私はこのようにそれを解決しました。

 var thename = 'Andrew';
 db.collection.find({'name': {'$regex': thename,$options:'i'}});

'大文字と小文字を区別しない完全一致'についてクエリを実行する場合は、次のように実行できます。

var thename =  '^Andrew$';
db.collection.find({'name': {'$regex': thename,$options:'i'}});

8
  1. マングース(およびノー​​ド)では、これは機能しました:

    • User.find({ email: /^name@company.com$/i })

    • User.find({ email: new RegExp(`^ $ {emailVariable} $`、 'i')})

  2. MongoDBでは、これは機能しました:

    • db.users.find({ email: { $regex: /^name@company.com$/i }})

どちらの行も大文字と小文字は区別されません。DB内の電子メールは可能性がNaMe@CompanY.Comあり、両方の行は引き続きDB内のオブジェクトを検索します。

同様に、使用/^NaMe@CompanY.Com$/iすることもできますname@company.comが、DB内に電子メールが見つかります。


7

MongoDB 3.4には、真の大文字と小文字を区別しないインデックスを作成する機能が含まれるようになりました。これにより、大規模なデータセットで大文字と小文字を区別しないルックアップの速度が大幅に向上します。強度2の照合順序を指定して作成されます。

おそらくそれを行う最も簡単な方法は、データベースに照合を設定することです。次に、すべてのクエリがその照合を継承し、それを使用します。

db.createCollection("cities", { collation: { locale: 'en_US', strength: 2 } } )
db.names.createIndex( { city: 1 } ) // inherits the default collation

次のようにすることもできます。

db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});

そして、次のように使用します。

db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});

これにより、「ニューヨーク」、「ニューヨーク」、「ニューヨーク」などの名前の都市が返されます。

詳細については、https//jira.mongodb.org/browse/SERVER-90をご覧ください。


強度:1は、大文字と小文字を区別せず、発音区別符号を区別しないインデックス付けには1で十分です。docs.mongodb.com/manual/reference/collat​​ion
GauravRagtah20年


4

私は数時間前にこの問題を解決しました。

var thename = 'Andrew'
db.collection.find({ $text: { $search: thename } });
  • この方法でクエリを実行すると、大文字と小文字の区別と発音区別符号の感度がデフォルトでfalseに設定されます。

Andrewのユーザーオブジェクトから必要なフィールドを次のように選択することで、これを拡張することもできます。

db.collection.find({ $text: { $search: thename } }).select('age height weight');

参照:https//docs.mongodb.org/manual/reference/operator/query/text/#text


1
$ textは、テキストインデックスでインデックス付けされたフィールドのコンテンツに対してテキスト検索を実行します。
SSHこの

4

...クエリするNodeJSのマングースで:

const countryName = req.params.country;

{ 'country': new RegExp(`^${countryName}$`, 'i') };

または

const countryName = req.params.country;

{ 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };

// ^australia$

または

const countryName = req.params.country;

{ 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };

// ^turkey$

Javascriptの完全なコード例、MongoDB上のMongooseORMを使用したNodeJS

// get all customers that given country name
app.get('/customers/country/:countryName', (req, res) => {
    //res.send(`Got a GET request at /customer/country/${req.params.countryName}`);

    const countryName = req.params.countryName;

    // using Regular Expression (case intensitive and equal): ^australia$

    // const query = { 'country': new RegExp(`^${countryName}$`, 'i') };
    // const query = { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };
    const query = { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };

    Customer.find(query).sort({ name: 'asc' })
        .then(customers => {
            res.json(customers);
        })
        .catch(error => {
            // error..
            res.send(error.message);
        });
});

2

大文字と小文字を区別しないインデックスを使用できます。

次の例では、デフォルトの照合順序を使用せずにコレクションを作成し、大文字と小文字を区別しない照合順序を使用して名前フィールドにインデックスを追加します。Unicodeの国際コンポーネント

/*
* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of 
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary 
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )

インデックスを使用するには、クエリで同じ照合順序を指定する必要があります。

db.users.insert( [ { name: "Oğuz" },
                            { name: "oğuz" },
                            { name: "OĞUZ" } ] )

// does not use index, finds one result
db.users.find( { name: "oğuz" } )

// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )

// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )

または、デフォルトの照合順序でコレクションを作成できます。

db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } )
db.users.createIndex( { name : 1 } ) // inherits the default collation

1

次のクエリは、必要な文字列を使用せず、グローバルに出現するドキュメントも検索します。

db.collection.find({name:{
                             $regex: new RegExp(thename, "ig")
                         }
                    },function(err, doc) {
                                         //Your code here...
                  });

1

大文字と小文字を区別しないリテラル文字列を検索するには:

正規表現の使用(推奨)

db.collection.find({
    name: {
        $regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')
    }
});

小文字のインデックスを使用する(より高速)

db.collection.find({
    name_lower: name.toLowerCase()
});

正規表現は、リテラル文字列照合よりも低速です。ただし、小文字のフィールドを追加すると、コードが複雑になります。疑わしい場合は、正規表現を使用してください。フィールドを置き換えることができる場合、つまり、そもそも大文字と小文字を気にしない場合にのみ、明示的に小文字のフィールドを使用することをお勧めします。

正規表現の前に名前をエスケープする必要があることに注意してください。ユーザー入力のワイルドカード.replace(/%/g, '.*')が必要な場合は、「a%」に一致して「a」で始まるすべての名前を検索できるように、エスケープ後に追加することをお勧めします。


-3

簡単な方法は、以下のように$ toLowerを使用することです。

db.users.aggregate([
    {
        $project: {
            name: { $toLower: "$name" }
        }
    },
    {
        $match: {
            name: the_name_to_search
        }
    }
])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.