注意
このページでは、自己管理型(Atlas Search 以外)配置に対する正規表現検索機能について説明します。MongoDB Atlas でホストされているデータに対して、MongoDB では、改良された全文検索ソリューションである Atlas Search を提供します。Atlas Search は独自の $regex演算子を持ちます。詳細については、Atlas Search ドキュメントの $regex を参照してください。
定義
互換性
次の環境でホストされる配置には $regex を使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
次のいずれかの構文バリエーションを使用します。
{ <field>: { $regex: /pattern/, $options: '<options>' } } { "<field>": { "$regex": "pattern", "$options": "<options>" } } { <field>: { $regex: /pattern/<options> } }
注意
$regexとmongodump を一緒に使用するには、クエリドキュメントを一重引用符('{... }')で囲み、 シェルとやり取りしないようにします。
クエリ ドキュメントは、フィールド名と演算子を引用符で囲むことを含む、拡張 JSON V 2 形式(緩和モード、標準モード、厳密モードのいずれか)である必要があります。以下がその例です。
mongodump -d=sample_mflix -c=movies -q='{"year": {"$regex": "20"}}'
正規式オブジェクト(/pattern/)を使用して正規表現を指定することもできます。
{ <field>: /pattern/<options> }
構文の使用に関する制限については、「 $regex と /pattern/ のシンタックス 」を参照してください。
次の <options> は正規表現で使用できます。
オプション | 説明 |
|---|---|
| 大文字と小文字を区別せずに一致します。 例、「 大文字と小文字を区別しない正規表現一致の実行 」を参照してください。 |
| アンカーを含むパターン(開始は パターンにアンカーが含まれていない場合、または文字列値に改行文字が含まれていない場合( 、 |
| エスケープされたり、文字クラスに含まれていたりしない限り、 さらに、エスケープされていないハッシュまたはパウンド(
|
| ドット記号( |
| Unicode オプション。使用可能ですが冗長です。 |
注意
$regex では、グローバル検索修飾子 g はサポートされていません。
動作
$regex と /pattern/ の構文
$in 式
$inクエリ述語演算子に正規表現を含めるには、JavaScript 正規表現オブジェクトのみを使用できます( /pattern/ )。
以下に例を挙げます。
{ name: { $in: [ /^acme/i, /^ack/ ] } }
$in 演算子内では $regex 演算子式を使用できません。
フィールドの暗黙的な AND 条件
フィールドのクエリ条件をカンマで区切ったリストに正規表現を含めるには、$regex 演算子を使用します。例は次のとおりです。
{ name: { $regex: /acme.*corp/i, $nin: [ 'acmeblahcorp' ] } } { name: { $regex: /acme.*corp/, $options: 'i', $nin: [ 'acmeblahcorp' ] } } { name: { $regex: 'acme.*corp', $options: 'i', $nin: [ 'acmeblahcorp' ] } }
x と s オプション
x オプションまたは s オプションのいずれかを使用するには、$regex 演算子とともに $options 演算子式を使用する必要があります。たとえば、 i オプションと s オプションを指定するには、次のように両方とも $options を使用する必要があります。
{ name: { $regex: /acme.*corp/, $options: "si" } } { name: { $regex: 'acme.*corp', $options: "si" } }
PCRE と JavaScript
JavaScriptでサポートされていない正規式で、 PCRE でサポートされている機能を使用するには、$regex 演算子を使用して、パターンを string として指定します。
大文字と小文字を区別しない文字列を一致させるには次のとおり。
"(?i)"は、大文字と小文字を区別しない一致を開始します。"(?-i)"は、大文字と小文字を区別しない一致を終了します。
たとえば、正規表現"(?i)a(?-i)cme" は、次の文字列と一致します。
"a"または"A"ではじまる文字列。これは、大文字と小文字を区別しない一致です。"cme"で終了する文字列。これは大文字と小文字を区別する一致です。
以下の文字列は、例の正規表現と一致します。
"acme""Acme"
次の例では、$regex 演算子を使用して、正規表現 "(?i)a(?-i)cme" と一致する name フィールドの文字列を検索します。
{ name: { $regex: "(?i)a(?-i)cme" } }
バージョン 6.1 以降、MongoDB では、正規表現パターン マッチングを実装するために PCRE 2(Perl Compatible Regular Expressions、Perl 互換正規表現)ライブラリが使用されます。Perl 互換正規表現 (PCRE2) の詳細については、 PCRE ドキュメントを参照してください。
$regex および $not
$not演算子は次の両方で論理NOT 操作を実行できます。
正規式オブジェクト(
/pattern/)以下に例を挙げます。
db.inventory.find( { item: { $not: /^p.*/ } } ) $regex演算子式以下に例を挙げます。
db.inventory.find( { item: { $not: { $regex: "^p.*" } } } ) db.inventory.find( { item: { $not: { $regex: /^p.*/ } } } )
インデックスの使用
$regex クエリのインデックス使用とパフォーマンスは、クエリが大文字と小文字を区別するかしないかによって異なります。
大文字と小文字を区別するクエリ
大文字と小文字を区別する正規式クエリでは、フィールドにインデックスが存在する場合、 MongoDB はインデックス内の値の正規式を照合します。これは、コレクションスキャンよりも高速です。
正規式が「プレフィックス式」の場合、さらに最適化を行うことができます。一致する可能性のあるものはすべて同じ string で始まるということを意味します。これにより、 MongoDB はそのプレフィックスから「範囲」を構築し、指定された範囲内のインデックスの値のみと一致させることができます。
正規式は、キャレット(^)または左アンカー(\A)で始まり、その後に単純な記号の string が続く場合、「プレフィックス式」です。例、正規表現 /^abc.*/ は、abc で始まるインデックスの値のみと一致するように最適化されています。
さらに、/^a/、/^a.*/、/^a.*$/ は同等の文字列と一致しますが、パフォーマンス特性は異なります。これらの式はすべて、適切なインデックスが存在する場合はインデックスを使用します。ただし、/^a.*/ と /^a.*$/ は遅くなります。 /^a/ はプレフィックスと一致した後、スキャンを停止することができます。
大文字と小文字を区別しないクエリ
大文字と小文字を区別しないインデックスは、$regex クエリのパフォーマンスを向上させません。$regex演算子は照合順序を考慮しないため、そのようなインデックスを活用できません。
例
このセクションの例では、次の products コレクションを使用します。
db.products.insertMany( [ { _id: 100, sku: "abc123", description: "Single line description." }, { _id: 101, sku: "abc789", description: "First line\nSecond line" }, { _id: 102, sku: "xyz456", description: "Many spaces before line" }, { _id: 103, sku: "xyz789", description: "Multiple\nline description" }, { _id: 104, sku: "Abc789", description: "SKU starts with A" } ] )
LIKE 一致の実行
次の例は、 sku フィールドが "%789" のようになっているすべてのドキュメントと一致します。
db.products.find( { sku: { $regex: /789$/ } } )
この例は、次のSQL のLIKE ステートメントと似ています。
SELECT * FROM products WHERE sku like "%789";
出力例:
[ { _id: 101, sku: 'abc789', description: 'First line\nSecond line' }, { _id: 103, sku: 'xyz789', description: 'Multiple\nline description' }, { _id: 104, sku: 'Abc789', description: 'SKU starts with A' } ]
大文字と小文字を区別しない正規表現一致の実行
次の例では、i オプションを使用して、ABC で始まる sku 値に対して大文字と小文字を区別しない一致を実行します。
db.products.find( { sku: { $regex: /^ABC/i } } )
出力例:
[ { _id: 100, sku: 'abc123', description: 'Single line description.' }, { _id: 101, sku: 'abc789', description: 'First line\nSecond line' }, { _id: 104, sku: 'Abc789', description: 'SKU starts with A' } ]
指定したパターンで始まる行の複数行一致
次の例では、 m オプションを使用して、複数行の文字列に対して文字 S で始まる行と一致させます。
db.products.find( { description: { $regex: /^S/, $options: 'm' } } )
出力例:
[ { _id: 100, sku: 'abc123', description: 'Single line description.' }, { _id: 101, sku: 'abc789', description: 'First line\nSecond line' }, { _id: 104, sku: 'Abc789', description: 'SKU starts with A' } ]
m オプションを指定しない場合、出力例は次のようになります。
[ { _id: 100, sku: 'abc123', description: 'Single line description.' }, { _id: 104, sku: 'Abc789', description: 'SKU starts with A' } ]
$regex パターンにアンカーが含まれていない場合、そのパターンは string 全体と一致します。 (例: )。
db.products.find( { description: { $regex: /S/ } } )
出力例:
[ { _id: 100, sku: 'abc123', description: 'Single line description.' }, { _id: 101, sku: 'abc789', description: 'First line\nSecond line' }, { _id: 104, sku: 'Abc789', description: 'SKU starts with A' } ]
改行に合わせるには、.ドット記号を使用する
次の例では、s オプションを使用してドット文字(. )が改行を 含む すべての文字と一致するようにし、i オプションを使用して大文字と小文字を区別しない一致を実行します。
db.products.find( { description: { $regex: /m.*line/, $options: 'si' } } )
出力例:
[ { _id: 102, sku: 'xyz456', description: 'Many spaces before line' }, { _id: 103, sku: 'xyz789', description: 'Multiple\nline description' } ]
s オプションを指定しない場合、クエリは次を返します。
[ { _id: 102, sku: 'xyz456', description: 'Many spaces before line' } ]
パターン内の空白を無視する
次の例では、x オプションを使用して、一致するパターン内で # で始まり、\n で終わる空白とコメントは無視します。
var pattern = "abc #category code\n123 #item number" db.products.find( { sku: { $regex: pattern, $options: "x" } } )
出力例:
[ { _id: 100, sku: 'abc123', description: 'Single line description.' } ]
文字列内の大文字と小文字を一致させるための正規表現の使用
次の例では、正規表現 "(?i)a(?-i)bc" を使用して、次の内容を含む sku フィールド文字列と一致させます。
"abc""Abc"
db.products.find( { sku: { $regex: "(?i)a(?-i)bc" } } )
出力例:
[ { _id: 100, sku: 'abc123', description: 'Single line description.' }, { _id: 101, sku: 'abc789', description: 'First line\nSecond line' }, { _id: 104, sku: 'Abc789', description: 'SKU starts with A' } ]
正規表現オプション拡張による ASCII 以外の文字との一致
バージョン 6.1 で追加。
デフォルトでは 、一部の正規表現オプション(/b や /w など)は ASCII 文字のみを認識します。そのため、UTF-8 文字に対して正規表現の一致を実行すると、予期しない結果を引き起こすことがあります。
MongoDB 6.1 以降では、UTF-8 文字と一致させるために*UCP 正規表現オプションを指定できます。
重要
UCP オプションのパフォーマンス
*UCP オプションを使用すると、*UCP で一致を実行するためには複数のステージのテーブルルックアップが必要となるため、オプションが指定されていないクエリよりも遅くなります。
たとえば、 songs コレクション内の次のドキュメントを考えてみましょう。
db.songs.insertMany( [ { _id: 0, "artist" : "Blue Öyster Cult", "title": "The Reaper" }, { _id: 1, "artist": "Blue Öyster Cult", "title": "Godzilla" }, { _id: 2, "artist" : "Blue Oyster Cult", "title": "Take Me Away" } ] )
次の正規表現クエリは、\b オプションを使用して正規表現の一致を行います。\b オプションは、単語の境界に一致します。
db.songs.find( { artist: { $regex: /\byster/ } } )
出力例:
[ { _id: 0, artist: 'Blue Öyster Cult', title: 'The Reaper' }, { _id: 1, artist: 'Blue Öyster Cult', title: 'Godzilla' } ]
上記の結果は予期できないもので、返された artist フィールド内のどの単語全体も一致した string(yster)で始まっていません。ドキュメント _id: 0 と _id: 1 の Ö 文字は、Ö が UTF-8 文字であるため、一致を実行する時には無視されます。
期待される結果は、このクエリが何もドキュメントを返さないことです。
クエリが UTF-8 文字を認識できるようにするには、次のようにパターンの前に *UCP オプションを指定します。
db.songs.find( { artist: { $regex: "(*UCP)/\byster/" } } )
このクエリでは何もドキュメントが返されません。これは、 フィールド内のどの単語全体も stringartist ysterで始まっていないため、期待した結果となりました。
Tip
正規表現パターンのエスケープ文字
*UCP またはその他の正規式オプションを指定する場合は、 シェルまたはドライバーに適切なエスケープ文字を使用してください。