Querying Documents

  • Querying Documents

  • Projection

  • Selecting fields

  • Additional Query Options

  • Hints

  • Cursor Batch Size

  • Collations

  • Read Preference

  • Comments

  • Query Distinct Values

  • GeoSpatial Queries

  • geoNear Queries

  • GeoJSON Support

  • Metrics and Distance calculation

  • Full-text Search

  • Query by Example :description: Spring Data MongoDB 提供了 Query 和 Criteria 类来创建查询。这些类提供了一致的、流畅的 API,支持嵌套谓词和 MongoDB 操作符。可以使用 Query 类来指定过滤条件、排序、字段选择以及其他查询选项。Criteria 类提供了一种链式、流畅的方式来构建复杂条件,包括相等、比较和布尔运算。

您可以使用 QueryCriteria 类来表达您的查询。它们的函数名称反映了本地 MongoDB 运算符名称,例如 ltlteis 等。QueryCriteria 类遵循流畅的 API 样式,以便您可以将多个方法条件和查询链接在一起,同时拥有易于理解的代码。为提高可读性,静态导入使您可以避免使用“new”关键字创建 QueryCriteria 实例。您还可以使用 BasicQuery 从纯 JSON 字符串创建 Query 实例,如下例所示: .Creating a Query instance from a plain JSON String

BasicQuery query = new BasicQuery("{ age : { $lt : 50 }, accounts.balance : { $gt : 1000.00 }}");
List<Person> result = mongoTemplate.find(query, Person.class);

Querying Documents in a Collection

先前,我们已经看到如何使用 MongoTemplate 上的 findOnefindById 函数检索单个文档。这些方法返回一个单一域对象,或者使用响应性 API 返回一个发出单个元素的 Mono。我们还可以查询要返回为域对象列表的文档集合。假设我们有一些名称和年龄存储在集合中作为文档的 Person 对象,并且每个人都有一个嵌入了余额的帐户文档,那么我们现在可以使用以下代码运行查询:

Querying for documents using the MongoTemplate
  • Imperative

  • Reactive

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

所有 find 函数都将 Query 对象作为参数。这个对象定义了用来执行查询的条件和选项。使用一个静态工厂函数名为 whereCriteria 对象来指定条件以实例化一个新的 Criteria 对象。我们建议对 org.springframework.data.mongodb.core.query.Criteria.whereQuery.query 使用静态导入以使查询更具可读性。

查询应该返回满足指定条件的 Person 对象的 ListFlux。本节的其余部分列出了 CriteriaQuery 类的对应于 MongoDB 中提供的运算符的方法。大多数方法返回 Criteria 对象,以便为 API 提供流畅的样式。

Example 1. Methods of the Criteria Class

Criteria 类提供以下方法,它们都对应 MongoDB 中的操作符:

  • Criteria all (Object o) 使用 $all 运算符创建一个标准

  • Criteria and (String key) 向当前 Criteria 添加一个带有指定 key 的链接 Criteria,并返回新创建的那个

  • Criteria andOperator (Criteria…​ criteria) 对所有提供的标准使用 $and 运算符创建一个与查询(需要 MongoDB 2.0 或更高版本)

  • Criteria andOperator (Collection<Criteria> criteria) 对所有提供的标准使用 $and 运算符创建一个与查询(需要 MongoDB 2.0 或更高版本)

  • Criteria elemMatch (Criteria c) 使用 $elemMatch 运算符创建一个标准

  • Criteria exists (boolean b) 使用 $exists 运算符创建一个标准

  • Criteria gt (Object o) 使用 $gt 运算符创建一个标准

  • Criteria gte (Object o) 使用 $gte 运算符创建一个标准

  • Criteria in (Object…​ o) 为 varargs 参数创建一个使用 $in 运算符的标准

  • 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 运算符创建一个也不查询

  • Criteria norOperator (Collection<Criteria> criteria) 对所有提供的标准使用 $nor 运算符创建一个也不查询

  • Criteria not () 创建一个使用 $not 元运算符的标准,该运算符会影响直接跟随的子句

  • Criteria orOperator (Criteria…​ criteria) 对所有提供的标准使用 $or 运算符创建一个或者查询

  • Criteria orOperator (Collection<Criteria> criteria) 对所有提供的标准使用 $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)JSON schema criteria 创建一个使用 $jsonSchema 运算符的标准。$jsonSchema 仅可应用于查询的最顶级,而不能特定于某个属性。要匹配嵌套字段,请使用模式的 properties 属性。

  • Criteria bits() 是通往 MongoDB bitwise query operators 的门户,如 $bitsAllClear

