此版本仍在开发中,尚未被视为稳定版。如需最新稳定版本,请使用 Spring Data MongoDB 5.0.4spring-doc.cadn.net.cn

查询文档

您可以使用 QueryCriteria 类来表达您的查询。 它们的命名方式与原生 MongoDB 操作符名称相对应,例如 ltlteis 等。 QueryCriteria 类遵循流畅 API 风格,因此您可以链式组合多个方法条件和查询,同时保持代码易于理解。 为了提高可读性,静态导入可让您在创建 QueryCriteria 实例时避免使用 'new' 关键字。 您还可以使用 BasicQuery 从纯 JSON 字符串创建 Query 实例,如下示例所示:spring-doc.cadn.net.cn

示例1. 从一个普通的 JSON 字符串创建 Query 实例
BasicQuery query = new BasicQuery("{ age : { $lt : 50 }, accounts.balance : { $gt : 1000.00 }}");
List<Person> result = mongoTemplate.find(query, Person.class);

查询集合中的文档

之前,我们已经了解了如何通过 findOne 上的 findByIdMongoTemplate 方法来检索单个文档。 这些方法会直接返回一个单独的领域对象,或者在使用响应式 API 时返回一个发出单个元素的 Mono。 我们还可以查询一组文档,并将其作为领域对象列表返回。 假设我们在一个集合中存储了多个包含姓名和年龄的 Person 对象,且每个人员都嵌入了一个带有余额的账户(account)文档,那么现在我们可以使用以下代码执行查询:spring-doc.cadn.net.cn

使用 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();
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;

// ...

Flux<Person> result = template.query(Person.class)
  .matching(query(where("age").lt(50).and("accounts.balance").gt(1000.00d)))
  .all();

所有查找方法都接受一个 Query 对象作为参数。 该对象定义了执行查询时所使用的条件和选项。 条件通过使用 Criteria 对象来指定,该对象提供了一个名为 where 的静态工厂方法,用于实例化新的 Criteria 对象。 我们建议对 org.springframework.data.mongodb.core.query.Criteria.whereQuery.query 使用静态导入,以提高查询语句的可读性。spring-doc.cadn.net.cn

该查询应返回一个符合指定条件的 List 对象的 FluxPerson。 本节其余部分列出了 CriteriaQuery 类中对应于 MongoDB 提供的操作符的方法。 大多数方法会返回 Criteria 对象,以提供流畅的 API 风格。spring-doc.cadn.net.cn

Criteria 类的方法

