スキーマ検証
バージョン 3.2 で追加。
MongoDB は、アップデートおよび挿入中にスキーマ検証を実行する機能を提供します。
MongoDB Atlas でホストされる配置向けに UI でのスキーマ検証を実装できます。
検証ルールを指定する
検証ルールはコレクションごとにあります。
新しいコレクションの作成時に検証ルールを指定するには、 db.createCollection()
をvalidator
オプションとともに使用します。
既存のコレクションにドキュメント検証を追加するには、 validator
オプションを指定したcollMod
コマンドを使用します。
MongoDB は、次の関連オプションも提供します。
validationLevel
オプションは、アップデート中に MongoDB が既存のドキュメントに検証ルールをどの程度厳密に適用するかを決定します。validationAction
オプションは、MongoDB が検証ルールに違反するドキュメントをerror
して拒否するか、ログ内の違反についてはwarn
して無効なドキュメントを許可するかどうかを決定します。
JSON Schema
バージョン 3.6 の新機能。
バージョン3.6以降、 MongoDB は JSON schema 検証 をサポートしています。 JSON schema検証を指定するには、validator
式で$jsonSchema
演算子を使用します。
注意
JSON schema は、スキーマ検証を実行するための推奨手段です。
たとえば、次の例では、 JSON schemaを使用して検証ルールを指定しています。
db.createCollection("students", { validator: { $jsonSchema: { bsonType: "object", required: [ "name", "year", "major", "address" ], properties: { name: { bsonType: "string", description: "must be a string and is required" }, year: { bsonType: "int", minimum: 2017, maximum: 3017, description: "must be an integer in [ 2017, 3017 ] and is required" }, major: { enum: [ "Math", "English", "Computer Science", "History", null ], description: "can only be one of the enum values and is required" }, gpa: { bsonType: [ "double" ], description: "must be a double if the field exists" }, address: { bsonType: "object", required: [ "city" ], properties: { street: { bsonType: "string", description: "must be a string if the field exists" }, city: { bsonType: "string", description: "must be a string and is required" } } } } } } })
詳細については、$jsonSchema
を参照してください。
bsonType
の定義は、[ BSON types ]ページで確認できます。
その他のクエリ式
$jsonSchema
クエリ演算子を使用する JSON schema 検証に加えて、MongoDB は他の クエリ演算子による検証をサポートしています。ただし、次の例外があります。
たとえば、次の例では、 クエリ式を使用して検証ルールを指定します。
db.createCollection( "contacts", { validator: { $or: [ { phone: { $type: "string" } }, { email: { $regex: /@mongodb\.com$/ } }, { status: { $in: [ "Unknown", "Incomplete" ] } } ] } } )
動作
検証はアップデートや挿入中に行われます。 コレクションに検証を追加すると、変更されるまで既存のドキュメントは検証チェックを受けません。
既存のドキュメントの検証チェックを実行するには、 validate
コマンドまたはdb.collection.validate()
shellヘルパーを使用します。
既存のドキュメント
validationLevel
オプションによって、MongoDB が検証ルールを適用する操作が決まります。
validationLevel
がstrict
(デフォルト)の場合、MongoDB はすべての挿入とアップデートに検証ルールを適用します。validationLevel
がmoderate
の場合、MongoDB は、検証条件をすでに満たしている既存のドキュメントの挿入とアップデートに検証ルールを適用します。moderate
レベルでは、検証条件を満たさない既存のドキュメントの更新は有効性についてチェックされません。
たとえば、以下のドキュメントでcontacts
コレクションを作成する場合、
db.contacts.insert([ { "_id": 1, "name": "Anne", "phone": "+1 555 123 456", "city": "London", "status": "Complete" }, { "_id": 2, "name": "Ivan", "city": "Vancouver" } ])
次のコマンドを発行して、 contacts
コレクションにバリデーターを追加します。
db.runCommand( { collMod: "contacts", validator: { $jsonSchema: { bsonType: "object", required: [ "phone", "name" ], properties: { phone: { bsonType: "string", description: "must be a string and is required" }, name: { bsonType: "string", description: "must be a string and is required" } } } }, validationLevel: "moderate" } )
contacts
コレクションにmoderate
validationLevel を持つバリデーターが追加されました。
_id: 1
を使用してドキュメントを更新しようとした場合、既存のドキュメントが条件に一致しているため、MongoDB は新しい検証ルールを適用します。対照的に、MongoDB は検証ルールを満たしていないため、
_id: 2
を含むドキュメントに検証ルールを適用しません。
MongoDB バージョン5.0以降では、検証条件が満たされていない場合、 バリデーターは詳細なエラー情報を返します。 エラー出力は網羅的なもので、最初のエラーだけでなく、すべてのエラーが報告されます。
重要
エラー出力は人間が消費するためのものです。 将来変更される可能性があるため、スクリプトでは依存しないでください。
次の例では、いずれのアップデートも、 name
が string である必要がある検証ルールと整合性がありません。
db.contacts.update( { _id: 1 }, { $set: { name: 10 } } ) db.contacts.update( { _id: 2 }, { $set: { name: 20 } } )
以下の出力は、 errInfo
オブジェクトに示されているように、 _id: 1
を含むドキュメントが詳細な説明で検証に失敗することを示しています。 このドキュメントは検証追加時に初期基準を満たしていなかったため、 _id: 2
を使用したドキュメントの更新に成功します。
// _id: 1 WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 121, "errmsg" : "Document failed validation", "errInfo" : { "failingDocumentId" : 1, "details" : { "operatorName" : "$jsonSchema", "schemaRulesNotSatisfied" : [ { "operatorName" : "properties", "propertiesNotSatisfied" : [ { "propertyName" : "name", "details" : [ { "operatorName" : "bsonType", "specifiedAs" : { "bsonType" : "string" }, "reason" : "type did not match", "consideredValue" : 10, "consideredType" : "double" } ] } ] } ] } } } }) // _id: 2 WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
検証を完全に無効にするには、 validationLevel
をoff
に設定します。
無効なドキュメントを受け入れるか拒否する
validationAction
オプションは、MongoDB が検証ルールに違反するドキュメントをどのように処理するかを決定します。
validationAction
がerror
(デフォルト)の場合、MongoDB は検証条件に違反する挿入または更新を拒否します。validationAction
がwarn
の場合、MongoDB は違反をログに記録しますが、挿入または更新の続行は許可します。
たとえば、次の JSON schema バリデーターを使用してcontacts2
コレクションを作成します。
db.createCollection( "contacts2", { validator: { $jsonSchema: { bsonType: "object", required: [ "phone" ], properties: { phone: { bsonType: "string", description: "must be a string and is required" }, email: { bsonType : "string", pattern : "@mongodb\.com$", description: "must be a string and match the regular expression pattern" }, status: { enum: [ "Unknown", "Incomplete" ], description: "can only be one of the enum values" } } } }, validationAction: "warn" } )
warn
validationAction
を使用すると、MongoDB はすべての違反をログに記録しますが、挿入または更新を続行できます。
たとえば、次の挿入操作は検証ルールに違反します。
db.contacts2.insertOne( { name: "Amanda", status: "Updated" } )
ただし、 validationAction
はwarn
のみであるため、MongoDB は検証違反メッセージのみをログに記録し、操作を続行できるようにします。 MongoDB ログを表示するには、次のコマンドを実行します。
db.adminCommand( { getLog: "global" } )
コレクションの使用状況によっては、このコマンドは多くのデータを返す可能性があります。 検証エラー(ログの長い 1 行。読みやすくするためにここで再フォーマットされています)には、次のような情報が含まれています。
"{\"t\":{\"$date\":\"2021-01-20T15:59:57.305+00:00\"}, \"s\":\"W\", \"c\":\"STORAGE\", \"id\":20294, \"ctx\":\"conn1\", \"msg\":\"Document would fail validation\", \"attr\":{\"namespace\":\"test.contacts2\", \"document\":{\"_id\":{\"$oid\":\"6008537d42e0d23385568881\"}, \"name\":\"Amanda\", \"status\":\"Updated\"}, \"errInfo\":{\"failingDocumentId\":{\"$oid\":\"6008537d42e0d23385568881\"}, \"details\":{\"operatorName\":\"$jsonSchema\", \"schemaRulesNotSatisfied\":[ {\"operatorName\":\"properties\", \"propertiesNotSatisfied\":[ {\"propertyName\":\"status\", \"details\":[ {\"operatorName\":\"enum\", \"specifiedAs\":{\"enum\":[ \"Unknown\", \"Incomplete\"]}, \"reason\":\"value was not found in enum\", \"consideredValue\":\"Updated\"}]}]}, {\"operatorName\":\"required\", \"specifiedAs\":{\"required\":[\"phone\"]}, \"missingProperties\":[\"phone\"]}]}}}}"
制限事項
admin
、local
、および config
データベース内のコレクションに対してバリデーターを指定することはできません。
system.*
コレクションにバリデーターを指定することはできません。
ドキュメント検証のバイパス
ユーザーはbypassDocumentValidation
オプションを使用してドキュメント検証をバイパスできます。
次のコマンドは、新しいオプションbypassDocumentValidation
を使用して、操作ごとの検証をバイパスできます。
applyOps
コマンドmapReduce
コマンドとdb.collection.mapReduce()
メソッドinsert
コマンドupdate
コマンド$out
{ コマンドと メソッドのaggregate
db.collection.aggregate()
$merge
} ステージと ステージ
アクセス制御が有効になっている配置でドキュメント検証をバイパスするには、認証されたユーザーはbypassDocumentValidation
アクションを持っている必要があります。 組み込みロールdbAdmin
とrestore
はこのアクションを提供します。