Criteria 类还为地理空间查询提供了以下方法。

  • Criteria within (Circle circle) 使用 $geoWithin $center 算符创建一个地理空间准则。

  • Criteria within (Box box) 使用 $geoWithin $box 操作创建一个地理空间准则。

  • Criteria withinSphere (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 类有一些其他方法,允许选择某些字段以及限制和排序结果。

Example 2. Methods of the Query class
  • Query addCriteria (Criteria criteria) 用于向查询添加其他准则

  • Field fields () 用于定义要包含在查询结果中的字段

  • Query limit (int limit) 用于将返回结果的大小限制在所给的限制之内(用于分页)

  • Query skip (int skip) 用于跳过结果中所给数量的文档(用于分页)

  • Query with (Sort sort) 用于提供结果的排序定义

  • Query with (ScrollPosition position) 用于提供一个滚动位置(基于偏移或数据集分页)来启动或恢复一个 Scroll

模板 API 允许直接使用结果投影,这些投影使你能够针对给定的域类型映射查询,同时将操作结果投影到另一个域类型,如下所述。

class

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

有关结果投影的更多信息,请参考文档的 Projections 部分。

Selecting fields

MongoDB 支持查询返回的 projecting fields。基于字段名称,投影可以包括和排除字段(除非明确排除,否则始终包括 _id 字段)。

Example 3. Selecting result fields
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 结果将通过 { "last_name" : 1 } 包含 _idlast_name
2 结果将仅通过 { "_id" : 0, "last_name" : 1 } 包含 last_name
3 结果将通过 { "address" : 1 } 包含 _id 和完整的 address 对象。
4 结果将通过 { "address.city" : 1 } 包含 _id 和仅包含 city 字段的 address 对象。

从 MongoDB 4.4 开始,你可以对字段投影使用聚合表达式,如下所示:

Example 4. Computing result fields using expressions
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-based Query Methods and Field Restriction中所述。

Additional Query Options

MongoDB 提供了多种方法向查询应用元信息,例如注释或批大小。直接使用 Query API 时,有几种方法可以实现这些选项。

Hints

索引提示可以用两种方式应用:使用索引名称或其字段定义。

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

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

Cursor Batch Size

游标批大小定义每个响应批中要返回的文档数。

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

Collations

对集合操作使用排序涉及在查询或操作选项中指定 Collation 实例,如下例所示:

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

Read Preference

要使用的 ReadPreference 可以直接设置在要运行的 Query 对象上,如下所述。

template.find(Person.class)
    .matching(query(where(...)).withReadPreference(ReadPreference.secondary()))
    .all();

Query 实例上设置的首选将取代 ReadPreference MongoTemplate 的默认值。

Comments

查询可以配备注释,这使得在服务器日志中查找查询变得更加容易。

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

Query Distinct Values

MongoDB 提供了一个操作,通过使用查询从结果文档中获取单个字段的不同值。结果值不必具有相同的数据类型,该特性也不限于简单类型。出于转换和类型的考虑,实际结果类型在检索中很重要。以下示例展示了如何查询不同值:

Example 5. Retrieving distinct values
template.query(Person.class)  1
  .distinct("lastname")       2
  .all();                     3
1 Query the Person collection.
2 选择 lastname 字段的唯一值。字段名称根据域类型属性声明进行映射,并考虑潜在的 @Field 注释。
3 检索所有唯一值,作为 ObjectList(由于未指定显式结果类型)。

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

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

Example 6. Retrieving strongly typed distinct values
template.query(Person.class)  1
  .distinct("lastname")       2
  .as(String.class)           3
  .all();                     4
1 查询 Person 的集合。
2 选择 lastname 字段的唯一值。字段名称根据域类型属性声明进行映射,并考虑潜在的 @Field 注释。
3 检索到的值将转换为所需的 target 类型 - 在本例中为 String。如果存储的字段包含一个文档,也可以将这些值映射到一个更复杂的类型。
4 addMyExtension 形式检索所有不同值。如果类型无法转换成所需的类型,则此方法将抛出 3

+= 地理空间查询

MongoDB 通过使用`$near`、$withingeoWithin$nearSphere 等运算符支持地理空间查询。Criteria 类中有专门针对地理空间查询的方法。还有几个形状类(BoxCirclePoint),它们与地理空间相关的 Criteria 方法结合使用。

在 MongoDB 事务中使用 GeoSpatial 查询时需要小心,请参阅Special behavior inside transactions

要了解如何执行 GeoSpatial 查询,请考虑以下 Venue 类(取自集成测试,并依赖于丰富的 MappingMongoConverter):

Example 7. Venue.java
@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);