Criteria 类提供了以下方法,所有这些方法都对应于 MongoDB 中的操作符:spring-doc.cadn.net.cn

  • Criteria all (Object o) 使用 $all 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria (String key) 向当前 Criteria 添加一个带有指定 key 的链式 Criteria,并返回新创建的 5spring-doc.cadn.net.cn

  • Criteria andOperator (Criteria…​ criteria) 使用 $and 操作符为所有提供的条件创建一个 AND 查询(需要 MongoDB 2.0 或更高版本)spring-doc.cadn.net.cn

  • Criteria andOperator (Collection<Criteria> criteria) 使用 $and 操作符为所有提供的条件创建一个 AND 查询(需要 MongoDB 2.0 或更高版本)spring-doc.cadn.net.cn

  • Criteria elemMatch (Criteria c) 使用 $elemMatch 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria exists (boolean b) 使用 $exists 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria gt (Object o) 使用 $gt 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria gte (Object o) 使用 $gte 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria in (Object…​ o) 使用 $in 操作符为可变参数创建一个条件。spring-doc.cadn.net.cn

  • Criteria in (Collection<?> collection) 使用集合创建一个采用 $in 操作符的条件spring-doc.cadn.net.cn

  • Criteria is (Object o) 使用字段匹配({ key:value })创建一个条件。如果指定的值是一个文档,则文档中字段的顺序和完全相等性将起作用。spring-doc.cadn.net.cn

  • Criteria lt (Object o) 使用 $lt 运算符创建一个条件spring-doc.cadn.net.cn

  • Criteria lte (Object o) 使用 $lte 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria mod (Number value, Number remainder) 使用 $mod 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria ne (Object o) 使用 $ne 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria nin (Object…​ o) 使用 $nin 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria norOperator (Criteria…​ criteria) 使用 $nor 操作符为所有提供的条件创建一个 nor 查询spring-doc.cadn.net.cn

  • Criteria norOperator (Collection<Criteria> criteria) 使用 $nor 操作符为所有提供的条件创建一个 nor 查询spring-doc.cadn.net.cn

  • Criteria not () 使用 $not 元操作符创建一个条件,该操作符作用于紧随其后的子句spring-doc.cadn.net.cn

  • Criteria orOperator (Criteria…​ criteria) 使用 $or 操作符为所有提供的条件创建一个 or 查询spring-doc.cadn.net.cn

  • Criteria orOperator (Collection<Criteria> criteria) 使用 $or 操作符为所有提供的条件创建一个 or 查询spring-doc.cadn.net.cn

  • Criteria regex (String re) 使用 $regex 创建一个条件spring-doc.cadn.net.cn

  • Criteria sampleRate (double sampleRate) 使用 $sampleRate 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria size (int s) 使用 $size 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria type (int t) 使用 $type 操作符创建一个条件spring-doc.cadn.net.cn

  • Criteria matchingDocumentStructure (MongoJsonSchema schema) 使用 $jsonSchema 操作符创建一个条件,用于JSON Schema 条件$jsonSchema 只能应用于查询的顶层,不能针对特定属性使用。请使用 schema 的 properties 属性来匹配嵌套字段。spring-doc.cadn.net.cn

  • Criteria bits() 是通往 MongoDB 位运算查询操作符(如 https://docs.mongodb.com/manual/reference/operator/query-bitwise/)的入口。spring-doc.cadn.net.cn

Criteria 类还提供了以下用于地理空间查询的方法。spring-doc.cadn.net.cn

  • Criteria within (Circle circle) 使用 $geoWithin $center 操作符创建一个地理空间条件。spring-doc.cadn.net.cn

  • Criteria within (Box box) 使用 $geoWithin $box 操作创建一个地理空间条件。spring-doc.cadn.net.cn

  • Criteria withinSphere (Circle circle) 使用 $geoWithin $center 操作符创建一个地理空间条件。spring-doc.cadn.net.cn

  • Criteria near (Point point) 使用 $near 操作创建一个地理空间条件spring-doc.cadn.net.cn

  • Criteria nearSphere (Point point) 使用 $nearSphere$center 操作创建一个地理空间查询条件。此功能仅适用于 MongoDB 1.7 及更高版本。spring-doc.cadn.net.cn

  • Criteria minDistance (double minDistance) 使用 $minDistance 操作创建一个地理空间条件,用于配合 $near 使用。spring-doc.cadn.net.cn

  • Criteria maxDistance (double maxDistance) 使用 $maxDistance 操作创建一个地理空间条件,用于与 $near 配合使用。spring-doc.cadn.net.cn

Query 类提供了一些额外的方法,可用于选择特定字段,以及限制和排序查询结果。spring-doc.cadn.net.cn

Query 类的方法
  • Query addCriteria (Criteria criteria) 用于向查询中添加额外的条件spring-doc.cadn.net.cn

  • Field fields () 用于定义要包含在查询结果中的字段spring-doc.cadn.net.cn

  • Query limit (int limit) 用于将返回结果的大小限制为指定的限制值(用于分页)spring-doc.cadn.net.cn

  • Query skip (int skip) 用于在结果中跳过指定数量的文档(用于分页)spring-doc.cadn.net.cn

  • Query with (Sort sort) 用于为查询结果提供排序定义spring-doc.cadn.net.cn

  • Query with (ScrollPosition position) 用于提供一个滚动位置(基于偏移量或基于键集的分页),以开始或恢复一个 Scrollspring-doc.cadn.net.cn

模板 API 允许直接使用结果投影,使您能够针对给定的领域类型执行查询,并将操作结果映射到另一个类型上,如下所述。spring-doc.cadn.net.cn

class

template.query(SWCharacter.class)
    .as(Jedi.class)

有关结果投影的更多信息,请参阅文档中的投影部分。spring-doc.cadn.net.cn

选择字段

MongoDB 支持投影查询返回的字段。 投影可以根据字段名称包含或排除字段(除非显式排除,否则 _id 字段始终包含在内)。spring-doc.cadn.net.cn

示例 2. 选择结果字段
public class Person {

    @Id String id;
    String firstname;

    @Field("last_name")
    String lastname;

    Address address;
}

query.fields().include("lastname");              (1)

query.fields().exclude("id").include("lastname") (2)

query.fields().include("address")                (3)

query.fields().include("address.city")           (4)
1 结果将通过 _id 同时包含 last_name{ "last_name" : 1 }
2 结果将仅通过 last_name 包含 { "_id" : 0, "last_name" : 1 } 字段。
3 结果将通过 _id 包含 address 和完整的 { "address" : 1 } 对象。
4 结果将包含 _id 以及仅包含 address 字段的 city 对象,这是通过 { "address.city" : 1 } 实现的。

从 MongoDB 4.4 开始,您可以使用聚合表达式进行字段投影,如下所示:spring-doc.cadn.net.cn

示例3. 使用表达式计算结果字段
query.fields()
  .project(MongoExpression.create("'$toUpper' : '$last_name'"))         (1)
  .as("last_name");                                                     (2)

query.fields()
  .project(StringOperators.valueOf("lastname").toUpper())               (3)
  .as("last_name");

query.fields()
  .project(AggregationSpELExpression.expressionOf("toUpper(lastname)")) (4)
  .as("last_name");
1 使用原生表达式。所使用的字段名必须引用数据库文档中的字段名称。
2 指定用于接收表达式结果投影的字段名称。生成的字段名称不会映射到领域模型。
3 使用 AggregationExpression。与原生的 MongoExpression 不同,字段名称会被映射为域模型中使用的名称。
4 结合使用 SpEL 与 AggregationExpression 来调用表达式函数。字段名称将映射到领域模型中所使用的名称。

@Query(fields="…") 允许在 Repository 层级使用表达式字段投影,如基于 MongoDB JSON 的查询方法与字段限制中所述。spring-doc.cadn.net.cn

附加查询选项

MongoDB 提供了多种方式将元信息(例如注释或批处理大小)应用到查询中。直接使用 Query API 时,有多个方法可用于设置这些选项。spring-doc.cadn.net.cn

提示

索引提示可以通过两种方式应用:使用索引名称或其字段定义。spring-doc.cadn.net.cn

template.query(Person.class)
    .matching(query("...").withHint("index-to-use"));

template.query(Person.class)
    .matching(query("...").withHint("{ firstname : 1 }"));

光标批处理大小

游标批处理大小定义了在每个响应批次中返回的文档数量。spring-doc.cadn.net.cn

Query query = query(where("firstname").is("luke"))
    .cursorBatchSize(100)

排序规则

在集合操作中使用排序规则(collations)只需在查询或操作选项中指定一个 Collation 实例,如下两个示例所示:spring-doc.cadn.net.cn

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);

