다형성 데이터를 저장하는 컬렉션 또는 다양한 구조나 스키마를 가진 문서에 대해 스키마 유효성 검사 지정할 수 있습니다.
단일 컬렉션 내에서 여러 스키마에 대한 스키마 유효성 검사 만들려면 유효성 검사 규칙에서 스키마를 설정하다 하고 문서가 컬렉션의 스키마 중 하나를 준수하는지 확인할 수 있습니다.
이 작업에 대하여
은행 고객에 대한 데이터와 해당 고객의 계정 세부 정보를 저장하는 컬렉션accounts
이 있다고 가정해 보겠습니다. 컬렉션 에 customer
문서와 account
문서가 모두 포함되어 있습니다.
다음 코드는 customer
컬렉션 에 두 개의 문서를 삽입하여 accounts
고객인 앤드류와 앤의 세부 정보를 각각 저장 . 또한 account
각 개인의 저축 계좌를 나타내는 두 개의 문서와 공유 당좌예금 계좌를 나타내는 세 번째 문서 account
삽입합니다. 이 튜토리얼의 코드는 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 schema 정의 만들기
서로 다른 유형의 문서를 구분하기 위해 여러 JSON schema를 사용할 수 있습니다. 문서 에 포함되어야 하는 속성과 허용하는 데이터 유형을 정의하려면 customer
문서 용 스키마와 account
문서 용 스키마 두 가지를 만듭니다. 각 스키마 나타내는 엔터티 유형을 식별하는 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 schema 연산자 사용합니다. 그런 다음 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