要查找 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);

Geo-near Queries

Changed in 2.2! MongoDB 4.2 移除了对 geoNear 命令的支持,该命令之前用于运行 NearQuery。 Spring Data MongoDB 2.2 MongoOperations#geoNear 使用 $geoNear aggregation 而非 geoNear 命令来运行 NearQuery。 以前在包装类型中返回的计算距离(使用 geoNear 命令时的 dis)现在已嵌入到结果文档中。如果给定的域类型已经包含了具有该名称的属性,则计算出的距离将命名为 calculated-distance,并附加一个潜在的随机后缀。 目标类型可能包含一个以返回距离命名的属性,以(附加)将其直接读回到域类型中,如下所示。

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

MongoDB 支持同时查询数据库中的地理位置并计算到给定原点距离的功能。通过 geon-near 查询,你可以表达诸如“查找周围 10 英里内的所有餐馆”之类的查询。为了让你做到这一点,MongoOperations 提供了 geoNear(…​) 方法,该方法以 NearQuery 作为参数(以及已经熟悉的实体类型和集合),如下例所示:

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(…)。有关更多信息,请参阅 JavaDoc 中的 NearQueryDistance

geo-near 操作返回一个封装 GeoResult 实例的 GeoResults 包装对象。包装 GeoResults 允许访问所有结果的平均距离。一个 GeoResult 对象承载找到的实体及其到原点的距离。

GeoJSON Support

MongoDB 为地理空间数据支持 GeoJSON 和简单的(旧版)坐标对。这些格式都可用于存储和查询数据。请参阅 MongoDB manual on GeoJSON support 以了解要求和限制。

GeoJSON Types in Domain Classes

在域类中使用 GeoJSON 类型很简单。org.springframework.data.mongodb.core.geo 包含 GeoJsonPointGeoJsonPolygon 等类型。这些类型扩展了现有的 org.springframework.data.geo 类型。以下示例使用 GeoJsonPoint

public class Store {