读取偏好

如下所示,要使用的ReadPreference可以直接设置在要执行的Query对象上。spring-doc.cadn.net.cn

template.find(Person.class)
    .matching(query(where(...)).withReadPreference(ReadPreference.secondary()))
    .all();
Query 实例上设置的读取偏好将覆盖 ReadPreference 的默认 MongoTemplate

评论

查询可以添加注释,以便在服务器日志中更容易查找。spring-doc.cadn.net.cn

template.find(Person.class)
    .matching(query(where(...)).comment("Use the force luke!"))
    .all();

查询唯一值

MongoDB 提供了一种操作,可通过查询从结果文档中获取某个单一字段的不同值。 所得的值不要求具有相同的数据类型,此功能也不限于简单类型。 在检索时,为了转换和类型处理,实际的结果类型是重要的。以下示例展示了如何查询不同值:spring-doc.cadn.net.cn

示例 4. 检索唯一值
template.query(Person.class)  (1)
  .distinct("lastname")       (2)
  .all();                     (3)
1 查询 Person 集合。
2 选择 lastname 字段的不同值。字段名称根据领域类型中的属性声明进行映射,并考虑可能存在的 @Field 注解。
3 检索所有不同的值,作为 List 类型的 Object 列表(由于未指定显式的返回类型)。

