Docs Menu
Docs Home
/
MongoDBマニュアル
/ / / /

$regex

項目一覧

  • 定義
  • 互換性
  • 構文
  • 動作

注意

このページでは、自己管理型(Atlas Search 以外)配置に対する正規表現検索機能について説明します。MongoDB Atlas でホストされているデータに対して、MongoDB では、改良された全文検索ソリューションである Atlas Search を提供します。Atlas Search は独自の $regex演算子を持ちます。詳細については、Atlas Search ドキュメントの $regex を参照してください。

$regex

クエリ内の文字列をパターン マッチングする正規表現機能を提供します。

次の環境でホストされる配置には $regex を使用できます。

  • MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです

  • MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン

  • MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン

$regex を使うには、以下の構文のいずれかを使います。

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ "<field>": { "$regex": "pattern", "$options": "<options>" } }
{ <field>: { $regex: /pattern/<options> } }

注意

$regexmongodump と共に使用するためには、クエリ ドキュメントを一重引用符('{ ... }')で囲み、shell 環境とやり取りしないようにする必要があります。

クエリ ドキュメントは、フィールド名と演算子を引用符で囲むことを含む、拡張 JSON V 2 形式(緩和モード、標準モード、厳密モードのいずれか)である必要があります。以下がその例です。

mongodump -d=sample_mflix -c=movies -q='{"year": {"$regex": "20"}}'

MongoDBでは、正規表現オブジェクト(/pattern/)を使用して正規表現を指定することもできます。

{ <field>: /pattern/<options> }

特定の構文の使用に関する制限については、「$regex と /pattern/ の構文」を参照してください。

$options

次の <options> は正規表現で使用できます。

オプション
説明
i
大文字と小文字を区別せずに一致させます。例として、「大文字と小文字を区別しない正規表現一致の実行」を参照してください。
m

アンカーを含むパターン(先頭は ^、末尾は $)の場合、複数行の値を含む文字列に対して各行の先頭または末尾で一致します。このオプションを指定しない場合、これらのアンカーは文字列の先頭か末尾で一致します。例については、「指定されたパターンで始まる行の複数行一致」を参照してください。

パターンにアンカーが含まれていない場合、または文字列値に改行文字が含まれていない場合(\n など)、 m オプションは効果がありません。

x

エスケープされたり、文字クラスに含まれていたりしない限り、$regex パターン内のすべての空白文字を無視できる「拡張」機能です。

さらに、エスケープされていないハッシュまたはパウンド(#)記号と次の改行を含む間にある文字は無視されるため、複雑なパターンでコメントを含めることができます。これはデータ文字にのみ適用され、パターン内の特殊文字シーケンスに空白文字が表示されることはありません。

x オプションは VT 文字の処理には影響しません(コード 11)。

s
ドット記号(.)を、改行文字を含むすべての文字と一致します。例については、「 .ドット記号を使用した改行との一致」を参照してください。
u
Unicode をサポートします。このフラグは使用可能ですが、冗長です。デフォルトで $regex 演算子に UTF が指定されるため、u オプションは不要です。

注意

$regex演算子はグローバル検索修飾子gをサポートしていません

$inクエリ述語演算子に正規表現を含めるには、JavaScript 正規表現オブジェクトのみを使用できます( /pattern/ )。

以下に例を挙げます。

{ name: { $in: [ /^acme/i, /^ack/ ] } }

$in 演算子内では $regex 演算子式を使用できません。

フィールドのクエリ条件をカンマで区切ったリストに正規表現を含めるには、$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 オプションのいずれかを使用するには、$regex 演算子とともに $options 演算子式を使用する必要があります。たとえば、 i オプションと s オプションを指定するには、次のように両方とも $options を使用する必要があります。

{ name: { $regex: /acme.*corp/, $options: "si" } }
{ name: { $regex: 'acme.*corp', $options: "si" } }

JavaScript でサポートされていない正規表現で、 PCRE でサポートされている機能を使用するには、 $regex 演算子を使用して正規表現を文字列として指定する必要があります。

大文字と小文字を区別しない文字列を一致させるには次のとおり。

  • "(?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 は、正規表現によるパターン一致を実装するために Perl 互換正規表現 (PCRE 2)ライブラリを使用します。Perl 互換正規表現 (PCRE2) の詳細については、 PCRE ドキュメントを参照してください。

$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 は正規表現をインデックス内の値と照合します。これは、コレクションをスキャンよりも高速です。

正規表現が「プレフィックス式」の場合、さらに最適化を行うことができます。一致する可能性のあるものはすべて同じ文字列で始まるということを意味します。これにより、MongoDB はそのプレフィックスから「範囲」を構築し、その範囲に含まれるインデックスの値のみと一致させることができます。

正規表現は、キャレット(^)または左アンカー(\A)で始まり、その後に単純な記号の文字列が続く場合、「プレフィックス式」です。たとえば、正規表現 /^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" }
] )

次の例は、 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 オプションを使用して、sku の値が ABC で始まるドキュメントに対して大文字と小文字を区別しない一致を実行します。

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 パターンにアンカーが含まれていない場合、次の例のように、パターンは文字列全体に対して一致します。

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' }
]

バージョン 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 フィールド内のどの単語も一致した文字列( yster)で始まっていません。ドキュメント _id: 0 および _id: 1Ö 文字は UTF-8 文字であるため、一致を実行する時には無視されます。

期待される結果は、このクエリが何もドキュメントを返さないことです。

クエリが UTF-8 文字を認識できるようにするには、次のようにパターンの前に *UCP オプションを指定します。

db.songs.find( { artist: { $regex: "(*UCP)/\byster/" } } )

このクエリでは何もドキュメントが返されず、期待した結果となりました。

Tip

正規表現パターンのエスケープ文字

*UCP またはその他の正規表現オプションを指定する場合は、shell またはドライバーに適切なエスケープ文字を使用していることを確認してください。

戻る

$mod