	String id;

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

如果 GeoJSON 对象的 坐标 表示_纬度_和_经度_对,则_经度_在前,然后是_纬度_。因此,GeoJsonPointgetX() 视为_经度_,将 getY() 视为_纬度_。

GeoJSON Types in Repository Query Methods

使用 GeoJSON 类型作为存储库查询参数会强制在创建查询时使用 $geometry 运算符,如下例所示:

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 类型来使用 add 运算符。
3 请注意,GeoJSON 多边形需要定义闭合环。
4 使用传统格式 add 运算符。

Metrics and Distance calculation

然后,MongoDB $geoNear 运算符允许使用 GeoJSON 点或传统坐标对。

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 个类似于以下的 Document:

{
    "_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 米半径内的所有文档看起来如下所示:

Example 8. GeoNear with GeoJSON
{
    "$geoNear": {
        "maxDistance": 400, 1
        "num": 10,
        "near": { type: "Point", coordinates: [-73.99171, 40.738868] },
        "spherical":true, 2
        "key": "location",
        "distanceField": "distance"
    }
}

返回以下 3 个 Document:

{
    "_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 从中心点在 add 中的最大距离。
2 GeoJSON 始终在球面上进行操作。
3 从中心点距离 add

现在,当使用旧的坐标对时,正如之前讨论过的,操作在 Radians 上进行。因此,在构造 $geoNear 命令时,我们使用了 Metrics#KILOMETERSMetric 确保正确设置距离倍率。

Example 9. GeoNear with Legacy Coordinate Pairs
{
    "$geoNear": {
        "maxDistance": 0.0000627142377, 1
        "distanceMultiplier": 6378.137, 2
        "num": 10,
        "near": [-73.99171, 40.738868],
        "spherical":true, 3
        "key": "location",
        "distanceField": "distance"
    }
}

返回 3 个 Document,与 GeoJSON 变体相同:

{
    "_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 从中心点在 add 中的最大距离。
2 距离乘数因此我们得到 Kilometers 作为生成距离。
3 确保我们在 2d_sphere 索引上进行操作。
4 从中心点计算到 Kilometers 的距离 - 将其乘以 1000 以匹配 GeoJSON 变体的 Meters

Full-text Search

从 MongoDB 版本 2.6 开始,可以使用 `$text`算子运行全文查询。特定于全文查询的方法和操作在 `TextQuery`和 `TextCriteria`中可用。在进行全文搜索时,请参阅 MongoDB reference以了解其行为和限制。

在実際に使用全文搜索之前,必须正确设置搜索索引。有关如何创建索引结构的更多详细信息,请参见 Text Index。以下示例展示了如何设置全文搜索:

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

可以将搜索 coffee cake 的查询定义并运行如下:

Example 10. Full Text Query
Query query = TextQuery
  .queryText(new TextCriteria().matchingAny("coffee", "cake"));

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

要按照 weights 的相关性对结果进行排序,请使用 TextQuery.sortByScore

Example 11. Full Text Query - Sort by Score
Query query = TextQuery
  .queryText(new TextCriteria().matchingAny("coffee", "cake"))
  .sortByScore() 1
  .includeScore(); 2

List<Document> page = template.find(query, Document.class);
1 使用评分属性按相关性对结果进行排序,这将触发 .sort({'score': {'$meta': 'textScore'}})
2 使用 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\") 或使用 TextCriteria.phrase. 来定义短语。以下示例显示了定义短语的两种方法:

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

您可以使用 TextCriteria 上的对应方法设置 $caseSensitive$diacriticSensitive 的标志。请注意,这两个可选标志已在 MongoDB 3.2 中引入,并且必须明确设置才能包含在查询中。

Query by Example

Query by Example可以在模板 API 级别运行示例查询上使用。

以下代码段显示了如何按示例进行查询:

Typed Example Query
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] })。

通过使用 UntypedExampleMatcher,可以绕过默认行为并跳过类型限制。因此,只要字段名称匹配,几乎任何域类型都可以用作创建引用的探测,如下例所示:

Example 12. Untyped Example Query
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);

当在 ExampleSpec 中包含 null 值时,Spring Data Mongo 使用嵌入式文档匹配而不是点表示法属性匹配。这样做会强制对所有属性值和嵌入式文档中的属性顺序进行完全文档匹配。

如果要在单个集合中存储不同实体或选择不编写类型提示,那么 UntypedExampleMatcher 可能是你的正确选择。 此外,请牢记使用 @TypeAlias 需要 MappingContext 热初始化。为此,请配置 initialEntitySet 以确保对读取操作进行正确的别名解析。

Spring Data MongoDB 为不同的匹配选项提供了支持:

Example 13. StringMatcher options
Matching Logical result

DEFAULT (case-sensitive)

{"firstname" : firstname}

DEFAULT (case-insensitive)

{"firstname" : { $regex: firstname, $options: 'i'}}

EXACT (case-sensitive)

{"firstname" : { $regex: /^firstname$/}}

EXACT (case-insensitive)

{"firstname" : { $regex: /^firstname$/, $options: 'i'}}

STARTING (case-sensitive)

{"firstname" : { $regex: /^firstname/}}

STARTING (case-insensitive)

{"firstname" : { $regex: /^firstname/, $options: 'i'}}

ENDING (case-sensitive)

{"firstname" : { $regex: /firstname$/}}

ENDING (case-insensitive)

{"firstname" : { $regex: /firstname$/, $options: 'i'}}

CONTAINING (case-sensitive)

{"firstname" : { $regex: /.firstname./}}

CONTAINING (case-insensitive)

{"firstname" : { $regex: /.firstname./, $options: 'i'}}

REGEX (case-sensitive)

{"firstname" : { $regex: /firstname/}}

REGEX (case-insensitive)

{"firstname" : { $regex: /firstname/, $options: 'i'}}

Query a collection for matching JSON Schema

你可以使用模式查询文档集合,以便找到与 JSON 模式定义的给定结构匹配的文档,如下例所示:

Example 14. Query for Documents matching a $jsonSchema
MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build();

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

请参阅 JSON Schema 部分以了解有关 Spring Data MongoDB 中架构支持的更多信息。