将不同值检索到一个 CollectionObject 中是最灵活的方式,因为它会尝试确定域类型的属性值,并将结果转换为所需的类型或映射的 Document 结构。spring-doc.cadn.net.cn

有时,当所需字段的所有值都固定为某种特定类型时,直接获取一个类型正确的 Collection 会更加方便,如下例所示:spring-doc.cadn.net.cn

示例 5. 获取强类型的唯一值
template.query(Person.class)  (1)
  .distinct("lastname")       (2)
  .as(String.class)           (3)
  .all();                     (4)
1 查询 Person 集合。
2 选择 lastname 字段的不同值。字段名称根据领域类型中的属性声明进行映射,并考虑可能存在的 @Field 注解。
3 检索到的值会被转换为目标类型——在本例中为String。如果存储的字段包含一个文档,也可以将这些值映射到更复杂的类型。
4 List 类型的 String 形式检索所有不同的值。如果该类型无法转换为所需的目标类型,此方法将抛出 DataAccessException

+= 地理空间查询spring-doc.cadn.net.cn

MongoDB 通过使用如 $near$withingeoWithin$nearSphere 等运算符支持地理空间查询。Criteria 类提供了专用于地理空间查询的方法。此外,还有一些形状类(BoxCirclePoint),它们与地理空间相关的 Criteria 方法配合使用。spring-doc.cadn.net.cn

在 MongoDB 事务中使用地理空间查询时需要特别注意,请参阅事务内的特殊行为

要了解如何执行地理空间查询,请考虑以下 Venue 类(取自集成测试,并依赖功能丰富的 MappingMongoConverter):spring-doc.cadn.net.cn

Venue.java
@Document(collection="newyork")
public class Venue {

  @Id
  private String id;
  private String name;
  private double[] location;

  @PersistenceCreator
  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 范围内的位置,您可以使用以下查询:spring-doc.cadn.net.cn

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 范围内的场所,您可以使用以下查询:spring-doc.cadn.net.cn

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范围内的场馆,您可以使用以下查询:spring-doc.cadn.net.cn

//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);

要查找靠近某个 Point 的场所,您可以使用以下查询:spring-doc.cadn.net.cn

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 的场馆,您可以使用以下查询:spring-doc.cadn.net.cn

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-doc.cadn.net.cn

Spring Data MongoDB 2.2 中的 MongoOperations#geoNear 使用 $geoNear 聚合, 而非 geoNear 命令来执行 NearQueryspring-doc.cadn.net.cn

之前在使用 geoNear 命令时,计算出的距离(即 dis)会包含在一个包装类型中返回,现在则直接嵌入到结果文档中。 如果给定的领域类型中已存在同名属性,则计算出的距离将被命名为 calculated-distance,并可能附加一个随机后缀。spring-doc.cadn.net.cn

目标类型可以包含一个以返回的距离命名的属性,以便(额外)直接将其读回领域类型中,如下所示。spring-doc.cadn.net.cn

GeoResults<VenueWithDistanceField> = template.query(Venue.class) (1)
    .as(VenueWithDistanceField.class)                            (2)
    .near(NearQuery.near(new GeoJsonPoint(-73.99, 40.73), KILOMETERS))
    .all();
1 用于标识目标集合和潜在查询映射的域类型。
2 包含一个类型为 disNumber 字段的目标类型。

MongoDB 支持在查询数据库中的地理位置的同时,计算与给定原点之间的距离。通过地理邻近(geo-near)查询,您可以表达诸如“查找周围 10 英里内的所有餐厅”之类的查询。为了实现这一功能,MongoOperations 提供了 geoNear(…) 方法,这些方法接受一个 NearQuery 作为参数(以及您已经熟悉的实体类型和集合),如下例所示:spring-doc.cadn.net.cn

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 来设置查询,以返回给定 Point 周围 10 英里范围内的所有 Restaurant 实例。 此处使用的 Metrics 枚举实际上实现了一个接口,以便可以将其他指标作为距离进行插入。 Metric 由一个乘数支持,用于将给定指标的距离值转换为原生距离。 此处显示的示例会将 10 视为英里。使用内置指标之一(英里和公里)会自动触发在查询上设置球形标志。 如果您想避免这种情况,请将普通 double 值传递给 maxDistance(…)。 有关更多信息,请参阅 NearQueryDistance 的 Javadoc。spring-doc.cadn.net.cn

地理邻近(geo-near)操作返回一个封装了 GeoResults 实例的 GeoResult 包装对象。 通过包装为 GeoResults,可以访问所有结果的平均距离。 单个 GeoResult 对象包含所找到的实体及其与原点之间的距离。spring-doc.cadn.net.cn

GeoJSON 支持

MongoDB 支持使用 GeoJSON 和简单(传统)坐标对来处理地理空间数据。这两种格式均可用于存储和查询数据。有关要求和限制的详细信息,请参阅 MongoDB 关于 GeoJSON 支持的手册spring-doc.cadn.net.cn

领域类中的 GeoJSON 类型

在领域类中使用 GeoJSON 类型非常简单。org.springframework.data.mongodb.core.geo 包包含诸如 GeoJsonPointGeoJsonPolygon 等类型。这些类型扩展了现有的 org.springframework.data.geo 类型。以下示例使用了 GeoJsonPointspring-doc.cadn.net.cn

public class Store {

