ピリオド(.
)とドル記号( ) を含むフィールド名$
Overview
MongoDB 5.0 では、ドル記号( $
)のプレフィックスが付いたフィールド名、またはピリオド( .
)のプレフィックスが付いたフィールド名の サポートが強化 されました。 これらの文字を使用するデータソースの操作を容易にするために、データを保存するための検証ルールが更新されました。
ほとんどの場合、このようなフィールド名を使用して保存されたデータには直接アクセスできません。 これらのフィールドにアクセスするクエリでは、 $getField
、 $setField
、 $literal
などのヘルパー メソッドを使用する必要があります。
フィールド名の検証ルールは、すべてのタイプのストレージ操作で同じではありません。 このページでは、さまざまな挿入操作と更新操作でドル記号( $
)のプレフィックスがついたフィールド名がどのように処理されるかがまとめられています。
挿入操作
ドル記号($
)のプレフィックスがついたフィールドは、挿入のトップレベルおよびネストされたフィールド名として使用できます。
db.sales.insertOne( { "$price": 50.00, "quantity": 30 } )
ドル記号($
)のプレフィックスがついたフィールドは、それ以外を予約語として使用する挿入で使用できます。$inc
のような演算子名や、id
、db
、ref
のような単語もフィールド名として使用できます。
db.books.insertOne( { "$id": "h1961-01", "location": { "$db": "novels", "$ref": "2007042768", "$inc": true } } )
アップサート中に新しいドキュメントを作成する更新は、フィールド名の検証の update
ではなく insert
として扱われます。アップサートは、ドル記号($
)のプレフィックスがついたフィールドを受け入れることができます。ただし、アップサートは、特殊なケースであるため、更新の match
の部分で既存のドキュメントが選択された場合、同様の更新操作でエラーが発生する可能性があります。
このコード サンプルは upsert: true
に設定されているため、クエリ用語の { "date": "2021-07-07" }
に一致するドキュメントがコレクションにまだ含まれていない場合は、新しいドキュメントが挿入されます。このサンプル コードが既存のドキュメントと一致する場合、$hotel
にドル記号($
)のプレフィックスが付いているため更新は失敗します。
db.expenses.updateOne( { "date": "2021-07-07" }, { $set: { "phone": 25.17, "$hotel": 320.10 } }, { upsert: true } )
ドキュメントを置き換える更新
更新演算子は、既存のフィールドを新しいドキュメントに置き換えるか、それらのフィールドを変更します。更新によって置換が実行される場合、ドル記号($
)のプレフィックスがついたフィールドは最上位のフィールド名として使用できません。
次のようなドキュメントについて考えてみましょう。
{ "_id": "E123", "address": { "$number": 123, "$street": "Elm Road" }, "$rooms": { "br": 2, "bath": 1 } }
既存のドキュメントを置き換える更新演算子を使用して address.$street
フィールドを変更することはできますが、その方法で $rooms
フィールドを更新することはできません。
db.housing.updateOne( { "_id": "E123" }, { $set: { "address.$street": "Elm Ave" } } )
集計パイプラインの一部として$setField
を使用して、 は最上位のドル記号( $
)のプレフィックス付きフィールドを$rooms
のように更新します。
ドキュメントを変更する更新
更新によって既存のドキュメント フィールドが、置き換えではなく変更される場合、ドル記号($
)のプレフィックスがついたフィールドが最上位のフィールド名になることがあります。サブフィールドには直接アクセスできますが、最上位のフィールドにアクセスするにはヘルパー メソッドが必要です。
このレコードのようなドキュメントがあるコレクションを考えてみましょう。
{ _id: ObjectId("610023ad7d58ecda39b8d161"), "part": "AB305", "$bin": 200, "quantity": 100, "pricing": { sale: true, "$discount": 60 } }
pricing.$discount
サブフィールドは、直接クエリできます。
db.inventory.findAndModify( { query: { "part": { $eq: "AB305" } }, update: { $inc: { "pricing.$discount": 10 } } } )
最上位レベルの $bin
フィールドの値にアクセスするには、$getField
と $literal
を使用します。
db.inventory.findAndModify( { query: { $expr: { $eq: [ { $getField: { $literal: "$bin" } }, 200 ] } }, update: { $inc: { "quantity": 10 } } } )
集計パイプラインを使用した更新
集計パイプラインのドル記号($
)のプレフィックスがついたフィールドを変更するには、$replaceWith
ステージで $setField
、$getField
、および $literal
使用します。
次のような学校のレコードのコレクションを考えてみましょう。
{ "_id": 100001, "$term": "fall", "registered": true, "grade": 4 }
パイプラインを使用して、ドル記号($
)のプレフィックスが付いた $term
フィールドを更新し、春学期の新しいコレクションを作成します。
db.school.aggregate( [ { $match: { "registered": true } }, { $replaceWith: { $setField: { field: { $literal: "$term" }, input: "$$ROOT", value: "spring" } } }, { $out: "spring2022" } ] )
一般的な制限
上記のストレージ検証ルールに加えて、ドル記号($
)のプレフィックスがついたフィールド名の使用には一般的な制限があります。これらのフィールドには、次のことはできません。
インデックスを付ける
シャードキーの一部に使用する
を使用して検証される
$jsonSchema
エスケープ シーケンスで変更する
フィールドレベル暗号化と併用する
_id
ドキュメントのサブフィールドに使用する
警告
ドル記号($)とピリオド(.)によるデータ損失の可能性
ドル記号($
)で始まるフィールド名や、ピリオド(.
)を含むフィールド名を使用し、MongoDB 5.0 以前のサーバーで未確認の書き込み(書き込み確認(write concern)w=0
)と組み合わせて使用すると、頻度は低いもののデータが失われる可能性があります。
insert 、 update 、およびfindAndModifyコマンドを実行すると、5.0 互換のドライバーは、ドル記号( $
)のプレフィックスが付いたフィールド名またはピリオド( .
)を含むフィールド名を持つドキュメントの使用に対する制限を解除します。 これらのフィールド名は、以前のドライバー バージョンではクライアント側のエラーを引き起こしていました。
ドライバーが接続されているサーバー バージョンに関係なく、制限は解除されます。5.0 ドライバーが古いサーバーにドキュメントを送信すると、エラーを送信することなくドキュメントは拒否されます。
警告
ドル記号($)とピリオド(.)に関するインポートとエクスポートの問題
MongoDB 5.0 以降、ドキュメントフィールド名に接頭辞としてドル記号($
)を付けたり、ピリオド(.
)を含めたりすることができます。ただし、フィールド名にこれらの記号が使用されている場合、状況によっては mongoimport
と mongoexport
が通常どおりに動作しないことがあります。
MongoDB Extended JSON v2では、型ラッパーと、型ラッパーと同じ名前を持つフィールドを区別できません。対応する BSON 表現にドル( $
)で始まるキーが含まれる可能性があるコンテキストでは、拡張 JSON 形式を使用しないでください。DBRef メカニズムは、この一般ルールの例外です。
フィールド名にピリオド(.
)が含まれる状態での mongoimport
と mongoexport
の使用にも制限があります。CSV ファイルではデータ階層を表すのにピリオド(.
)が使用されるため、フィールド名のピリオド(.
)はネストのレベルと誤解されます。