此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Data MongoDB 4.4.0! |
JSON 架构
从版本 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 架构文档始终从其根开始描述整个文档。Schema 本身是一个 schema 对象,它可以包含 描述属性和子文档的嵌入式架构对象。 |
2 | required 是一个属性,用于描述文档中需要哪些属性。它可以是可选的,也可以与其他
架构约束。请参阅 MongoDB 的可用关键字文档。 |
3 | properties 与描述类型的 schema 对象相关。它包含特定于属性的架构约束。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 | 获取架构构建器以使用 Fluent API 配置架构。 |
2 | 直接配置所需属性(如此处所示),或使用 3 中的更多详细信息配置。 |
3 | 配置所需的 String-typed 字段,仅允许 和 值。属性可以是类型化的,也可以是非类型的。使用 static import of 可使语法稍微紧凑一些,并获取入口点,例如 .firstname luke han JsonSchemaProperty string(…) |
4 | 构建 schema 对象。 |
已经有一些预定义的强类型架构对象( 和 )可用
通过网关接口上的静态方法。
但是,您可能需要构建自定义属性验证规则,这些规则可以通过生成器 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));
生成 Schema
设置 Schema 可能是一项耗时的任务,我们鼓励每个决定这样做的人真正花时间。
重要的是,架构更改可能很困难。
然而,有时人们可能不想拒绝它,这就是发挥作用的地方。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 properties 在生成架构时被省略。 |
_id 使用可转换为 like 类型的 properties 会被映射到,除非通过 Comments 有更具体的信息可用。ObjectId String { type : 'object' } @MongoId |
Java | 架构类型 | 笔记 |
---|---|---|
|
|
with if metadata available. |
|
|
- |
|
|
- |
|
|
其中 property 保存可能的枚举值。 |
|
|
simple 类型数组,除非它是 |
|
|
- |
上面的示例演示了如何从非常精确的类型化源派生架构。
在域模型中使用多态元素可能会导致泛型类型和泛型类型的模式表示不准确,这些泛型类型可能会表示为没有进一步规范。 允许定义其他详细信息,如渲染架构时应考虑的嵌套文档类型。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 架构才能进行组合。
以下示例显示了由于数据类型不匹配而无法自动合并的定义。
在这种情况下,必须向 提供 。
|
加密字段
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 | 加密字段覆盖默认加密算法。 |
Annotation 支持通过 SpEL 表达式解析 keyId。
为此,需要并提供其他环境元数据(通过 )。
该函数是通过 an 定义的,如下面的代码片段所示。
提供自定义扩展提供了最灵活的 keyId 计算方式。
|
JSON 架构类型
下表显示了支持的 JSON 架构类型:
架构类型 | Java 类型 | 架构属性 |
---|---|---|
|
- |
|
|
|
|
|
除 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
|
|
(无) |
untyped 是所有类型化架构类型都继承的泛型类型。它为类型化架构类型提供所有架构属性。untyped |
有关更多信息,请参阅 $jsonSchema。