乐趣区

关于spring:Spring认证中国教育管理中心Spring-Data-MongoDB教程五

原题目:Spring 认证中国教育管理中心 -Spring Data MongoDB 教程五(内容起源:Spring 中国教育管理中心)

11.6.5.GeoJSON 反对
MongoDB 反对 GeoJSON 和用于天文空间数据的简略(传统)坐标对。这些格局既可用于存储数据,也可用于查问数据。请参阅无关 GeoJSON 反对的 MongoDB 手册以理解要求和限度。

域类中的 GeoJSON 类型
在域类中应用 GeoJSON 类型很简略。该
org.springframework.data.mongodb.core.geo 包中蕴含的类型,如 GeoJsonPoint,GeoJsonPolygon 和其余。这些类型是对现有 org.springframework.data.geo 类型的扩大。以下示例应用了一个 GeoJsonPoint:

public class Store {

String id;

/**
 * location is stored in GeoJSON format.
 * {
 *   "type" : "Point",
 *   "coordinates" : [x, y]
 * }
 */
GeoJsonPoint location;

}
Spring 认证中国教育管理中心 -Spring Data MongoDB 教程五
存储库查询方法中的 GeoJSON 类型
应用 GeoJSON 类型作为存储库查问参数会 $geometry 在创立查问时强制应用运算符,如以下示例所示:

public interface StoreRepository extends CrudRepository<Store, String> {

List<Store> findByLocationWithin(Polygon polygon);  

}

/*

  • {
  • “location”: {
  • “$geoWithin”: {
  • “$geometry”: {
  • “type”: “Polygon”,
  • “coordinates”: [
  • [
  • [-73.992514,40.758934],
  • [-73.961138,40.760348],
  • [-73.991658,40.730006],
  • [-73.992514,40.758934]
  • ]
  • ]
  • }
  • }
  • }
  • }
    */

repo.findByLocationWithin(
new GeoJsonPolygon(

new Point(-73.992514, 40.758934),
new Point(-73.961138, 40.760348),
new Point(-73.991658, 40.730006),
new Point(-73.992514, 40.758934)));                 

/*

  • {
  • “location” : {
  • “$geoWithin” : {
  • “$polygon” : [[-73.992514,40.758934] , [-73.961138,40.760348] , [-73.991658,40.730006] ]
  • }
  • }
  • }
    */

repo.findByLocationWithin(
new Polygon(

new Point(-73.992514, 40.758934),
new Point(-73.961138, 40.760348),
new Point(-73.991658, 40.730006)));

Spring 认证中国教育管理中心 -Spring Data MongoDB 教程五
应用 commons 类型的存储库办法定义容许应用 GeoJSON 和遗留格局调用它。

应用 GeoJSON 类型来应用 $geometry 运算符。

请留神,GeoJSON 多边形须要定义一个关闭的环。

应用旧格局 $polygon 运算符。

度量和间隔计算
而后 MongoDB$geoNear 运算符容许应用 GeoJSON Point 或旧坐标对。

NearQuery.near(new Point(-73.99171, 40.738868))
{
“$geoNear”: {

//...
"near": [-73.99171, 40.738868]

}
}
NearQuery.near(new GeoJsonPoint(-73.99171, 40.738868))
{
“$geoNear”: {

//...
"near": {"type": "Point", "coordinates": [-73.99171, 40.738868] }

}
}
只管在语法上有所不同,但无论汇合中的指标 Document 应用什么格局,服务器都能够承受。

* 间隔计算存在微小差别。应用旧格局对地球上的弧度进行操作,如球体,而 GeoJSON 格局应用 Meters。

为防止重大的头痛,请确保将 设置 Metric 为所需的测量单位,以确保正确计算间隔。

换句话说:

假如您有 5 个文件,如下所示:

{

"_id" : ObjectId("5c10f3735d38908db52796a5"),
"name" : "Penn Station",
"location" : {"type" : "Point", "coordinates" : [  -73.99408, 40.75057] }

}
{

"_id" : ObjectId("5c10f3735d38908db52796a6"),
"name" : "10gen Office",
"location" : {"type" : "Point", "coordinates" : [ -73.99171, 40.738868] }

}
{

"_id" : ObjectId("5c10f3735d38908db52796a9"),
"name" : "City Bakery",
"location" : {"type" : "Point", "coordinates" : [ -73.992491, 40.738673] }

}
{

"_id" : ObjectId("5c10f3735d38908db52796aa"),
"name" : "Splash Bar",
"location" : {"type" : "Point", "coordinates" : [ -73.992491, 40.738673] }

}
{

"_id" : ObjectId("5c10f3735d38908db52796ab"),
"name" : "Momofuku Milk Bar",
"location" : {"type" : "Point", "coordinates" : [ -73.985839, 40.731698] }

}
Spring 认证中国教育管理中心 -Spring Data MongoDB 教程五
[-73.99171, 40.738868] 应用 GeoJSON 获取 400 米半径内的所有文档如下所示:

示例 77. GeoNear 和 GeoJSON

{

"$geoNear": {
    "maxDistance": 400, 
    "num": 10,
    "near": {type: "Point", coordinates: [-73.99171, 40.738868] },
    "spherical":true, 
    "key": "location",
    "distanceField": "distance"
}

}
返回以下 3 个文件:

{

"_id" : ObjectId("5c10f3735d38908db52796a6"),
"name" : "10gen Office",
"location" : {"type" : "Point", "coordinates" : [ -73.99171, 40.738868] }
"distance" : 0.0 

}
{

"_id" : ObjectId("5c10f3735d38908db52796a9"),
"name" : "City Bakery",
"location" : {"type" : "Point", "coordinates" : [ -73.992491, 40.738673] }
"distance" : 69.3582262492474 

}
{

"_id" : ObjectId("5c10f3735d38908db52796aa"),
"name" : "Splash Bar",
"location" : {"type" : "Point", "coordinates" : [ -73.992491, 40.738673] }
"distance" : 69.3582262492474 

}
到中心点的最大间隔(以米为单位)。

GeoJSON 总是在一个球体上运行。

到中心点的间隔(以米为单位)。

当初,当应用旧坐标对时,如前所述,对弧度进行操作。所以咱们应用 Metrics#KILOMETERS when constructing the `$geoNear 命令。在 Metric 确保使乘数设置正确的间隔。

示例 78. 带有传统坐标对的 GeoNear

{

"$geoNear": {
    "maxDistance": 0.0000627142377, 
    "distanceMultiplier": 6378.137, 
    "num": 10,
    "near": [-73.99171, 40.738868],
    "spherical":true, 
    "key": "location",
    "distanceField": "distance"
}

}
像 GeoJSON 变体一样返回 3 个文档:

{

"_id" : ObjectId("5c10f3735d38908db52796a6"),
"name" : "10gen Office",
"location" : {"type" : "Point", "coordinates" : [ -73.99171, 40.738868] }
"distance" : 0.0 

}
{

"_id" : ObjectId("5c10f3735d38908db52796a9"),
"name" : "City Bakery",
"location" : {"type" : "Point", "coordinates" : [ -73.992491, 40.738673] }
"distance" : 0.0693586286032982 

}
{

"_id" : ObjectId("5c10f3735d38908db52796aa"),
"name" : "Splash Bar",
"location" : {"type" : "Point", "coordinates" : [ -73.992491, 40.738673] }
"distance" : 0.0693586286032982 

}
到中心点的最大间隔(以弧度为单位)。

间隔乘数所以咱们失去公里作为后果间隔。

确保咱们对 2d_sphere 索引进行操作。

间隔中心点的间隔以公里为单位 - 乘以 1000 以匹配 GeoJSON 变体的米。

GeoJSON 杰克逊模块
通过应用 Web 反对,Spring Data 将额定的 Jackson 注册 Modules 到 ObjectMapper 用于反 / 序列化常见 Spring Data 域类型。请参阅 Spring Data Jackson Modules 局部以理解无关此性能的基础架构设置的更多信息。

