跳到主要内容

查询文档

DeepSeek V3 中英对照 Querying Documents

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

示例 1. 从纯 JSON 字符串创建 Query 实例

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

查询集合中的文档

之前,我们看到了如何在 MongoTemplate 上使用 findOnefindById 方法来检索单个文档。这些方法直接返回一个单一的领域对象,或者使用响应式 API 返回一个发出单个元素的 Mono。我们也可以查询一组文档,并将其作为领域对象的列表返回。假设我们有许多 Person 对象,其姓名和年龄作为文档存储在集合中,并且每个人都有一个包含余额的嵌入式账户文档,那么我们可以使用以下代码运行查询:

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

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

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

Criteria 类的方法

Criteria 类提供了以下方法,所有这些方法都对应 MongoDB 中的操作符:

  • Criteria all (Object o) 使用 $all 操作符创建一个查询条件

  • Criteria and (String key) 向当前 Criteria 添加一个带有指定 key 的链式 Criteria,并返回新创建的 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) 使用 $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) 使用 $jsonSchema 操作符为 JSON schema criteria 创建一个查询条件。$jsonSchema 只能应用于查询的顶层,而不能应用于特定属性。使用 schema 的 properties 属性来匹配嵌套字段。

  • Criteria bits()MongoDB 位查询操作符(如 $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 类提供了一些额外的方法,允许选择特定字段以及限制和排序结果。

Query 类的方法

  • 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)
java

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

选择字段

MongoDB 支持对查询返回的字段进行投影。投影可以根据字段名称来包含或排除字段(除非显式排除,否则 _id 字段始终会被包含)。

示例 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
java
  • 结果将包含 _idlast_name,通过 { "last_name" : 1 } 指定。

  • 结果将仅包含 last_name,通过 { "_id" : 0, "last_name" : 1 } 指定。

  • 结果将包含 _id 和整个 address 对象,通过 { "address" : 1 } 指定。

  • 结果将包含 _id 和仅包含 city 字段的 address 对象,通过 { "address.city" : 1 } 指定。

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

示例 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");
java
  • 使用原生表达式。所使用的字段名必须引用数据库文档中的字段名。

  • 将表达式结果投射到的字段名进行赋值。生成的字段名不会映射到领域模型中。

  • 使用 AggregationExpression。与原生 MongoExpression 不同,字段名会映射到领域模型中使用的字段名。

  • 结合 AggregationExpression 使用 SpEL 来调用表达式函数。字段名会映射到领域模型中使用的字段名。

@Query(fields="…") 允许在 Repository 层使用表达式字段投影,如 MongoDB 基于 JSON 的查询方法和字段限制 中所述。

附加查询选项

MongoDB 提供了多种方式来为查询应用元信息,例如注释或批处理大小。直接使用 Query API 时,有几种方法可以设置这些选项。

提示

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

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

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

游标批处理大小

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

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

排序规则

在使用集合操作时指定排序规则(collation),只需在查询或操作选项中指定一个 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);
java

读取偏好

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

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

Query 实例上设置的偏好将覆盖 MongoTemplate 的默认 ReadPreference

注释

查询可以附加注释,这使得它们更容易在服务器日志中被查找。

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

查询唯一值

MongoDB 提供了一种操作,通过从结果文档中使用查询来获取单个字段的唯一值。结果值不需要具有相同的数据类型,该功能也不仅限于简单类型。在检索时,实际的结果类型对于转换和类型化确实很重要。以下示例展示了如何查询唯一值:

示例 4. 获取唯一值

template.query(Person.class)  1
.distinct("lastname") 2
.all(); 3
java
  • 查询 Person 集合。

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

  • 检索所有不同的值作为 ObjectList(由于未指定明确的结果类型)。

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

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

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

template.query(Person.class)  1
.distinct("lastname") 2
.as(String.class) 3
.all(); 4
java
  • 查询 Person 集合。

  • 选择 lastname 字段的唯一值。字段名称根据域类型属性声明进行映射,同时考虑潜在的 @Field 注解。

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

  • 将所有唯一值作为 StringList 检索。如果类型无法转换为所需的目标类型,此方法将抛出 DataAccessException

