共计 10224 个字符,预计需要花费 26 分钟才能阅读完成。
原题目:Spring 认证中国教育管理中心 -Spring Data MongoDB 教程六(内容起源:Spring 中国教育管理中心)
JSON 模式类型
下表显示了反对的 JSON 架构类型:
Spring 认证中国教育管理中心 -Spring Data MongoDB 教程六
Spring 认证中国教育管理中心 -Spring Data MongoDB 教程六
untyped 是由所有类型化架构类型继承的泛型类型。它为 untyped 类型化架构类型提供所有架构属性。
无关更多信息,请参阅 $jsonSchema。
11.6.8. 晦涩的模板 API
MongoOperations 当波及到与 MongoDB 的更多低级交互时,该接口是外围组件之一。它提供了宽泛的办法,涵盖了从汇合创立、索引创立和 CRUD 操作到更高级性能(例如 Map-Reduce 和聚合)的需要。您能够为每个办法找到多个重载。它们中的大多数涵盖了 API 的可选或可为空的局部。
FluentMongoOperations 为通用办法提供更窄的接口,MongoOperations 并提供更易读、更晦涩的 API。入口点(insert(…)、find(…)、update(…)和其余)遵循基于要运行的操作的天然命名模式。从入口点开始,API 旨在仅提供依赖于上下文的办法,这些办法导致调用理论 MongoOperations 对应方的终止办法——all 以下示例中的办法:
List<SWCharacter> all = ops.find(SWCharacter.class)
.inCollection(“star-wars”)
.all();
如果应用类名 SWCharacter 定义汇合 @Document 或应用类名作为汇合名,则跳过此步骤,这很好。
有时,在 MongoDB 中集持有不同的类型,如实体 Jedi 的汇合内 SWCharacters。要为 Query 和返回值映射应用不同的类型,您能够应用 as(Class<?> targetType)不同的映射后果,如以下示例所示:
List<Jedi> all = ops.find(SWCharacter.class)
.as(Jedi.class)
.matching(query(where(“jedi”).is(true)))
.all();
查问字段依据 SWCharacter 类型进行映射。
后果文档被映射到 Jedi.
您能够通过提供指标类型间接将投影利用于后果文档 as(Class<?>)。
应用投影容许 MongoTemplate 通过限度对投影指标类型所需字段的理论响应来优化后果映射。只有 Query 自身不蕴含任何字段限度并且指标类型是关闭接口或 DTO 投影,这实用。
能够检索单个实体和检索多个实体作为一个之间切换 List 或 Stream 通过终止办法:first(),one(),all(),或 stream()。
应用 编写天文空间查问时 near(NearQuery),终止办法的数量将更改为仅包含对 geoNear 在 MongoDB 中运行命令无效的办法(将实体作为 GeoResult 内获取 GeoResults),如以下示例所示:
GeoResults<Jedi> results = mongoOps.query(SWCharacter.class)
.as(Jedi.class)
.near(alderaan) // NearQuery.near(-73.9667, 40.78).maxDis…
.all();
11.6.9.Kotlin 的类型平安查问
Kotlin 通过其语言语法和扩大零碎反对特定畛域的语言创立。Spring Data MongoDB 附带一个 Kotlin 扩大,用于 Criteria 应用 Kotlin 属性援用来构建类型平安查问。应用此扩大的查问通常受害于进步的可读性。大多数关键字 Criteria 都有匹配的 Kotlin 扩展名,例如 inValues 和 regex。
思考以下解释类型平安查问的示例:
import org.springframework.data.mongodb.core.query.*
mongoOperations.find<Book>(
Query(Book::title isEqualTo “Moby-Dick”)
)
mongoOperations.find<Book>(
Query(titlePredicate = Book::title exists true)
)
mongoOperations.find<Book>(
Query(
Criteria().andOperator(
Book::price gt 5,
Book::price lt 10
))
)
// Binary operators
mongoOperations.find<BinaryMessage>(
Query(BinaryMessage::payload bits { allClear(0b101) })
)
// Nested Properties (i.e. refer to “book.author”)
mongoOperations.find<Book>(
Query(Book::author / Author::name regex “^H”)
)
Spring 认证中国教育管理中心 -Spring Data MongoDB 教程六
isEqualTo() 是一个接收器类型的中断扩大函数 KProperty<T>,返回 Criteria.
对于按位运算符,传递一个 lambda 参数,您能够在其中调用
Criteria.BitwiseCriteriaOperators.
要结构嵌套属性,请应用 / 字符(重载运算符 div)。
11.6.10. 其余查问选项
MongoDB 提供了多种将元信息(如正文或批量大小)利用于查问的 Query 办法。间接应用 API 有几种办法能够用于这些选项。
Query query = query(where(“firstname”).is(“luke”))
.comment("find luke")
.batchSize(100)
评论流传到 MongoDB 配置文件日志。
每个响应批次中要返回的文档数。
在存储库级别,@Meta 正文提供了以申明形式增加查问选项的办法。
@Meta(comment = “find luke”, batchSize = 100, flags = { SLAVE_OK})
List<Person> findByFirstname(String firstname);
11.7. 按示例查问
11.7.1. 介绍
本章介绍了 Query by Example 并解释了如何应用它。
示例查问 (QBE) 是一种用户敌对的查问技术,具备简略的界面。它容许动态创建查问,并且不须要您编写蕴含字段名称的查问。事实上,Query by Example 基本不须要您应用特定于商店的查询语言编写查问。
11.7.2. 用法
Query by Example API 由三局部组成:
探针:具备填充字段的域对象的理论示例。
ExampleMatcher:ExampleMatcher 蕴含无关如何匹配特定字段的详细信息。它能够在多个示例中重复使用。
Example: AnExample 由探针和 ExampleMatcher. 它用于创立查问。
Query by Example 非常适合以下几个用例:
应用一组动态或动静束缚查问您的数据存储。
频繁重构域对象而不用放心毁坏现有查问。
独立于底层数据存储 API 工作。
Query by Example 也有几个限度:
不反对嵌套或分组的属性束缚,例如 firstname = ?0 or (firstname = ?1 and lastname = ?2).
仅反对字符串的开始 / 蕴含 / 完结 / 正则表达式匹配以及其余属性类型的准确匹配。
在开始应用 Query by Example 之前,您须要有一个域对象。首先,为您的存储库创立一个接口,如以下示例所示:
示例 91. 示例 Person 对象
public class Person {
@Id
private String id;
private String firstname;
private String lastname;
private Address address;
// … getters and setters omitted
}
后面的示例显示了一个简略的域对象。您能够应用它来创立 Example. 默认状况下,null 疏忽具备值的字段,并应用商店特定的默认值匹配字符串。
将属性蕴含在 Query by Example 规范中是基于可空性。除非疏忽属性门路,否则始终蕴含应用原始类型 (int, double, …)的属性。
能够应用 of 工厂办法或应用 ExampleMatcher. Example 是不可变的。以下清单显示了一个简略的示例:
示例 92. 简略示例
Person person = new Person();
person.setFirstname(“Dave”);
Example<Person> example = Example.of(person);
创立域对象的新实例。
设置要查问的属性。
创立 Example.
您能够应用存储库运行示例查问。为此,让您的存储库接口扩大 QueryByExampleExecutor<T>. 以下清单显示了 QueryByExampleExecutor 界面的摘录:
例 93. QueryByExampleExecutor
public interface QueryByExampleExecutor<T> {
<S extends T> S findOne(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example);
// … more functionality omitted.
}
11.7.3. 示例匹配器
示例不限于默认设置。您能够应用 为字符串匹配、空值解决和特定于属性的设置指定本人的默认值 ExampleMatcher,如以下示例所示:
示例 94. 具备自定义匹配的示例匹配器
Person person = new Person();
person.setFirstname(“Dave”);
ExampleMatcher matcher = ExampleMatcher.matching()
.withIgnorePaths(“lastname”)
.withIncludeNullValues()
.withStringMatcher(StringMatcher.ENDING);
Example<Person> example = Example.of(person, matcher);
创立域对象的新实例。
设置属性。
创立一个 ExampleMatcher 以冀望所有值匹配。即便没有进一步的配置,它也能够在这个阶段应用。
结构一个新 ExampleMatcher 的疏忽 lastname 属性门路。
结构一个 newExampleMatcher 以疏忽 lastname 属性门路并蕴含空值。
结构一个 newExampleMatcher 来疏忽 lastname 属性门路,蕴含空值,并执行后缀字符串匹配。
创立一个新的 Example 基于域对象和配置上 ExampleMatcher。
默认状况下,ExampleMatcher 冀望在探测器上设置的所有值都匹配。如果要取得与任何隐式定义的谓词匹配的后果,请应用
ExampleMatcher.matchingAny().
您能够为单个属性指定行为(例如“名字”和“姓氏”,或者对于嵌套属性,“address.city”)。您能够应用匹配选项和辨别大小写来调整它,如以下示例所示:
示例 95. 配置匹配器选项
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher(“firstname”, endsWith())
.withMatcher(“lastname”, startsWith().ignoreCase());
}
另一种配置匹配器选项的办法是应用 lambdas(在 Java 8 中引入)。这种办法创立了一个回调,要求实现者批改匹配器。您不须要返回匹配器,因为配置选项保留在匹配器实例中。以下示例显示了应用 lambda 的匹配器:
示例 96. 应用 lambda 配置匹配器选项
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher(“firstname”, match -> match.endsWith())
.withMatcher(“firstname”, match -> match.startsWith());
}
Example 应用配置的合并视图创立的查问。默认匹配设置能够在 ExampleMatcher 级别设置,而独自的设置能够利用于特定的属性门路。已设置上的设置 ExampleMatcher 由属性门路设置继承,除非它们被明确定义。属性补丁上的设置比默认设置具备更高的优先级。下表形容了各种 ExampleMatcher 设置的范畴:
Spring 认证中国教育管理中心 -Spring Data MongoDB 教程六
11.7.4. 运行示例
以下示例显示了在应用存储库(Person 在本例中为对象)时如何按示例进行查问:
示例 97. 应用存储库按示例查问
public interface PersonRepository extends QueryByExampleExecutor<Person> {
}
public class PersonService {
@Autowired PersonRepository personRepository;
public List<Person> findPeople(Person probe) {
return personRepository.findAll(Example.of(probe));
}
}
一种 Example 蕴含非类型化的 ExampleSpec 用处库类型及其汇合名称。类型化 ExampleSpec 实例应用它们的类型作为后果类型和 Repository 实例的汇合名称。
在 中蕴含 null 值时 ExampleSpec,Spring Data Mongo 应用嵌入式文档匹配而不是点符号属性匹配。这样做会强制对嵌入文档中的所有属性值和属性程序进行准确的文档匹配。
Spring Data MongoDB 反对以下匹配选项:
Spring 认证中国教育管理中心 -Spring Data MongoDB 教程六
11.7.5. 无类型示例
默认状况下 Example 是严格键入的。这意味着映射的查问具备蕴含的类型匹配,将其限度为探测可调配的类型。例如,当保持应用默认类型键 (_class) 时,查问具备诸如 (_class : { $in : [ com.acme.Person] }) 之类的限度。
通过应用 UntypedExampleMatcher,能够绕过默认行为并跳过类型限度。因而,只有字段名称匹配,简直任何域类型都能够用作创立援用的探针,如以下示例所示:
示例 98. 无类型的示例查问
class JustAnArbitraryClassWithMatchingFieldName {
@Field(“lastname”) String value;
}
JustAnArbitraryClassWithMatchingFieldNames probe = new JustAnArbitraryClassWithMatchingFieldNames();
probe.value = “stark”;
Example example = Example.of(probe, UntypedExampleMatcher.matching());
Query query = new Query(new Criteria().alike(example));
List<Person> result = template.find(query, Person.class);
UntypedExampleMatcher 如果您在单个汇合中存储不同的实体或抉择不编写类型提醒,这可能是您的正确抉择。
另外,请记住,应用 @TypeAlias 须要对 MappingContext. 为此,请配置 initialEntitySet 为以确保读取操作的正确别名解析。
11.8. 计数文件
在 SpringData MongoDB 3.x 之前的版本中,计数操作应用 MongoDB 的外部收集统计信息。随着 MongoDB 事务的引入,这不再可能,因为统计数据无奈正确反映须要基于聚合的计数办法的事务期间的潜在变动。因而,在 2.x 版本中,MongoOperations.count()如果没有正在进行的事务,将应用收集统计信息,如果是,则应用聚合变体。
从 Spring Data MongoDB 3.x 开始,任何 count 操作都应用通过 MongoDBs 的基于聚合的计数办法的过滤条件是否存在 countDocuments。如果应用程序在解决收集统计数据的限度下很好,则
MongoOperations.estimatedCount() 提供了一种代替办法。
MongoDBs 本地 countDocuments 办法和 $match 汇集,不反对 $near 和 $nearSphere 但须要 $geoWithin 连同 $center 或 $centerSphere 不反对 $minDistance(见
https://jira.mongodb.org/brow…)。
因而,Query 将重写给定的 count 操作,应用 Reactive-/MongoTemplate 绕过如下所示的问题。
{location : { $near : [-73.99171, 40.738868], $maxDistance : 1.1 } }
{location : { $geoWithin : { $center: [ [-73.99171, 40.738868], 1.1] } } }
{location : { $near : [-73.99171, 40.738868], $minDistance : 0.1, $maxDistance : 1.1 } }
{$and :[ { $nor :[ { location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868], 0.01] } } } ]}, {location :{ $geoWithin :{ $center :[ [-73.99171, 40.738868], 1.1] } } } ] }
应用 计数源查问 $near。
当初应用 $geoWithinwith 重写查问 $center。
应用 $nearwith$minDistance 和计算源查问 $maxDistance。
重写的查问当初联合了 $nor $geowithin 规范来解决不受反对的 $minDistance.
11.9.Map-Reduce 操作
您能够应用 Map-Reduce 查问 MongoDB,这对于批处理、数据聚合以及查询语言不能满足您的需要时十分有用。
Spring 通过提供办法 MongoOperations 来简化 Map-Reduce 操作的创立和运行,从而提供与 MongoDB 的 Map-Reduce 的集成。它能够将 Map-Reduce 操作的后果转换为 POJO,并与 Spring 的 Resource 形象集成。这让您能够搁置您的文件系统、类门路、HTTP 服务器或任何其余 Spring 资源实现上的 JavaScript 文件,而后通过简略的 URI 款式语法援用 JavaScript 资源——例如,classpath:reduce.js; 在文件中内部化 JavaScript 代码通常比将它们作为 Java 字符串嵌入到文件中更可取您的代码。请留神,如果您违心,您依然能够将 JavaScript 代码作为 Java 字符串传递。
11.9.1. 示例用法
为了了解如何执行 Map-Reduce 操作,咱们应用了 MongoDB – The Definitive Guide [1]一书中的一个例子。在这个例子中,咱们创立了三个具备值 [a,b], [b,c] 的文档和 [c,d]。每个文档中的值都与键“x”相关联,如下例所示(假如这些文档位于名为 的汇合中 jmr1):
{“_id” : ObjectId(“4e5ff893c0277826074ec533”), “x” : [“a”, “b”] }
{“_id” : ObjectId(“4e5ff893c0277826074ec534”), “x” : [“b”, “c”] }
{“_id” : ObjectId(“4e5ff893c0277826074ec535”), “x” : [“c”, “d”] }
以下 map 函数计算每个文档的数组中每个字母的呈现次数:
function () {
for (var i = 0; i < this.x.length; i++) {emit(this.x[i], 1);
}
}
上面的 reduce 函数总结了所有文档中每个字母的呈现:
function (key, values) {
var sum = 0;
for (var i = 0; i < values.length; i++)
sum += values[i];
return sum;
}
运行上述函数会产生以下汇合:
{“_id” : “a”, “value” : 1}
{“_id” : “b”, “value” : 2}
{“_id” : “c”, “value” : 2}
{“_id” : “d”, “value” : 1}
假如 map 和 reduce 函数位于 map.js 和 reduce.js 并捆绑在您的 jar 中,因而它们在类门路上可用,您能够按如下形式运行 Map-Reduce 操作:
MapReduceResults<ValueObject> results = mongoOperations.mapReduce(“jmr1”, “classpath:map.js”, “classpath:reduce.js”, ValueObject.class);
for (ValueObject valueObject : results) {
System.out.println(valueObject);
}
后面的示例产生以下输入:
ValueObject [id=a, value=1.0]
ValueObject [id=b, value=2.0]
ValueObject [id=c, value=2.0]
ValueObject [id=d, value=1.0]
的 MapReduceResults 类实现 Iterable 并提供拜访的原始输入和定时和上面列出了计数 statistics.TheValueObject 类:
public class ValueObject {
private String id;
private float value;
public String getId() {
return id;
}
public float getValue() {
return value;
}
public void setValue(float value) {
this.value = value;
}
@Override
public String toString() {
return "ValueObject [id=" + id + ", value=" + value + "]";
}
}
默认状况下,应用的是输入类型,INLINE 因而您无需指定输入汇合。要指定额定的 Map-Reduce 选项,请应用带有额定 MapReduceOptions 参数的重载办法。该类 MapReduceOptions 具备晦涩的 API,因而能够增加额定的选项以紧凑的语法实现。以下示例将输入汇合 jmr1_out 设置为(请留神,仅设置输入汇合假设默认输入类型为 REPLACE):
MapReduceResults<ValueObject> results = mongoOperations.mapReduce(“jmr1”, “classpath:map.js”, “classpath:reduce.js”,
new MapReduceOptions().outputCollection("jmr1_out"), ValueObject.class);
还有一个动态导入 (import static
org.springframework.data.mongodb.core.mapreduce.MapReduceOptions.options;) 可用于使语法略微紧凑一些,如以下示例所示:
MapReduceResults<ValueObject> results = mongoOperations.mapReduce(“jmr1”, “classpath:map.js”, “classpath:reduce.js”,
options().outputCollection("jmr1_out"), ValueObject.class);
您还能够指定一个查问来缩小输出 Map-Reduce 操作的数据集。以下示例从 Map-Reduce 操作的思考中删除蕴含 [a,b] 的文档:
Query query = new Query(where(“x”).ne(new String[] {“a”, “b”}));
MapReduceResults<ValueObject> results = mongoOperations.mapReduce(query, “jmr1”, “classpath:map.js”, “classpath:reduce.js”,
options().outputCollection("jmr1_out"), ValueObject.class);
请留神,您能够在查问上指定额定的限度和排序值,但不能跳过值。