	String id;

	/**
	 * { "type" : "Point", "coordinates" : [ x, y ] }
	 */
	GeoJsonPoint location;
}

如果coordinates一个 GeoJSON 对象的纬度经度对,经度先执行,然后是纬度.
GeoJsonPoint因此处理getX() as 经度getY() as 纬度.spring-doc.cadn.net.cn

仓库查询方法中的 GeoJSON 类型

将 GeoJSON 类型用作仓库查询参数时,会在创建查询时强制使用 $geometry 操作符,如下例所示:spring-doc.cadn.net.cn

public interface StoreRepository extends CrudRepository<Store, String> {

	List<Store> findByLocationWithin(Polygon polygon);  (1)

}

/*
 * {
 *   "location": {
 *     "$geoWithin": {
 *       "$geometry": {
 *         "type": "Polygon",
 *         "coordinates": [
 *           [
 *             [-73.992514,40.758934],
 *             [-73.961138,40.760348],
 *             [-73.991658,40.730006],
 *             [-73.992514,40.758934]
 *           ]
 *         ]
 *       }
 *     }
 *   }
 * }
 */
repo.findByLocationWithin(                              (2)
  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)));                 (3)

/*
 * {
 *   "location" : {
 *     "$geoWithin" : {
 *        "$polygon" : [ [-73.992514,40.758934] , [-73.961138,40.760348] , [-73.991658,40.730006] ]
 *     }
 *   }
 * }
 */
repo.findByLocationWithin(                              (4)
  new Polygon(
    new Point(-73.992514, 40.758934),
    new Point(-73.961138, 40.760348),
    new Point(-73.991658, 40.730006)));
1 使用通用类型定义的仓库方法允许以 GeoJSON 和旧版格式两种方式调用。
2 使用 GeoJSON 类型以利用 $geometry 操作符。
3 请注意,GeoJSON 多边形需要定义一个闭合的环。
4 使用旧版格式的 $polygon 操作符。

度量和距离计算

然后,MongoDB 的 $geoNear 操作符允许使用 GeoJSON 点或传统的坐标对。spring-doc.cadn.net.cn

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

尽管语法不同,服务器都能正常接受这两种格式,无论集合中的目标文档使用何种格式。spring-doc.cadn.net.cn

在距离计算上存在巨大差异。使用旧版格式时,计算基于类似地球的球体上的弧度,而 GeoJSON 格式则使用

为了避免严重的问题,请务必将Metric设置为所需的度量单位,以确保距离计算正确。spring-doc.cadn.net.cn

换句话说:spring-doc.cadn.net.cn

假设你有如下所示的5个文档:spring-doc.cadn.net.cn

{
    "_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 ] }
}

使用 GeoJSON,获取距离 [-73.99171, 40.738868] 400 米半径范围内的所有文档的代码如下所示:spring-doc.cadn.net.cn