地理空间查询

MongoDB 支持通过使用如 $near$withingeoWithin$nearSphere 等操作符进行地理空间查询。在 Criteria 类中提供了专门用于地理空间查询的方法。此外,还有一些形状类(BoxCirclePoint)与地理空间相关的 Criteria 方法结合使用。

备注

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

要理解如何进行地理空间查询,可以参考以下 Venue 类(取自集成测试,并依赖于功能丰富的 MappingMongoConverter):

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

要在 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);
java

要使用球面坐标查找 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);
java

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

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

要使用球面坐标查找 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);
java

地理邻近查询

注意

2.2 版本中的变更!
MongoDB 4.2 移除了对 geoNear 命令的支持,该命令之前用于运行 NearQuery

Spring Data MongoDB 2.2 的 MongoOperations#geoNear 使用了 $geoNear 聚合 而不是 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();
java
  • 用于标识目标集合和潜在查询映射的域类型。

  • 包含 dis 字段的目标类型,字段类型为 Number

MongoDB 支持在查询数据库时获取地理位置信息,并同时计算与给定原点的距离。通过地理邻近查询(geo-near queries),你可以表达诸如“查找周围 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);
java

我们使用 NearQuery 构建器 API 来设置一个查询,以返回给定 Point 周围 10 英里范围内的所有 Restaurant 实例。这里使用的 Metrics 枚举实际上实现了一个接口,因此其他度量单位也可以插入到距离计算中。Metric 由一个乘数支持,用于将给定度量单位的距离值转换为原生距离。此处显示的示例将 10 视为英里。使用内置的度量单位之一(英里和千米)会自动触发在查询中设置球形标志。如果你想避免这种情况,可以将普通的 double 值传递给 maxDistance(…)。有关更多信息,请参阅 NearQueryDistance 的 Javadoc。

地理邻近操作返回一个 GeoResults 包装对象,该对象封装了 GeoResult 实例。通过包装 GeoResults,可以访问所有结果的平均距离。单个 GeoResult 对象包含找到的实体及其与起点的距离。

GeoJSON 支持

MongoDB 支持使用 GeoJSON 和简单的(遗留的)坐标对来存储地理空间数据。这两种格式都可以用于数据的存储和查询。有关要求和限制的详细信息,请参阅 MongoDB 关于 GeoJSON 支持的手册

域类中的 GeoJSON 类型

在领域类中使用 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;
}
java
提示

如果 GeoJSON 对象的 coordinates 表示的是纬度经度对,那么经度在前,纬度在后。
因此,GeoJsonPointgetX() 视为经度,将 getY() 视为纬度

仓库查询方法中的 GeoJSON 类型

使用 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)));
java
  • 使用 commons 类型定义的仓库方法允许使用 GeoJSON 和传统格式调用它。

  • 使用 GeoJSON 类型以利用 $geometry 操作符。

  • 请注意,GeoJSON 多边形需要定义一个闭合环。

  • 使用传统格式的 $polygon 操作符。

指标与距离计算

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

NearQuery.near(new Point(-73.99171, 40.738868))
java
{
"$geoNear": {
//...
"near": [-73.99171, 40.738868]
}
}
json
NearQuery.near(new GeoJsonPoint(-73.99171, 40.738868))
java
{
"$geoNear": {
//...
"near": { "type": "Point", "coordinates": [-73.99171, 40.738868] }
}
}
json

尽管在语法上有所不同,服务器可以接受这两种格式,无论集合中的目标文档使用哪种格式。

注意

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

为了避免严重的麻烦,请确保将 Metric 设置为所需的计量单位,以确保距离能够正确计算。

换句话说:

假设你有 5 个如下所示的文档:

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

使用 GeoJSON,从 [-73.99171, 40.738868] 获取 400 米半径范围内的所有文档如下所示:

示例 6. 使用 GeoJSON 的 GeoNear

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

返回以下 3 个文档:

{
"_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
}
json
  • 距中心点的最大距离,单位为

  • GeoJSON 始终基于球面进行计算。

  • 距中心点的距离,单位为

