You can specify schema validation for a collection that stores polymorphic data, or documents with varying structures or schemas.您可以为存储多态数据的集合或具有不同结构或模式的文档指定模式验证。
To create schema validation for multiple schemas within a single collection, you can set the schemas in your validation rules and ensure that documents conform to one of your collection's schemas.要为单个集合中的多个模式创建模式验证,可以在验证规则中设置模式,并确保文档符合集合的模式之一。
About this Task关于此任务
Consider a collection, 考虑一个集合,accounts, that stores data on customers of a bank and their account details. The collection contains both customer documents and account documents.accounts,它存储银行客户及其帐户详细信息的数据。该集合包含customer文档和account文档。
The following code inserts two 以下代码将两个customer documents into the accounts collection to store the details of customers Andrew and Anne, respectively. customer文档插入到accounts集合中,分别存储客户Andrew和Anne的详细信息。It also inserts two 它还插入了两份account documents to represent each of their individual savings accounts and a third account document to represent their shared checking account. account文件,分别代表他们的个人储蓄账户和第三份account文件。You can run the code for this tutorial in the MongoDB Shell (mongosh).您可以在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")
}
] );
To only allow documents that adhere to the 要只允许符合customer or account schemas into the accounts collection, set up schema validation using the following procedure.customer或account模式的文档进入accounts集合,请使用以下过程设置模式验证。
Steps步骤
Create a JSON schema definition for each type of document为每种类型的文档创建JSON模式定义
To distinguish between different types of documents, you can use multiple JSON schemas. To define what attributes need to be in a document and what data types they accept, create two schemas: one for a 为了区分不同类型的文档,您可以使用多个JSON模式。要定义文档中需要哪些属性以及它们接受哪些数据类型,请创建两个模式:一个用于customer document, and one for an account document. Each schema includes a docType attribute to identify which type of entity it represents.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" }
}
};Configure the collection to only accept the appropriate documents将集合配置为只接受适当的文档
To allow documents that match either the 要允许与customerSchema or the accountSchema, use the oneOf JSON schema operator. customerSchema或accountSchema匹配的文档,请使用oneOf JSON模式运算符。Then, use the 然后,使用collMod command to update the accounts collection to use to your schema validation.collMod命令更新要用于架构验证的帐户集合。
db.runCommand({
collMod: "accounts",
validator: { $jsonSchema: { oneOf: [ customerSchema, accountSchema ] } }
})Add extra semantic validations添加额外的语义验证
You can optionally add extra semantic validations. For example, you can add the following constraints to your collection’s documents:您可以选择添加额外的语义验证。例如,您可以将以下约束添加到集合的文档中:
For对于customerdocuments, thecustomerSincevalue can't be any earlier than the current time.customer文档,customerSince值不能早于当前时间。For对于accountdocuments, thedateOpenedvalue can't be any earlier than the current time.account文档,dateOpened值不能早于当前时间。For savings accounts, the对于储蓄账户,balancecan't fall below zero.balance(余额)不能低于零。
You can implement the extra validations by identifying invalid 您可以通过识别无效的customer and account documents and implementing those constraints into your schema validation.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
})Verify the documents in your collection核实您集合的文件
To verify that all the documents already in your collection adhere to your new schema validation, use the 要验证集合中已有的所有文档是否符合新的模式验证,请使用db.collection.validate() command.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 in the output indicates that all the documents in the accounts collection comply with the collection schemas.nNonCompliantDocuments: 0表示帐户集合中的所有文档都符合集合架构。
Test your schema validation测试模式验证
To verify your schema validation, you can try to insert an invalid document into the 为了验证架构验证,您可以尝试将无效文档插入到accounts collection. For example, try inserting a customer document missing the required last field, for last name:accounts集合中。例如,尝试插入一个缺少姓氏所需的last字段的customer文档:
db.accounts.insertOne(
{
"docType": "customer",
"customerId": "12345",
"name": {
"first": "John",
},
"customerSince": "2025-01-01T00:00:00Z"
}
)
MongoServerError: Document failed validation