例:
> db.stuff.save({"foo":"bar"});
> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
regex を使うことができます。
あなたの例ではそれは以下のようになります。
db.stuff.find( { foo: /^bar$/i } );
ただし、値を見つけるたびに追加料金が発生するのではなく、途中で値を小文字(または大文字)に変換することもできます。明らかにこれは人々の名前などには有効ではありませんが、おそらくタグのようなユースケースです。
更新:
元の答えは今では時代遅れです。 Mongodbは現在、多くの機能を備えた高度な全文検索をサポートしています。
元の答え:
正規表現の大文字と小文字を区別しないで/ iで検索すると、mongodbはインデックスで検索できないため、大きなデータセットに対するクエリには長時間かかることがあります。
小さなデータセットでも、それほど効率的ではありません。クエリの保証よりもはるかに大きいCPUヒットを受けます。これは、スケールを達成しようとしている場合に問題になる可能性があります。
代わりに、大文字のコピーを保存してそれを検索することもできます。たとえば、大文字と小文字が混在するユーザー名を持つUserテーブルがありますが、idはユーザー名の大文字のコピーです。これは大文字と小文字を区別する複製が不可能であることを保証します( "Foo"と "foo"の両方を持つことは許されないでしょう)。
メッセージ本文のようにフィールドが大きい場合は、データを複製することはおそらくお勧めできません。その場合は、Apache Luceneのような無関係のインデクサーを使用するのが最善の選択肢だと思います。
前の例は次の点に注意してください。
db.stuff.find( { foo: /bar/i } );
barを含むすべてのエントリがクエリ(bar1、barxyz、openbar)と一致するようになります。auth関数でのユーザー名検索では非常に危険です。 ..
次のように適切な正規表現構文を使用して、検索語のみに一致させる必要があるかもしれません。
db.stuff.find( { foo: /^bar$/i } );
正規表現の構文ヘルプについては、 http://www.regular-expressions.info/ を参照してください。
あなたが変数から正規表現を作成する必要があるなら、これはそれをするためのはるかに良い方法です: https://stackoverflow.com/a/10728069/309514
その後、次のようにすることができます。
var string = "SomeStringToFind";
var regex = new RegExp(["^", string, "$"].join(""), "i");
// Creates a regex of: /^SomeStringToFind$/i
db.stuff.find( { foo: regex } );
これは、よりプログラム的になるという利点があります。あるいは、再利用する場合は、事前にコンパイルすることでパフォーマンスを向上させることができます。
MongoDB以降、大文字と小文字を区別しないで高速検索を実行するための推奨される方法は、大文字と小文字を区別しないインデックスを使用することです。
私は創設者の一人に個人的に電子メールを送ってこれを機能させてください、そして彼はそれを実現させました!それは 2009年以来のJIRAの問題 であり、そして多くがこの機能を要求しています。これがどのように動作するのかです:
大文字と小文字を区別しないインデックスは、1または2の強度を持つ 照合 を指定して作成されます。大文字と小文字を区別しないインデックスは、次のように作成できます。
db.cities.createIndex(
{ city: 1 },
{
collation: {
locale: 'en',
strength: 2
}
}
);
コレクションを作成するときに、コレクションごとに既定の照合順序を指定することもできます。
db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );
どちらの場合も、大/小文字を区別しない索引を使用するには、索引またはコレクションの作成時に使用したのと同じ照合順序をfind
操作に指定する必要があります。
db.cities.find(
{ city: 'new york' }
).collation(
{ locale: 'en', strength: 2 }
);
これにより、 "New York"、 "new york"、 "New york"などが返されます。
username: 'bill'
はBILL
またはBill
と一致しますが、全文検索クエリではありません。これは 語幹付きbill
の単語(Bills
、billed
など)とも一致します。正規表現を使うことを提案する答えは遅い、なぜならインデックスを使っても ドキュメンテーション状態 :
「大文字と小文字を区別しない正規表現クエリでは、一般にインデックスを効果的に使用できません。$ regexの実装では照合順序が認識されず、大文字と小文字を区別しないインデックスを利用できません。」
$regex
の回答も ユーザー入力インジェクション のリスクを冒しています。
db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity
TL、DR
使用しない正規表現
自然に移動し、mongodbの作り付けのインデックスを使用して検索
db.articles.insert(
[
{ _id: 1, subject: "coffee", author: "xyz", views: 50 },
{ _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
{ _id: 3, subject: "Baking a cake", author: "abc", views: 90 },
{ _id: 4, subject: "baking", author: "xyz", views: 100 },
{ _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
{ _id: 6, subject: "Сырники", author: "jkl", views: 80 },
{ _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
{ _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
]
)
検索したいTEXTフィールドのどちらかにインデックスを作成する必要があります。
db.articles.createIndex( { subject: "text" } )
db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } ) //FOR SENSITIVITY
db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});
Mongo(現在のバージョン2.0.0)はインデックス付きフィールドに対して大文字と小文字を区別しない検索を許可していません - 彼らのドキュメント を見てください。インデックスのないフィールドでは、他の答えにリストされている正規表現は問題ないはずです。
最良の方法はあなたの選択した言語にあります。あなたのオブジェクトのためのモデルラッパーを作成するとき、save()メソッドがあなたが検索するフィールドのセットを通して反復するようにしてください。これらのフィールドのセットは、検索に使用される小文字の対応物を持つ必要があります。
オブジェクトが再度保存されるたびに、小文字のプロパティがチェックされ、メインプロパティへの変更があれば更新されます。これにより、効率的に検索できるようになりますが、毎回lcフィールドを更新するのに必要な余分な作業は隠されます。
小文字のフィールドは、キー:値オブジェクトストア、または単に接頭辞lc_が付いたフィールド名です。 2番目の方法を使用して、照会を単純化しています(深いオブジェクト照会は時に混乱を招く可能性があります)。
注意:あなたはlc_フィールドをインデックスしたいのですが、それらが基づいているメインフィールドではありません。
Regexベースのクエリを使用するときに注意することが1つ非常に重要なこと - あなたがログインシステムのためにこれをしているとき、 あなたが探しているすべての一文字をエスケープする ^と$演算子を忘れないでください。 LodashにはこのためのNice関数があります 。すでに使用している必要があります。
db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})
どうして?ユーザーが自分のユーザー名として.*
を入力したとします。これはすべてのユーザー名と一致し、ユーザーのパスワードを推測するだけでログインが可能になります。
Mongooseを使用してこれは私のために働いた:
var find = function(username, next){
User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
if(err) throw err;
next(null, res);
});
}
"Table"の "column"を検索し、大文字と小文字を区別しないで検索したいとします。最も効率的な方法は以下の通りです。
//create empty JSON Object
mycolumn = {};
//check if column has valid value
if(column) {
mycolumn.column = {$regex: new RegExp(column), $options: "i"};
}
Table.find(mycolumn);
上記のコードでは、検索値をRegExとして追加し、オプションとして "i"で設定された鈍感な条件で検索します。
ではごきげんよう。
大文字と小文字を区別しないインデックスを使用できます。
次の例では、デフォルトの照合順序を指定せずにコレクションを作成し、大文字と小文字を区別しない照合順序で[名前]フィールドにインデックスを追加します。 nicodeの国際コンポーネント
/* 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
集約フレームワークはmongodb 2.2で導入されました。文字列演算子 "$ strcasecmp"を使用すると、文字列間で大文字と小文字を区別しないで比較できます。正規表現を使用するよりもお勧めで簡単です。
これが集約コマンド演算子に関する公式文書です。 https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp 。
変数を検索してそれをエスケープするには:
const escapeStringRegexp = require('escape-string-regexp')
const name = 'foo'
db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')})
変数をエスケープすると、 '。*'などの正規表現による攻撃からクエリが保護されます。
RegExpを使用します。他のオプションが機能しない場合は、RegExpが適切なオプションです。文字列の大文字と小文字を区別しません。
var username = new RegExp("^" + "John" + "$", "i");;
クエリでユーザー名を使用してから、完了です。
私もそれがあなたのために働くことを願っています。ではごきげんよう。
あなたがmongoのドキュメントで見ることができるように - バージョン3.2からデフォルトで$text
インデックスは大文字と小文字を区別しません: https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity
C#では、フィルタを使うのは私にとってはうまくいきます。
string s = "searchTerm";
var filter = Builders<Model>.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower()));
var listSorted = collection.Find(filter).ToList();
var list = collection.Find(filter).ToList();
私はメソッドが戻りが起こった後に呼ばれると信じているので私はまだこれをテストしていないのでそれはインデックスを使うかもしれません。
これはまたの問題を避けます
var filter = Builders<Model>.Filter.Eq(p => p.Title.ToLower(), s.ToLower());
そのmongodbはp.Title.ToLower()がプロパティであると考え、正しくマッピングされません。
これらは文字列検索でテスト済みです
{'_id': /.*CM.*/} ||find _id where _id contains ->CM
{'_id': /^CM/} ||find _id where _id starts ->CM
{'_id': /CM$/} ||find _id where _id ends ->CM
{'_id': /.*UcM075237.*/i} ||find _id where _id contains ->UcM075237, ignore upper/lower case
{'_id': /^UcM075237/i} ||find _id where _id starts ->UcM075237, ignore upper/lower case
{'_id': /UcM075237$/i} ||find _id where _id ends ->UcM075237, ignore upper/lower case
私は同様の問題に直面していましたが、これが私のために働いたものです。
const flavorExists = await Flavors.findOne({
'flavor.name': { $regex: flavorName, $options: 'i' },
});
Golangを使っていて、mongodbとmgoを使って大文字と小文字を区別して全文検索をしたいという方は godoc globalsign library 。
collation := &mgo.Collation{
Locale: "en",
Strength: 2,
}
err := collection.Find(query).Collation(collation)
大文字と小文字を区別しない正規表現用の単純なFuncを作成しました。これを私のフィルタで使用します。
private Func<string, BsonRegularExpression> CaseInsensitiveCompare = (field) =>
BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase));
その後、次のように単純にフィールドをフィルタリングします。
db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count();