现在,当使用传统的坐标对时,我们操作的是之前讨论过的弧度。因此,在构造 $geoNear 命令时,我们使用 Metrics#KILOMETERSMetric 确保距离乘数被正确设置。

示例 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"
}
}
json

返回与 GeoJSON 变体相同的 3 个文档:

{
"_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
}
json
  • 从中心点出发的最大距离,单位为弧度

  • 距离乘数,以便我们得到以公里为单位的最终距离。

  • 确保我们在 2d_sphere 索引上操作。

  • 从中心点出发的距离,单位为公里——将其乘以 1000 以匹配 GeoJSON 变体的单位。

全文搜索

自 MongoDB 2.6 版本起,您可以通过使用 $text 运算符来执行全文查询。特定于全文查询的方法和操作可以在 TextQueryTextCriteria 中找到。在执行全文搜索时,请参阅 MongoDB 参考文档 以了解其行为和限制。

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

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

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

示例 8. 全文查询

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

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

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

示例 9. 全文查询 - 按评分排序

Query query = TextQuery
.queryText(new TextCriteria().matchingAny("coffee", "cake"))
.sortByScore() 1
.includeScore(); 2

List<Document> page = template.find(query, Document.class);
java
  • 使用 score 属性按相关性对结果进行排序,这会触发 .sort({'score': {'$meta': 'textScore'}})

  • 使用 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"));
java

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

你可以通过在 TextCriteria 上使用相应的方法来设置 $caseSensitive$diacriticSensitive 标志。请注意,这两个可选标志在 MongoDB 3.2 中引入,除非显式设置,否则不会包含在查询中。

示例查询

按示例查询 可以在 Template API 级别运行示例查询。

以下代码片段展示了如何通过示例进行查询:

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

默认情况下,Example 是严格类型化的。这意味着映射的查询包含类型匹配,限制其只能探测可分配的类型。例如,当坚持使用默认的类型键(_class)时,查询会有一些限制,例如(_class : { $in : [ com.acme.Person] })。

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

示例 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);
java
备注

ExampleSpec 中包含 null 值时,Spring Data Mongo 使用嵌入文档匹配,而不是点符号属性匹配。这样做会强制对所有属性值以及嵌入文档中的属性顺序进行精确文档匹配。

备注

如果你在单个集合中存储了不同的实体,或者选择不编写类型提示,那么 UntypedExampleMatcher 可能是你的正确选择。

另外,请记住,使用 @TypeAlias 需要预先初始化 MappingContext。为此,请配置 initialEntitySet 以确保读取操作时能够正确解析别名。

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

StringMatcher 选项

匹配方式逻辑结果
DEFAULT (区分大小写){"firstname" : firstname}
DEFAULT (不区分大小写){"firstname" : { $regex: firstname, $options: 'i'}}
EXACT (区分大小写){"firstname" : { $regex: /^firstname$/}}
EXACT (不区分大小写){"firstname" : { $regex: /^firstname$/, $options: 'i'}}
STARTING (区分大小写){"firstname" : { $regex: /^firstname/}}
STARTING (不区分大小写){"firstname" : { $regex: /^firstname/, $options: 'i'}}
ENDING (区分大小写){"firstname" : { $regex: /firstname$/}}
ENDING (不区分大小写){"firstname" : { $regex: /firstname$/, $options: 'i'}}
CONTAINING (区分大小写){"firstname" : { $regex: /.*firstname.*/}}
CONTAINING (不区分大小写){"firstname" : { $regex: /.*firstname.*/, $options: 'i'}}
REGEX (区分大小写){"firstname" : { $regex: /firstname/}}
REGEX (不区分大小写){"firstname" : { $regex: /firstname/, $options: 'i'}}

查询匹配 JSON Schema 的集合

你可以使用模式(schema)来查询任何集合中匹配由 JSON 模式定义的特定结构的文档,如下例所示:

示例 11:查询匹配 $jsonSchema 的文档

MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname").build();

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

请参阅 JSON Schema 部分以了解 Spring Data MongoDB 中的模式支持。