原标题:Spring认证中国教育管理中心-Spring Data MongoDB教程四(内容来源:Spring中国教育管理中心)
11.5.9.删除文档的方法
您可以使用五种重载方法之一从数据库中删除对象:
template.remove(tywin, “GOT”);
template.remove(query(where(“lastname”).is(“lannister”)), “GOT”);
template.remove(new Query().limit(3), “GOT”);
template.findAllAndRemove(query(where(“lastname”).is(“lannister”), “GOT”);
template.findAllAndRemove(new Query().limit(3), “GOT”);
_id从关联的集合中删除由它指定的单个实体。
从GOT集合中删除与查询条件匹配的所有文档。
删除GOT集合中的前三个文档。不同于<2>,文档,以除去由它们的标识_id,运行给定的查询,应用sort,limit和skip选择第一,然后在一次在一个单独的步骤中除去所有。
从GOT集合中删除与查询条件匹配的所有文档。与 <3> 不同的是,文档不会被批量删除,而是逐个删除。
删除GOT集合中的前三个文档。与 <3> 不同的是,文档不会被批量删除,而是逐个删除。
11.5.10。乐观锁定
该@Version注释在 MongoDB 的上下文中提供类似于 JPA 的语法,并确保更新仅应用于具有匹配版本的文档。因此,version 属性的实际值被添加到更新查询中,如果另一个操作同时更改了文档,则更新不会产生任何影响。在这种情况下,
OptimisticLockingFailureException会抛出an 。以下示例显示了这些功能:
@Document
class Person {
@Id String id;
String firstname;
String lastname;
@Version Long version;
}
Person daenerys = template.insert(new Person(“Daenerys”));
Person tmp = template.findOne(query(where(“id”).is(daenerys.getId())), Person.class);
daenerys.setLastname(“Targaryen”);
template.save(daenerys);
template.save(tmp); // throws OptimisticLockingFailureException
最初插入文档。version设置为0。
加载刚刚插入的文档。version还在0。
用 更新文档version = 0。将lastname和设置version为1。
尝试更新先前加载的文档,但仍有version = 0. 操作失败并显示
OptimisticLockingFailureException,因为当前version是1。
乐观锁定需要将 设置WriteConcern为ACKNOWLEDGED。否则
OptimisticLockingFailureException可以被无声吞噬。
从版本 2.2 开始,MongoOperations还包括@Version从数据库中删除实体时的属性。要删除Document没有版本检查使用MongoOperations#remove(Query,…)的替代MongoOperations#remove(Object)。
从版本 2.2 开始,存储库在删除版本化实体时检查确认删除的结果。一
OptimisticLockingFailureException,如果一个版本实体不能被删除,通过提高CrudRepository.delete(Object)。在这种情况下,版本已更改或对象在此期间被删除。使用CrudRepository.deleteById(ID)旁路乐观锁定功能,也不管他们的版本中删除对象。
11.6.查询文件
您可以使用Query和Criteria类来表达你的queries.They有反映本地MongoDB的运营商名称方法的名称,如lt,lte,is,和others.TheQuery和Criteria类遵循流畅API的风格,让你可以连续使用多个方法标准和查询同时具有易于理解的代码。为了提高可读性,静态导入让您避免使用“new”关键字来创建Query和Criteria实例。您还可以使用从纯 JSON 字符串BasicQuery创建Query实例,如下例所示:
示例 71.从纯 JSON 字符串创建 Query 实例
BasicQuery query = new BasicQuery("{ age : { $lt : 50 }, accounts.balance : { $gt : 1000.00 }}");
List<Person> result = mongoTemplate.find(query, Person.class);
Spring MongoDB 还支持 GeoSpatial 查询(参见GeoSpatial Queries部分)和 Map-Reduce 操作(参见Map-Reduce部分)。
11.6.1.查询集合中的文档
早些时候,我们看到了如何使用findOne和findById方法检索单个文档MongoTemplate。这些方法返回单个域对象。我们还可以查询要作为域对象列表返回的文档集合。假设我们有许多Person带有名称和年龄的对象作为文档存储在一个集合中,并且每个人都有一个带有余额的嵌入式帐户文档,我们现在可以使用以下代码运行查询:
示例 72. 使用 MongoTemplate 查询文档
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;
// …
List<Person> result = template.query(Person.class)
.matching(query(where(“age”).lt(50).and(“accounts.balance”).gt(1000.00d)))
.all();
所有的 find 方法都以一个Query对象作为参数。此对象定义用于执行查询的条件和选项。这些标准是通过使用一个Criteria对象来指定的,该对象具有一个静态工厂方法,where用于实例化一个新Criteria对象。我们建议使用静态进口
org.springframework.data.mongodb.core.query.Criteria.where和Query.query使查询更具可读性。
查询应返回Person满足指定条件的对象列表。本节的其余部分列出了Criteria与QueryMongoDB 中提供的运算符对应的和类的方法。大多数方法返回Criteria对象,为 API 提供流畅的样式。
Criteria 类的方法
的Criteria类提供了以下的方法,所有这些都对应于运营商在MongoDB中:
Criteria all (Object o)使用$all运算符创建条件
Criteria 并将 指定(String key)的链添加到当前并返回新创建的CriteriakeyCriteria
Criteria andOperator (Criteria… criteria)使用$and运算符为所有提供的条件创建和查询(需要 MongoDB 2.0 或更高版本)
Criteria andOperator (Collection<Criteria> criteria)使用$and运算符为所有提供的条件创建和查询(需要 MongoDB 2.0 或更高版本)
Criteria elemMatch (Criteria c)使用$elemMatch运算符创建标准
Criteria 存在 (boolean b)使用$exists运算符创建条件
Criteria gt (Object o)使用$gt运算符创建标准
Criteria gte (Object o)使用$gte运算符创建条件
Criteria in (Object… o)使用$invarargs 参数的运算符创建条件。
Criteria in (Collection<?> collection)使用$in使用集合的运算符创建条件
Criteria is (Object o)使用字段匹配 ( { key:value })创建标准。如果指定的值是文档,则文档中的字段顺序和完全相等很重要。
Criteria lt (Object o)使用$lt运算符创建一个条件
Criteria lte (Object o)使用$lte运算符创建条件
Criteria mod (Number value, Number remainder)使用$mod运算符创建一个标准
Criteria ne (Object o)使用$ne运算符创建标准
Criteria nin (Object… o)使用$nin运算符创建一个标准
Criteria norOperator (Criteria… criteria)使用$nor运算符为所有提供的条件创建一个 nor 查询
Criteria norOperator (Collection<Criteria> criteria)使用$nor运算符为所有提供的条件创建一个 nor 查询
Criteria not ()使用$not影响紧随其后的子句的元运算符创建一个条件
Criteria orOperator (Criteria… criteria)使用$or运算符为所有提供的条件创建 or 查询
Criteria orOperator (Collection<Criteria> criteria)使用$or运算符为所有提供的条件创建 or 查询
Criteria regex (String re)使用$regex
Criteria sampleRate (double sampleRate)使用$sampleRate运算符创建标准
Criteria size (int s)使用$size运算符创建标准
Criteria type (int t)使用$type运算符创建条件
Criteria matchingDocumentStructure (MongoJsonSchema schema)创建使用的标准$jsonSchema操作员JSON模式标准。$jsonSchema只能应用于查询的顶层,而不是特定于属性的。使用properties架构的属性来匹配嵌套字段。
Criteria bits()是MongoDB 按位查询运算符(如$bitsAllClear.
Criteria 类还为地理空间查询提供了以下方法(请参阅GeoSpatial Queries部分以查看它们的实际效果):
Criteria 内 (Circle circle)创建使用地理空间标准$geoWithin $center运算符。
Criteria 内 (Box box)创建使用地理空间标准$geoWithin $box操作。
Criteria insideSphere (Circle circle)使用$geoWithin $center运算符创建地理空间标准。
Criteria Near (Point point)使用$near操作创建地理空间标准
Criteria NearSphere (Point point)使用$nearSphere$center操作创建地理空间标准。这仅适用于 MongoDB 1.7 及更高版本。
Criteria minDistance (double minDistance)使用$minDistance操作创建地理空间标准,与 $near 一起使用。
Criteria maxDistance (double maxDistance)使用$maxDistance操作创建地理空间标准,与 $near 一起使用。
Query 类的方法
本Query类有提供查询选项的一些额外的方法:
Query addCriteria (Criteria criteria)用于向查询添加附加条件
Field fields ()用于定义要包含在查询结果中的字段
Query limit (int limit)用于将返回结果的大小限制为提供的限制(用于分页)
Query skip (int skip)用于跳过结果中提供的文档数(用于分页)
Query with (Sort sort)用于为结果提供排序定义
选择字段
MongoDB 支持投影查询返回的字段。投影可以根据名称包含和排除字段(_id除非明确排除,否则始终包含该字段)。
示例 73. 选择结果字段
public class Person {
[@Id](/user/Id) String id;
String firstname;
[@Field](/user/Field)("last_name")
String lastname;
Address address;
}
query.fields().include(“lastname”);
query.fields().exclude(“id”).include(“lastname”)
query.fields().include(“address”)
query.fields().include(“address.city”)
结果将同时包含_id和last_namevia { “last_name” : 1 }。
结果将仅包含last_namevia { “_id” : 0, “last_name” : 1 }。
结果将通过 包含_id整个address对象{ “address” : 1 }。
结果将包含仅包含字段 via的_idand 和address对象。city{ “address.city” : 1 }
从 MongoDB 4.4 开始,您可以使用聚合表达式进行字段投影,如下所示:
示例 74. 使用表达式计算结果字段
query.fields()
.project(MongoExpression.create("’$toUpper’ : ‘$last_name’"))
.as(“last_name”);
query.fields()
.project(StringOperators.valueOf(“lastname”).toUpper())
.as(“last_name”);
query.fields()
.project(AggregationSpELExpression.expressionOf(“toUpper(lastname)”))
.as(“last_name”);
使用本机表达式。使用的字段名称必须引用数据库文档中的字段名称。
分配表达式结果投影到的字段名称。结果字段名称未映射到域模型。
使用AggregationExpression. 除了 native MongoExpression,字段名称映射到域模型中使用的名称。
使用 SpEL 和 anAggregationExpression来调用表达式函数。字段名称映射到域模型中使用的名称。
@Query(fields="…")允许在Repository级别使用表达式字段投影,如MongoDB JSON-based Query Methods and Field Restriction 中所述。
11.6.2.查询文档的方法
查询方法需要指定T返回的目标类型,并且它们使用显式集合名称重载,以便查询应该对返回类型指示的集合以外的集合进行操作。以下查询方法可让您查找一个或多个文档:
findAll:T从集合中查询类型对象的列表。
findOne:将集合上的即席查询的结果映射到指定类型的对象的单个实例。
findById:返回给定 ID 和目标类的对象。
find:将集合上的即席查询的结果映射到List指定类型的 a 。
findAndRemove:将集合上的即席查询的结果映射到指定类型的对象的单个实例。与查询匹配的第一个文档被返回并从数据库中的集合中删除。
11.6.3.查询不同的值
MongoDB 提供了一种操作,通过使用来自结果文档的查询来获取单个字段的不同值。结果值不需要具有相同的数据类型,该功能也不限于简单类型。对于检索,实际结果类型对于转换和打字很重要。以下示例显示了如何查询不同的值:
示例 75. 检索不同的值
template.query(Person.class)
.distinct(“lastname”)
.all();
查询Person集合。
选择该lastname字段的不同值。字段名称根据域类型属性声明进行映射,同时考虑了潜在的@Field注释。
将所有不同的值作为Listof检索Object(由于未指定明确的结果类型)。
将不同的值检索到CollectionofObject是最灵活的方式,因为它尝试确定域类型的属性值并将结果转换为所需的类型或映射Document结构。
有时,当所需字段的所有值都固定为某种类型时,直接获取正确类型的 更方便,Collection如下例所示:
示例 76. 检索强类型的不同值
template.query(Person.class)
.distinct(“lastname”)
.as(String.class)
.all();
查询 的集合Person。
选择该lastname字段的不同值。字段名根据域类型属性声明进行映射,同时考虑了潜在的@Field注释。
检索到的值将转换为所需的目标类型 - 在本例中为String. 如果存储的字段包含文档,还可以将值映射到更复杂的类型。
检索所有不同的值作为 a Listof String。如果类型无法转换为所需的目标类型,则此方法将抛出DataAccessException.
11.6.4.地理空间查询
MongoDB的支持通过使用等运营商的地理空间查询$near,$within,geoWithin,和$nearSphere。Criteria类中提供了特定于地理空间查询的方法。还有一些形状类(Box、Circle和Point)与地理空间相关Criteria方法结合使用。
在 MongoDB 事务中使用 GeoSpatial 查询时需要注意,请参阅事务内的特殊行为。
要了解如何执行 GeoSpatial 查询,请考虑以下Venue类(取自集成测试并依赖于 rich MappingMongoConverter):
@Document(collection=“newyork”)
public class Venue {
@Id
private String id;
private String name;
private double[] location;
@PersistenceConstructor
Venue(String name, double[] location) {
super();
this.name = name;
this.location = location;
}
public Venue(String name, double x, double y) {
super();
this.name = name;
this.location = new double[] { x, y };
}
public String getName() {
return name;
}
public double[] getLocation() {
return location;
}
@Override
public String toString() {
return “Venue [id=” + id + “, name=” + name + “, location=”
- Arrays.toString(location) + “]”;
}
}
要在 中查找位置Circle,您可以使用以下查询:
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues =
template.find(new Query(Criteria.where(“location”).within(circle)), Venue.class);
要在Circle使用球坐标中查找场地,您可以使用以下查询:
Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
List<Venue> venues =
template.find(new Query(Criteria.where(“location”).withinSphere(circle)), Venue.class);
要在 中查找场所Box,您可以使用以下查询:
//lower-left then upper-right
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
List<Venue> venues =
template.find(new Query(Criteria.where(“location”).within(box)), Venue.class);
要查找 a 附近的场地Point,您可以使用以下查询:
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues =
template.find(new Query(Criteria.where(“location”).near(point).maxDistance(0.01)), Venue.class);
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues =
template.find(new Query(Criteria.where(“location”).near(point).minDistance(0.01).maxDistance(100)), Venue.class);
要Point使用球坐标查找附近的场地,您可以使用以下查询:
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues =
template.find(new Query(
Criteria.where(“location”).nearSphere(point).maxDistance(0.003712240453784)),
Venue.class);
近地查询
在 2.2 中改变了!
MongoDB 4.2删除了对 geoNear之前用于运行NearQuery.
Spring Data MongoDB 2.2MongoOperations#geoNear使用$geoNear 聚合 而不是geoNear命令来运行NearQuery.
dis先前在包装器类型中返回的计算距离(使用 geoNear 命令时)现在嵌入到生成的文档中。如果给定的域类型已经包含具有该名称的属性,则计算出的距离将calculated-distance使用一个潜在的随机后缀命名。
目标类型可能包含一个以返回的距离命名的属性,以(另外)将其直接读回域类型,如下所示。
GeoResults<VenueWithDisField> = template.query(Venue.class)
.as(VenueWithDisField.class)
.near(NearQuery.near(new GeoJsonPoint(-73.99, 40.73), KILOMETERS))
.all();
用于标识目标集合和潜在查询映射的域类型。
包含distype 字段的目标类型Number。
MongoDB 支持在数据库中查询地理位置并同时计算距给定原点的距离。使用 geo-near 查询,您可以表达诸如“查找周围 10 英里内的所有餐馆”之类的查询。为了让您这样做,MongoOperations提供geoNear(…)了将 aNearQuery作为参数的方法(以及已经熟悉的实体类型和集合),如以下示例所示:
Point location = new Point(-73.99171, 40.738868);
NearQuery query = NearQuery.near(location).maxDistance(new Distance(10, Metrics.MILES));
GeoResults<Restaurant> = operations.geoNear(query, Restaurant.class);
我们使用NearQuery构建器 API 设置查询以返回Restaurant给定范围Point内 10 英里范围内的所有实例。Metrics这里使用的枚举实际上实现了一个接口,以便其他度量也可以插入到一定距离。AMetric由乘数支持,以将给定度量的距离值转换为原生距离。此处显示的示例将 10 视为英里。使用内置指标之一(英里和公里)会自动触发要在查询上设置的球形标志。如果您想避免这种情况,请将普通double值传递到maxDistance(…). 欲了解更多信息,请参阅的JavaDoc的NearQuery和Distance。
geo-near 操作返回一个GeoResults封装GeoResult实例的包装器对象。WrappingGeoResults允许访问所有结果的平均距离。单个GeoResult对象携带找到的实体加上它与原点的距离。