多形データ を保存するコレクション、またはさまざまな構造またはスキーマを持つコレクションに対してスキーマ検証を指定できます。
単一のコレクション内に複数のスキーマのスキーマ検証を作成するには、検証ルールでスキーマを設定し、ドキュメントがコレクションのスキーマの 1 つに準拠していることを確認します。
このタスクについて
accounts
金融機関の顧客とそのアカウント詳細に関するデータを保存するコレクション、 について考えてみましょう。コレクションにはcustomer
ドキュメントとaccount
ドキュメントの両方が含まれています。
次のコードでは、2customer
つの ドキュメントをaccounts
コレクションに挿入して、それぞれ と の詳細を保存します。また、個々の保存アカウントを表すために 2account
つの ドキュメントと、共有のチェックアカウントを表す 3account
番目の ドキュメントも挿入されます。このチュートリアルのコードは、 MongoDB Shell(mongosh)で実行できます。
db.accounts.insertMany( [ { "customerId": "CUST-123456789", "docType": "customer", "name": { "title": "Mr", "first": "Andrew", "middle": "James", "last": "Morgan" }, "address": { "street1": "240 Blackfriars Rd", "city": "London", "postCode": "SE1 8NW", "country": "UK" }, "customerSince": ISODate("2005-05-20") }, { "customerId": "CUST-987654321", "docType": "customer", "name": { "title": "Mrs", "first": "Anne", "last": "Morgan" }, "address": { "street1": "240 Blackfriars Rd", "city": "London", "postCode": "SE1 8NW", "country": "UK" }, "customerSince": ISODate("2003-12-01") }, { "accountNumber": "ACC1000000654", "docType": "account", "accountType": "checking", "customerId": [ "CUST-123456789", "CUST-987654321" ], "dateOpened": ISODate("2003-12-01"), "balance": Decimal128("5067.65") }, { "accountNumber": "ACC1000000432", "docType": "account", "accountType": "savings", "customerId": [ "CUST-123456789" ], "dateOpened": ISODate("2005-10-28"), "balance": Decimal128("10341.21") }, { "accountNumber": "ACC1000000890", "docType": "account", "accountType": "savings", "customerId": [ "CUST-987654321" ], "dateOpened": ISODate("2003-12-15"), "balance": Decimal128("10341.89") } ] );
customer
または account
スキーマに準拠するドキュメントのみを accounts
コレクションに許可するには、次の手順を使用してスキーマ検証を設定します。
手順
各ドキュメントのタイプにJSON スキーマ の定義を作成
異なるタイプのドキュメントを区別するために、複数のJSONスキーマを使用できます。ドキュメントに含める必要がある属性と、それらが受け入れるデータ型を定義するには、 customer
ドキュメント用に 1 つ、account
ドキュメント用に 1 つのスキーマを作成します。各スキーマには、表すエンティティのタイプを識別するための docType
属性が含まれています。
const customerSchema = { required: ["docType", "customerId", "name", "customerSince"], properties: { docType: { enum: ["customer"] }, customerId: { bsonType: "string"}, name: { bsonType: "object", required: ["first", "last"], properties: { title: { enum: ["Mr", "Mrs", "Ms", "Dr"]}, first: { bsonType: "string" }, middle: { bsonType: "string" }, last: { bsonType: "string" } } }, address: { bsonType: "object", required: ["street1", "city", "postCode", "country"], properties: { street1: { bsonType: "string" }, street2: { bsonType: "string" }, postCode: { bsonType: "string" }, country: { bsonType: "string" } } }, customerSince: { bsonType: "date" } } }; const accountSchema = { required: ["docType", "accountNumber", "accountType", "customerId", "dateOpened", "balance"], properties: { docType: { enum: ["account"] }, accountNumber: { bsonType: "string" }, accountType: { enum: ["checking", "savings", "mortgage", "loan"] }, customerId: { bsonType: "array" }, dateOpened: { bsonType: "date" }, balance: { bsonType: "decimal" } } };
適切なドキュメントのみを受け入れるようにコレクションを構成する
customerSchema
accountSchema
oneOf
または のいずれかに一致するドキュメントを許可するには、 JSON スキーマ演算子を使用します。次に、collMod
コマンドを使用して、使用するaccounts
コレクションをスキーマ検証に更新します。
db.runCommand({ collMod: "accounts", validator: { $jsonSchema: { oneOf: [ customerSchema, accountSchema ] } } })
余分なセマンティック検証を追加する
オプションで、セマンティック検証を追加できます。例、コレクションのドキュメントに次の制約を追加できます。
customer
ドキュメントの場合、customerSince
値は現在の時刻より前の時刻にはできません。account
ドキュメントの場合、dateOpened
値は現在の時刻より前の時刻にはできません。節約アカウントの場合、
balance
は 0 を下回ることはできません。
無効な customer
ドキュメントと account
ドキュメントを識別し、それらの制約をスキーマ検証に実装することで、追加の検証を実装できます。
const invalidCustomer = { "$expr": { "$gt": ["$customerSince", "$$NOW"] } }; const invalidAccount = { $or: [ { accountType: "savings", balance: { $lt: 0} }, { "$expr": { "$gt": ["$dateOpened", "$$NOW"]} } ] };
const schemaValidation = { "$and": [ { $jsonSchema: { oneOf: [ customerSchema, accountSchema ] }}, { $nor: [ invalidCustomer, invalidAccount ] } ] }; db.runCommand({ collMod: "accounts", validator: schemaValidation })
コレクション内のドキュメントを検証する
コレクションにすでにあるすべてのドキュメントが新しいスキーマ検証に準拠していることを確認するには、db.collection.validate()
コマンドを使用します。
db.accounts.validate()
{ ns: '66cf8508e64dbb03ce45b30e_test.accounts', uuid: UUID('1aedf62a-f202-4e7c-b434-879057bb6d6b'), nInvalidDocuments: 0, nNonCompliantDocuments: 0, nrecords: 10, nIndexes: 1, keysPerIndex: { _id_: 10 }, indexDetails: { _id_: { valid: true } }, valid: true, repaired: false, readTimestamp: Timestamp({ t: 1749235730, i: 26 }), warnings: [], errors: [], extraIndexEntries: [], missingIndexEntries: [], corruptRecords: [], ok: 1, '$clusterTime': { clusterTime: Timestamp({ t: 1749235753, i: 31 }), signature: { hash: Binary.createFromBase64('3h7qyhLsgU21Pnzf/KVLl8suu2I=', 0), keyId: Long('7449048397505364002') } }, operationTime: Timestamp({ t: 1749235753, i: 31 }) }
nNonCompliantDocuments: 0
出力の は、accounts
コレクション内のすべてのドキュメントがコレクションスキーマに準拠していることを示します。
スキーマ検証をテストする
スキーマ検証を確認するには、 accounts
コレクションに無効なドキュメントを挿入してみてください。例、姓に必須の last
フィールドが欠落している customer
ドキュメントを挿入してみてください。
db.accounts.insertOne( { "docType": "customer", "customerId": "12345", "name": { "first": "John", }, "customerSince": "2025-01-01T00:00:00Z" } )
MongoServerError: Document failed validation