MongoDB 模块 JsonDeserializer 通过 GeoJsonConfiguration 公开 GeoJsonModule.

org.springframework.data.mongodb.core.geo.GeoJsonPoint
org.springframework.data.mongodb.core.geo.GeoJsonMultiPoint
org.springframework.data.mongodb.core.geo.GeoJsonLineString
org.springframework.data.mongodb.core.geo.GeoJsonMultiLineString
org.springframework.data.mongodb.core.geo.GeoJsonPolygon
org.springframework.data.mongodb.core.geo.GeoJsonMultiPolygon
该 GeoJsonModule 只注册 JsonDeserializer 小号!
要 ObjectMapper 为 JsonSerializers 装备一组对称的 s,您须要为 手动配置这些 sObjectMapper 或提供作为 Spring
BeanSpringDataJacksonModules 公开的自定义配置 GeoJsonModule.serializers()。

class GeoJsonConfiguration implements SpringDataJacksonModules {

@Bean
public Module geoJsonSerializers() {return GeoJsonModule.serializers();
}

}
下一个次要版本 (4.0) 将默认为 GeoJSON 类型注册 JsonDeserializers 和 JsonSerializers。

11.6.6. 全文查问
从 MongoDB 2.6 版开始,您能够应用 $text 运算符运行全文查问。办法和操作具体到全文查问是可用的 TextQuery 和 TextCriteria。进行全文搜寻时,请参阅 MongoDB 参考以理解其行为和限度。

全文检索
在理论应用全文搜寻之前,您必须正确设置搜寻索引。无关如何创立索引构造的更多详细信息,请参阅文本索引。以下示例显示了如何设置全文搜寻:

db.foo.createIndex(
{
title : “text”,
content : “text”
},
{
weights : {

          title : 3
        }

}
)
coffee cake 能够按如下形式定义和运行查问搜寻:

例 79. 全文查问

Query query = TextQuery
.queryText(new TextCriteria().matchingAny(“coffee”, “cake”));

List<Document> page = template.find(query, Document.class);
依据 weights 用处按相关性对后果进行排序 TextQuery.sortByScore。

示例 80. 全文查问 – 按分数排序

Query query = TextQuery
.queryText(new TextCriteria().matchingAny(“coffee”, “cake”))
.sortByScore()
.includeScore();

List<Document> page = template.find(query, Document.class);
应用 score 属性按触发的相关性对后果进行排序.sort({‘score’: {‘$meta’: ‘textScore’}})。

用于 TextQuery.includeScore()在后果中蕴含计算出的相关性 Document。

您能够通过在搜索词前加上 - 或应用来排除搜索词,notMatching 如下例所示(请留神,这两行具备雷同的成果,因而是多余的):

// search for ‘coffee’ and not ‘cake’
TextQuery.queryText(new TextCriteria().matching(“coffee”).matching(“-cake”));
TextQuery.queryText(new TextCriteria().matching(“coffee”).notMatching(“cake”));
TextCriteria.matching 按原样应用提供的术语。因而,您能够通过将短语放在双引号之间来定义短语(例如,\”coffee cake\”)或应用 byTextCriteria.phrase. 上面的示例显示了定义短语的两种形式:

// search for phrase ‘coffee cake’
TextQuery.queryText(new TextCriteria().matching(“\”coffee cake\””));
TextQuery.queryText(new TextCriteria().phrase(“coffee cake”));
您能够应用 上的相应办法为 $caseSensitive 和设置标记。请留神,这两个可选标记已在 MongoDB 3.2 中引入,除非明确设置,否则不会蕴含在查问中。$
diacriticSensitiveTextCriteria

11.6.7. 校对
从 3.4 版本开始,MongoDB 反对用于汇合和索引创立以及各种查问操作的排序规定。排序规定依据 ICU 排序规定定义字符串比拟规定。归类文档由封装在 中的各种属性组成 Collation,如上面的清单所示:

Collation collation = Collation.of(“fr”)

.strength(ComparisonLevel.secondary()

.includeCase())

.numericOrderingEnabled()

.alternate(Alternate.shifted().punct())

