为了账号安全,请及时绑定邮箱和手机立即绑定

Spring认证中国教育管理中心-Spring Data MongoDB教程四

标签:
Spring

原标题: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> 不同的是,文档不会被批量删除,而是逐个删除。

https://img1.sycdn.imooc.com//6193795b0001b1ad06400304.jpg


11.5.10。乐观锁定

该@Version注释在 MongoDB 的上下文中提供类似于 JPA 的语法,并确保更新仅应用于具有匹配版本的文档。因此,version 属性的实际值被添加到更新查询中,如果另一个操作同时更改了文档,则更新不会产生任何影响。在这种情况下,
OptimisticLockingFailureException会抛出an 。以下示例显示了这些功能:

@Documentclass 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。

https://img1.sycdn.imooc.com//6193795c0001fc6d06400370.jpg


乐观锁定需要将 设置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 String id;    String firstname;

    @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 }

https://img1.sycdn.imooc.com//6193795d0001af6706400361.jpg


从 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来调用表达式函数。字段名称映射到域模型中使用的名称。

https://img1.sycdn.imooc.com//6193795d0001306306400286.jpg


@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(由于未指定明确的结果类型)。

https://img1.sycdn.imooc.com//6193795d00010e1806400163.jpg


将不同的值检索到CollectionofObject是最灵活的方式,因为它尝试确定域类型的属性值并将结果转换为所需的类型或映射Document结构。

有时,当所需字段的所有值都固定为某种类型时,直接获取正确类型的 更方便,Collection如下例所示:

示例 76. 检索强类型的不同值

template.query(Person.class)  
  .distinct("lastname")       
  .as(String.class)           
  .all();

查询 的集合Person。

选择该lastname字段的不同值。字段名根据域类型属性声明进行映射,同时考虑了潜在的@Field注释。

检索到的值将转换为所需的目标类型 - 在本例中为String. 如果存储的字段包含文档,还可以将值映射到更复杂的类型。

检索所有不同的值作为 a Listof String。如果类型无法转换为所需的目标类型,则此方法将抛出DataAccessException.

https://img1.sycdn.imooc.com//6193795e00014e1406400200.jpg


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) + "]";
  }
}

https://img1.sycdn.imooc.com//6193795e00016fbb06400434.jpg


要在 中查找位置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-rightBox 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对象携带找到的实体加上它与原点的距离。


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消