最新的稳定版请使用 Spring Data MongoDB 4.3.1! |
最新的稳定版请使用 Spring Data MongoDB 4.3.1! |
从版本 3.6 开始,MongoDB 支持根据提供的 JSON 架构验证文档的集合。 在创建集合时,可以定义架构本身以及验证操作和级别,如以下示例所示:
{
"type": "object", (1)
"required": [ "firstname", "lastname" ], (2)
"properties": { (3)
"firstname": { (4)
"type": "string",
"enum": [ "luke", "han" ]
},
"address": { (5)
"type": "object",
"properties": {
"postCode": { "type": "string", "minLength": 4, "maxLength": 5 }
}
}
}
}
1 | JSON 架构文档始终从其根目录描述整个文档。架构是架构对象本身,可以包含 描述属性和子文档的嵌入式架构对象。 |
2 | required 是一个属性,用于描述文档中需要哪些属性。可以选择性地指定它,以及其他
架构约束。请参阅 MongoDB 关于可用关键字的文档。 |
3 | properties 与描述类型的架构对象相关。它包含特定于属性的架构约束。object |
4 | firstname 指定文档内字段的约束。在这里,它是一个基于字符串的元素声明
可能的字段值。firstname properties |
5 | address 是一个子文档,用于定义其字段中值的架构。postCode |
您可以通过指定架构文档(即使用 API 解析或构建文档对象)或使用 Spring Data 的 JSON 架构实用程序构建它来提供架构。 是所有 JSON 架构相关操作的入口点。以下示例演示如何使用 JSON 架构:Document
org.springframework.data.mongodb.core.schema
MongoJsonSchema
MongoJsonSchema.builder()
MongoJsonSchema.builder() (1)
.required("lastname") (2)
.properties(
required(string("firstname").possibleValues("luke", "han")), (3)
object("address")
.properties(string("postCode").minLength(4).maxLength(5)))
.build(); (4)
1 | 获取架构构建器,使用流畅的 API 配置架构。 |
2 | 直接配置所需属性,如下所示,或使用更多详细信息(如 3 所示)。 |
3 | 配置所需的 String 类型字段,仅允许 和 值。属性可以是类型化的,也可以是非类型的。使用 的静态导入可使语法稍微更紧凑,并获取入口点,例如 。firstname luke han JsonSchemaProperty string(…) |
4 | 生成架构对象。 |
已经有一些预定义的强类型架构对象( 和 ) 可用
通过网关接口上的静态方法。
但是,您可能需要生成自定义属性验证规则,这些规则可以通过构建器 API 创建,如以下示例所示:JsonSchemaObject
JsonSchemaProperty
// "birthdate" : { "bsonType": "date" }
JsonSchemaProperty.named("birthdate").ofType(Type.dateType());
// "birthdate" : { "bsonType": "date", "description", "Must be a date" }
JsonSchemaProperty.named("birthdate").with(JsonSchemaObject.of(Type.dateType()).description("Must be a date"));
CollectionOptions
提供对集合的架构支持的入口点,如以下示例所示:
$jsonSchema
MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build();
template.createCollection(Person.class, CollectionOptions.empty().schema(schema));
1 | JSON 架构文档始终从其根目录描述整个文档。架构是架构对象本身,可以包含 描述属性和子文档的嵌入式架构对象。 |
2 | required 是一个属性,用于描述文档中需要哪些属性。可以选择性地指定它,以及其他
架构约束。请参阅 MongoDB 关于可用关键字的文档。 |
3 | properties 与描述类型的架构对象相关。它包含特定于属性的架构约束。object |
4 | firstname 指定文档内字段的约束。在这里,它是一个基于字符串的元素声明
可能的字段值。firstname properties |
5 | address 是一个子文档,用于定义其字段中值的架构。postCode |
1 | 获取架构构建器,使用流畅的 API 配置架构。 |
2 | 直接配置所需属性,如下所示,或使用更多详细信息(如 3 所示)。 |
3 | 配置所需的 String 类型字段,仅允许 和 值。属性可以是类型化的,也可以是非类型的。使用 的静态导入可使语法稍微更紧凑,并获取入口点,例如 。firstname luke han JsonSchemaProperty string(…) |
4 | 生成架构对象。 |
生成架构
设置架构可能是一项耗时的任务,我们鼓励每个决定这样做的人真正花时间。
这很重要,架构更改可能很困难。
然而,有时人们可能不想犹豫不决,这就是发挥作用的地方。JsonSchemaCreator
public class Person {
private final String firstname; (1)
private final int age; (2)
private Species species; (3)
private Address address; (4)
private @Field(fieldType=SCRIPT) String theForce; (5)
private @Transient Boolean useTheForce; (6)
public Person(String firstname, int age) { (1) (2)
this.firstname = firstname;
this.age = age;
}
// gettter / setter omitted
}
MongoJsonSchema schema = MongoJsonSchemaCreator.create(mongoOperations.getConverter())
.createSchemaFor(Person.class);
template.createCollection(Person.class, CollectionOptions.empty().schema(schema));
{
'type' : 'object',
'required' : ['age'], (2)
'properties' : {
'firstname' : { 'type' : 'string' }, (1)
'age' : { 'bsonType' : 'int' } (2)
'species' : { (3)
'type' : 'string',
'enum' : ['HUMAN', 'WOOKIE', 'UNKNOWN']
}
'address' : { (4)
'type' : 'object'
'properties' : {
'postCode' : { 'type': 'string' }
}
},
'theForce' : { 'type' : 'javascript'} (5)
}
}
1 | 简单对象属性被视为常规属性。 |
2 | 基元类型被视为必需属性 |
3 | 枚举仅限于可能的值。 |
4 | 检查对象类型属性并将其表示为嵌套文档。 |
5 | String 由转换器转换为的 type 属性。Code |
6 | @Transient 生成架构时将省略属性。 |
_id 使用可转换为“喜欢”的类型的属性将映射到,除非通过注释提供更具体的信息。ObjectId String { type : 'object' } @MongoId |
爪哇岛 | 架构类型 | 笔记 |
---|---|---|
|
|
如果元数据可用。 |
|
|
- |
|
|
- |
|
|
属性包含可能的枚举值。 |
|
|
简单类型数组,除非它是 |
|
|
- |
上面的示例演示了如何从非常精确的类型化源派生架构。
在领域模型中使用多态元素可能会导致 和 泛型类型的架构表示不准确,这些类型很可能表示为没有进一步规范。 允许定义其他详细信息,例如呈现架构时应考虑的嵌套文档类型。Object
<T>
{ type : 'object' }
MongoJsonSchemaCreator.property(…)
class Root {
Object value;
}
class A {
String aValue;
}
class B {
String bValue;
}
MongoJsonSchemaCreator.create()
.property("value").withTypes(A.class, B.class) (1)
{
'type' : 'object',
'properties' : {
'value' : {
'type' : 'object',
'properties' : { (1)
'aValue' : { 'type' : 'string' },
'bValue' : { 'type' : 'string' }
}
}
}
}
1 | 给定类型的属性将合并到一个元素中。 |
MongoDB的无模式方法允许将不同结构的文档存储在一个集合中。
这些可以建模为具有公共基类。
无论选择哪种方法,都可以帮助规避将多个架构合并为一个架构的需要。MongoJsonSchemaCreator.merge(…)
abstract class Root {
String rootValue;
}
class A extends Root {
String aValue;
}
class B extends Root {
String bValue;
}
MongoJsonSchemaCreator.mergedSchemaFor(A.class, B.class) (1)
{
'type' : 'object',
'properties' : { (1)
'rootValue' : { 'type' : 'string' },
'aValue' : { 'type' : 'string' },
'bValue' : { 'type' : 'string' }
}
}
}
1 | 给定类型的属性(及其继承的属性)将合并到一个架构中。 |
具有相同名称的属性需要引用相同的 JSON 架构才能合并。
下面的示例显示了由于数据类型不匹配而无法自动合并的定义。
在这种情况下,必须向 提供 。
|
1 | 简单对象属性被视为常规属性。 |
2 | 基元类型被视为必需属性 |
3 | 枚举仅限于可能的值。 |
4 | 检查对象类型属性并将其表示为嵌套文档。 |
5 | String 由转换器转换为的 type 属性。Code |
6 | @Transient 生成架构时将省略属性。 |
_id 使用可转换为“喜欢”的类型的属性将映射到,除非通过注释提供更具体的信息。ObjectId String { type : 'object' } @MongoId |
爪哇岛 | 架构类型 | 笔记 |
---|---|---|
|
|
如果元数据可用。 |
|
|
- |
|
|
- |
|
|
属性包含可能的枚举值。 |
|
|
简单类型数组,除非它是 |
|
|
- |
1 | 给定类型的属性将合并到一个元素中。 |
1 | 给定类型的属性(及其继承的属性)将合并到一个架构中。 |
具有相同名称的属性需要引用相同的 JSON 架构才能合并。
下面的示例显示了由于数据类型不匹配而无法自动合并的定义。
在这种情况下,必须向 提供 。
|
加密字段
MongoDB 4.2 字段级加密允许直接加密单个属性。
设置 JSON 架构时,可以将属性包装在加密属性中,如以下示例所示。
MongoJsonSchema schema = MongoJsonSchema.builder()
.properties(
encrypted(string("ssn"))
.algorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")
.keyId("*key0_id")
).build();
与其手动定义加密字段,不如利用注释,如下面的代码片段所示。@Encrypted
@Document
@Encrypted(keyId = "xKVup8B1Q+CkHaVRx+qa+g==", algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Random") (1)
static class Patient {
@Id String id;
String name;
@Encrypted (2)
String bloodType;
@Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") (3)
Integer ssn;
}
1 | 将为 设置的默认加密设置。encryptMetadata |
2 | 使用默认加密设置的加密字段。 |
3 | 覆盖默认加密算法的加密字段。 |
注解支持通过 SpEL 表达式解析 keyId。
为此,需要提供额外的环境元数据(通过 )。
该函数通过 an 定义,如下面的代码片段所示。
提供自定义扩展提供了计算 keyId 的最灵活方法。
|
1 | 将为 设置的默认加密设置。encryptMetadata |
2 | 使用默认加密设置的加密字段。 |
3 | 覆盖默认加密算法的加密字段。 |
注解支持通过 SpEL 表达式解析 keyId。
为此,需要提供额外的环境元数据(通过 )。
该函数通过 an 定义,如下面的代码片段所示。
提供自定义扩展提供了计算 keyId 的最灵活方法。
|
JSON 架构类型
下表显示了支持的 JSON 架构类型:
架构类型 | Java 类型 | 架构属性 |
---|---|---|
|
- |
|
|
|
|
|
任何数组,除了 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
untyped 是所有类型化架构类型继承的泛型类型。它为类型化的架构类型提供所有架构属性。untyped |
有关详细信息,请参阅$jsonSchema。
架构类型 | Java 类型 | 架构属性 |
---|---|---|
|
- |
|
|
|
|
|
任何数组,除了 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
untyped 是所有类型化架构类型继承的泛型类型。它为类型化的架构类型提供所有架构属性。untyped |