.forwardDiacriticSort()

.normalizationEnabled();
Collation 创立时须要语言环境。这能够是语言环境的字符串示意模式,a Locale(思考语言、国家和变体)或 CollationLocale. 创立时必须应用语言环境。

整顿强度定义了示意字符之间差别的比拟级别。您能够依据所选强度配置各种选项(辨别大小写、大小写排序等)。

指定是将数字字符串作为数字还是作为字符串进行比拟。

指定排序规定是否应将空格和标点符号视为根本字符以进行比拟。

指定带有变音符号的字符串是否从字符串的前面排序,例如应用某些法语词典排序。

指定是否查看文本是否须要归一化以及是否进行归一化。

排序规定可用于创立汇合和索引。如果您创立一个指定排序规定的汇合,除非您指定不同的排序规定,否则该排序规定将利用于索引创立和查问。排序规定对整个操作无效,不能在每个字段的根底上指定。

与其余元数据一样,排序规定能够通过 正文的 collation 属性从域类型派生 @Document,并将在运行查问、创立汇合或索引时间接利用。

当 MongoDB 在第一次交互时主动创立汇合时,将不会应用带正文的排序规定。这将须要额定的商店交互提早整个过程。请
MongoOperations.createCollection 在这些状况下应用。

Collation french = Collation.of(“fr”); Collation german = Collation.of(“de”); template.createCollection(Person.class, CollectionOptions.just(collation)); template.indexOps(Person.class).ensureIndex(new Index(“name”, Direction.ASC).collation(german));

如果未指定排序规定 (Collation.simple()),MongoDB 将应用简略的二进制比拟。

对汇合操作应用排序规定是 Collation 在查问或操作选项中指定实例的问题,如以下两个示例所示:

示例 81. 应用排序规定与 find

Collation collation = Collation.of(“de”);

Query query = new Query(Criteria.where(“firstName”).is(“Amél”)).collation(collation);

List<Person> results = template.find(query, Person.class);
示例 82. 应用排序规定与 aggregate

Collation collation = Collation.of(“de”);

AggregationOptions options = AggregationOptions.builder().collation(collation).build();

Aggregation aggregation = newAggregation(
project(“tags”),
unwind(“tags”),
group(“tags”)

.count().as("count")

).withOptions(options);

AggregationResults<TagCount> results = template.aggregate(aggregation, “tags”, TagCount.class);
仅当用于操作的排序规定与索引排序规定匹配时才应用索引。

MongoDB RepositoriesCollations 通过注解的 collation 属性反对 @Query。

示例 83. 对存储库的整顿反对

public interface PersonRepository extends MongoRepository<Person, String> {

@Query(collation = “en_US”)
List<Person> findByFirstname(String firstname);

@Query(collation = “{ ‘locale’ : ‘en_US’}”)
List<Person> findPersonByFirstname(String firstname);

@Query(collation = “?1”)
List<Person> findByFirstname(String firstname, Object collation);

@Query(collation = “{ ‘locale’ : ‘?1’}”)
List<Person> findByFirstname(String firstname, String collation);

List<Person> findByFirstname(String firstname, Collation collation);

@Query(collation = “{ ‘locale’ : ‘en_US’}”)
List<Person> findByFirstname(String firstname, @Nullable Collation collation);
}
动态归类定义导致{‘locale’ : ‘en_US’}.

动态归类定义导致{‘locale’ : ‘en_US’}.

动静整顿取决于第二个办法参数。容许的类型包含 String(eg. ‘en_US’), Locacle(eg. Locacle.US) 和 Document(eg. new Document(“locale”, “en_US”))

动静整顿取决于第二个办法参数。

将 Collation 办法参数利用于查问。

该 Collation 办法的参数笼罩默认 collation 的 @Query,如果不为空。

如果您为存储库查找器办法启用了主动索引创立,则在创立索引时将包含潜在的动态排序规定定义,如 (1) 和 (2) 所示。

最 Collation 具体的 outroules 可能定义了其余的 outroules。这意味着办法参数超过查询方法正文超过 doamin 类型正文。