示例 6. 使用 GeoJSON 的 GeoNear
{
    "$geoNear": {
        "maxDistance": 400, (1)
        "num": 10,
        "near": { type: "Point", coordinates: [-73.99171, 40.738868] },
        "spherical":true, (2)
        "key": "location",
        "distanceField": "distance"
    }
}

返回以下 3 个文档:spring-doc.cadn.net.cn

{
    "_id" : ObjectId("5c10f3735d38908db52796a6"),
    "name" : "10gen Office",
    "location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
    "distance" : 0.0 (3)
}
{
    "_id" : ObjectId("5c10f3735d38908db52796a9"),
    "name" : "City Bakery ",
    "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
    "distance" : 69.3582262492474 (3)
}
{
    "_id" : ObjectId("5c10f3735d38908db52796aa"),
    "name" : "Splash Bar",
    "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
    "distance" : 69.3582262492474 (3)
}
1 距离中心点的最大距离(单位:)。
2 GeoJSON 始终基于球体进行操作。
3 距中心点的距离,单位为

现在,如前所述,当使用传统的坐标对时,操作的是弧度(Radians)。因此,在构建 Metrics#KILOMETERS when constructing the `$geoNear 命令时,我们使用 Metric2 会确保距离乘数被正确设置。spring-doc.cadn.net.cn

示例 7. 使用传统坐标对的 GeoNear
{
    "$geoNear": {
        "maxDistance": 0.0000627142377, (1)
        "distanceMultiplier": 6378.137, (2)
        "num": 10,
        "near": [-73.99171, 40.738868],
        "spherical":true, (3)
        "key": "location",
        "distanceField": "distance"
    }
}

返回与 GeoJSON 变体相同的 3 个文档:spring-doc.cadn.net.cn

{
    "_id" : ObjectId("5c10f3735d38908db52796a6"),
    "name" : "10gen Office",
    "location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
    "distance" : 0.0 (4)
}
{
    "_id" : ObjectId("5c10f3735d38908db52796a9"),
    "name" : "City Bakery ",
    "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
    "distance" : 0.0693586286032982 (4)
}
{
    "_id" : ObjectId("5c10f3735d38908db52796aa"),
    "name" : "Splash Bar",
    "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
    "distance" : 0.0693586286032982 (4)
}
1 距中心点的最大距离(单位:弧度)。
2 距离乘数,以便我们得到以公里为单位的结果距离。
3 确保我们在 2d_sphere 索引上进行操作。
4 距离中心点的公里数——将其乘以1000即可转换为GeoJSON变体所使用的

全文搜索

从 MongoDB 2.6 版本开始,您可以使用 $text 操作符执行全文查询。TextQueryTextCriteria 中提供了全文查询特有的方法和操作。执行全文搜索时,请参阅 MongoDB 参考文档 以了解其行为和限制。spring-doc.cadn.net.cn

在实际使用全文搜索之前,您必须正确设置搜索索引。 有关如何创建索引结构的更多详细信息,请参阅文本索引。 以下示例展示了如何设置全文搜索:spring-doc.cadn.net.cn

db.foo.createIndex(
{
  title : "text",
  content : "text"
},
{
  weights : {
              title : 3
            }
}
)

可以按如下方式定义并运行一个搜索 coffee cake 的查询:spring-doc.cadn.net.cn

示例 8. 全文查询
Query query = TextQuery
  .queryText(new TextCriteria().matchingAny("coffee", "cake"));

List<Document> page = template.find(query, Document.class);

要根据weights按相关性对结果进行排序,请使用TextQuery.sortByScorespring-doc.cadn.net.cn

示例9. 全文查询 - 按得分排序
Query query = TextQuery
  .queryText(new TextCriteria().matchingAny("coffee", "cake"))
  .sortByScore() (1)
  .includeScore(); (2)

List<Document> page = template.find(query, Document.class);
1 使用 score 属性按相关性对结果进行排序,这将触发 .sort({'score': {'$meta': 'textScore'}})
2 使用 TextQuery.includeScore() 在返回的 Document 中包含计算得出的相关性得分。

你可以通过在搜索词前加上 - 前缀,或使用 notMatching 来排除某些搜索词,如下例所示(请注意,以下两行效果相同,因此是冗余的):spring-doc.cadn.net.cn