JSON 架构
从 version 3.6 开始,MongoDB 反对依据提供的 JSON Schema 验证文档的汇合。创立汇合时能够定义架构自身以及验证操作和级别,如以下示例所示:

示例 84. 示例 JSON 模式

{
“type”: “object”,

“required”: [“firstname”, “lastname”],

“properties”: {

"firstname": {                                                         
  "type": "string",
  "enum": ["luke", "han"]
},
"address": {                                                           
  "type": "object",
  "properties": {"postCode": { "type": "string", "minLength": 4, "maxLength": 5}
  }
}

}
}
JSON 模式文档总是从其根开始形容整个文档。模式是模式对象自身,它能够蕴含形容属性和子文档的嵌入模式对象。

required 是形容文档中须要哪些属性的属性。它能够与其余模式束缚一起抉择指定。请参阅无关可用关键字的 MongoDB 文档。

properties 与形容 object 类型的模式对象相干。它蕴含特定于属性的架构束缚。

firstname 为 firsname 文档内的字段指定束缚。在这里,它是一个基于字符串的 properties 元素,用于申明可能的字段值。

address 是为其 postCode 字段中的值定义架构的子文档。

您能够通过指定模式文档(即,通过应用 DocumentAPI 解析或构建文档对象)或应用 Spring Data 的 JSON 模式实用程序构建它来提供模式
org.springframework.data.mongodb.core.schema。MongoJsonSchema 是所有与 JSON 模式相干的操作的入口点。以下示例显示了如何应用 MongoJsonSchema.builder() 创立 JSON 模式:

示例 85. 创立一个 JSON 模式

MongoJsonSchema.builder()

.required("lastname")                                                    

.properties(required(string("firstname").possibleValues("luke", "han")), 

            object("address")
                 .properties(string("postCode").minLength(4).maxLength(5)))

.build();                                        

获取模式构建器以应用晦涩的 API 配置模式。

间接配置所需的属性,如此处所示,或应用更多详细信息如 3 所示。

配置所需的字符串类型 firstname 字段,仅容许 luke 和 han 值。属性能够是有类型的或无类型的。应用动态导入 JsonSchemaProperty 使语法略微紧凑一些并取得入口点,例如 string(…).

构建架构对象。应用模式创立汇合或查问文档。

曾经有一些预约义和强类型模式对象(JsonSchemaObject 和 JsonSchemaProperty)通过网关接口上的静态方法可用。然而,您可能须要构建自定义属性验证规定,能够通过构建器 API 创立,如下例所示:

// “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 为汇合提供架构反对的入口点,如以下示例所示:

示例 86. 创立汇合 $jsonSchema

MongoJsonSchema schema = MongoJsonSchema.builder().required(“firstname”, “lastname”).build();

template.createCollection(Person.class, CollectionOptions.empty().schema(schema));
生成模式
设置模式可能是一项耗时的工作,咱们激励每个决定这样做的人真正花工夫。重要的是,架构更改可能很艰难。然而,有时人们可能不想回绝它,这就是 JsonSchemaCreator 发挥作用的中央。

JsonSchemaCreator 它的默认实现会生成 MongoJsonSchema 映射根底构造提供的域外类型元数据。这意味着,会思考带正文的属性以及潜在的自定义转换。

例 87. 从域类型生成 Json Schema

public class Person {

private final String firstname;                   
private final int age;                            
private Species species;                          
private Address address;                          
private @Field(fieldType=SCRIPT) String theForce; 
private @Transient Boolean useTheForce;           

public Person(String firstname, int age) {         

    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'],                     
'properties' : {'firstname' : { 'type' : 'string'},  
    'age' : {'bsonType' : 'int'}        
    'species' : {                         
        'type' : 'string',
        'enum' : ['HUMAN', 'WOOKIE', 'UNKNOWN']
    }
    'address' : {                         
        'type' : 'object'
        'properties' : {'postCode' : { 'type': 'string'}
        }
    },
    'theForce' : {'type' : 'javascript'} 
 }

}
简略对象属性被视为惯例属性。

原始类型被认为是必须的属性

枚举仅限于可能的值。

对象类型属性被查看并示意为嵌套文档。

StringCode 由转换器转换为的类型属性。

@Transient 生成模式时省略属性。

_id 应用能够转换为 ObjectIdlike 类型的属性将 String 被映射到,{type : ‘object’} 除非通过 @MongoId 正文有更具体的信息可用。

Spring 认证中国教育管理中心 -Spring Data MongoDB 教程五
查问匹配 JSON Schema 的汇合
您能够应用架构来查问与 JSON 架构定义的给定构造匹配的文档的任何汇合,如以下示例所示:

示例 88. 查问匹配 a 的文档 $jsonSchema

MongoJsonSchema schema = MongoJsonSchema.builder().required(“firstname”, “lastname”).build();

template.find(query(matchingDocumentStructure(schema)), Person.class);
加密字段
MongoDB 4.2 字段级加密容许间接加密单个属性。

如下例所示,在设置 JSON 架构时,能够将属性包装在加密属性中。

示例 89. 通过 Json Schema 的客户端字段级加密

MongoJsonSchema schema = MongoJsonSchema.builder()

.properties(encrypted(string("ssn"))
        .algorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")
        .keyId("*key0_id")
).build();

能够利用 @Encrypted 正文,而不是手动定义加密字段,如上面的代码片段所示。

示例 90. 通过 Json Schema 的客户端字段级加密

@Document
@Encrypted(keyId = “xKVup8B1Q+CkHaVRx+qa+g==”, algorithm = “AEAD_AES_256_CBC_HMAC_SHA_512-Random”)
static class Patient {

@Id String id;
String name;

@Encrypted 
String bloodType;

@Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") 
Integer ssn;

}
将为 设置的默认加密设置 encryptMetadata。

应用默认加密设置的加密字段。

笼罩默认加密算法的加密字段。

该 @EncryptedAnnoation 反对解决通过布局环境地政司表达式 keyIds。为此,MappingContext 须要并且必须提供额定的环境元数据(通过)。

@Document
@Encrypted(keyId = “#{mongocrypt.keyId(#target)}”)
static class Patient {

@Id String id;
String name;

@Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Random")
String bloodType;

@Encrypted(algorithm = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")
Integer ssn;

}

MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext);
MongoJsonSchema patientSchema = schemaCreator

.filter(MongoJsonSchemaCreator.encryptedOnly())
.createSchemaFor(Patient.class);

该 mongocrypt.keyId 函数是通过 定义的
EvaluationContextExtension,如上面的代码片段所示。提供自定义扩大提供了最灵便的计算 keyId 的形式。

public class EncryptionExtension implements EvaluationContextExtension {

@Override
public String getExtensionId() {return "mongocrypt";}

@Override
public Map<String, Function> getFunctions() {return Collections.singletonMap("keyId", new Function(getMethod("computeKeyId", String.class), this));
}

public String computeKeyId(String target) {// ... lookup via target element name}

}
要将派生加密设置与
AutoEncryptionSettingsSpring Boot 应用程序联合应用,请应用 MongoClientSettingsBuilderCustomizer.

@Bean
MongoClientSettingsBuilderCustomizer customizer(MappingContext mappingContext) {

return (builder) -> {

    // ... keyVaultCollection, kmsProvider, ...

    MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext);
    MongoJsonSchema patientSchema = schemaCreator
        .filter(MongoJsonSchemaCreator.encryptedOnly())
        .createSchemaFor(Patient.class);

    AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
        .keyVaultNamespace(keyVaultCollection)
        .kmsProviders(kmsProviders)
        .extraOptions(extraOpts)
        .schemaMap(Collections.singletonMap("db.patient", patientSchema.schemaDocument().toBsonDocument()))
        .build();

    builder.autoEncryptionSettings(autoEncryptionSettings);
};

}
确保将驱动程序设置
com.mongodb.AutoEncryptionSettings 为应用客户端加密。MongoDB 不反对对所有字段类型进行加密。特定数据类型须要确定性加密以保留相等比拟性能。

退出移动版