// 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\"))或使用 TextCriteria.phrase. 来定义短语。 以下示例展示了定义短语的两种方式:spring-doc.cadn.net.cn

// search for phrase 'coffee cake'
TextQuery.queryText(new TextCriteria().matching("\"coffee cake\""));
TextQuery.queryText(new TextCriteria().phrase("coffee cake"));

你可以通过 $caseSensitive 上的相应方法来设置 $diacriticSensitiveTextCriteria 标志。 请注意,这两个可选标志是在 MongoDB 3.2 中引入的,除非显式设置,否则不会包含在查询中。spring-doc.cadn.net.cn

按示例查询

按示例查询 可用于模板 API 层级来执行示例查询。spring-doc.cadn.net.cn

以下代码片段展示了如何通过示例进行查询:spring-doc.cadn.net.cn

类型化示例查询
Person probe = new Person();
probe.lastname = "stark";

Example example = Example.of(probe);

Query query = new Query(new Criteria().alike(example));
List<Person> result = template.find(query, Person.class);

默认情况下,Example 是严格类型化的。这意味着映射的查询包含类型匹配限制,仅限于可赋值的探针类型。 例如,当使用默认的类型键(_class)时,查询会包含类似如下的限制:(_class : { $in : [ com.acme.Person] })。spring-doc.cadn.net.cn

通过使用 UntypedExampleMatcher,可以绕过默认行为并跳过类型限制。因此,只要字段名称匹配,几乎任何领域类型都可以用作创建查询条件的探针,如下例所示:spring-doc.cadn.net.cn

示例 10. 无类型示例查询
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);

null 中包含 ExampleSpec 值时,Spring Data Mongo 会使用嵌入式文档匹配,而不是点号表示法的属性匹配。 这样做会强制对嵌入式文档中的所有属性值及其属性顺序进行精确匹配。spring-doc.cadn.net.cn

如果你在单个集合中存储了不同的实体,或者选择不写入类型提示信息,那么UntypedExampleMatcher很可能适合你。spring-doc.cadn.net.cn

此外,请注意,使用 @TypeAlias 需要提前初始化 MappingContext。为此,请配置 initialEntitySet,以确保在读取操作时能够正确解析别名。spring-doc.cadn.net.cn

Spring Data MongoDB 提供了对不同匹配选项的支持:spring-doc.cadn.net.cn

StringMatcher 选项
匹配 逻辑结果

DEFAULT(区分大小写)spring-doc.cadn.net.cn

{"firstname" : firstname}spring-doc.cadn.net.cn

DEFAULT(不区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: firstname, $options: 'i'}}spring-doc.cadn.net.cn

EXACT(区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /^firstname$/}}spring-doc.cadn.net.cn

EXACT(不区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /^firstname$/, $options: 'i'}}spring-doc.cadn.net.cn

STARTING(区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /^firstname/}}spring-doc.cadn.net.cn

STARTING(不区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /^firstname/, $options: 'i'}}spring-doc.cadn.net.cn

ENDING(区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /firstname$/}}spring-doc.cadn.net.cn

ENDING(不区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /firstname$/, $options: 'i'}}spring-doc.cadn.net.cn

CONTAINING(区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /.*firstname.*/}}spring-doc.cadn.net.cn

CONTAINING(不区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /.*firstname.*/, $options: 'i'}}spring-doc.cadn.net.cn

REGEX(区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /firstname/}}spring-doc.cadn.net.cn

REGEX(不区分大小写)spring-doc.cadn.net.cn

{"firstname" : { $regex: /firstname/, $options: 'i'}}spring-doc.cadn.net.cn

查询与 JSON Schema 匹配的集合

您可以使用一个模式(schema)来查询任意集合中符合由 JSON 模式所定义的特定结构的文档,如下例所示:spring-doc.cadn.net.cn

示例 11. 查询匹配 $jsonSchema 的文档
MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build();

template.find(query(matchingDocumentStructure(schema)), Person.class);

请参阅JSON Schema部分,以了解有关 Spring Data MongoDB 中模式支持的更多信息。spring-doc.cadn.net.cn