Elasticsearch 操作

Spring Data Elasticsearch 使用多个接口来定义可对 Elasticsearch 索引执行的操作(有关响应式接口的描述,请参阅 响应式 Elasticsearch 操作)。spring-doc.cadn.net.cn

这些接口对应于 Elasticsearch API 的结构。spring-doc.cadn.net.cn

这些接口的默认实现提供:spring-doc.cadn.net.cn

索引管理及索引和映射的自动创建。

IndexOperations 接口及其提供的实现(可从 ElasticsearchOperations 实例获取,例如通过调用 operations.indexOps(clazz))使用户能够在 Elasticsearch 集群中创建索引、设置映射或存储模板和别名信息。 将要创建的索引的详细信息可以通过使用 @Setting 注解进行设置,有关更多信息,请参阅 索引设置spring-doc.cadn.net.cn

这些操作均不会由 IndexOperationsElasticsearchOperations 的实现自动完成。 调用相关方法是用户的责任。spring-doc.cadn.net.cn

使用 Spring Data Elasticsearch 仓库时,支持自动创建索引和编写映射,请参阅 使用相应映射自动创建索引spring-doc.cadn.net.cn

使用示例

此示例展示了如何在 Spring REST 控制器中使用注入的 ElasticsearchOperations 实例。 该示例假设 Person 是一个使用 @Document@Id 等注解的类(请参阅 映射注解概述)。spring-doc.cadn.net.cn

示例 1. ElasticsearchOperations 的用法
@RestController
@RequestMapping("/")
public class TestController {

  private  ElasticsearchOperations elasticsearchOperations;

  public TestController(ElasticsearchOperations elasticsearchOperations) { (1)
    this.elasticsearchOperations = elasticsearchOperations;
  }

  @PostMapping("/person")
  public String save(@RequestBody Person person) {                         (2)
    Person savedEntity = elasticsearchOperations.save(person);
    return savedEntity.getId();
  }

  @GetMapping("/person/{id}")
  public Person findById(@PathVariable("id")  Long id) {                   (3)
    Person person = elasticsearchOperations.get(id.toString(), Person.class);
    return person;
  }
}
1 让 Spring 在构造函数中注入提供的 ElasticsearchOperations Bean。
2 将某个实体存储到 Elasticsearch 集群中。 实体的 ID 从返回的实体中读取,因为它在 person 对象中可能为 null,并由 Elasticsearch 创建。
3 通过 ID 获取实体。

要查看 ElasticsearchOperations 的全部功能,请参阅 API 文档。spring-doc.cadn.net.cn

搜索结果类型

当使用 DocumentOperations 接口的方法检索文档时,仅返回找到的实体。 当使用 SearchOperations 接口的方法进行搜索时,每个实体可提供额外信息,例如所找到实体的得分(score)排序值(sortValues)spring-doc.cadn.net.cn

为了返回这些信息,每个实体都被封装在一个 SearchHit 对象中,该对象包含此实体特有的附加信息。 这些 SearchHit 对象本身又被返回到一个 SearchHits 对象中,该对象还包含有关整个搜索的信息,例如 maxScore、请求的聚合或完成请求所需的执行持续时间。 现在可以使用以下类和接口:spring-doc.cadn.net.cn

SearchHit<T>

包含以下信息:spring-doc.cadn.net.cn

SearchHits<T>

包含以下信息:spring-doc.cadn.net.cn

搜索页面<T>

定义了一个包含 SearchHits<T> 元素的 Spring Data Page,可用于通过仓库方法进行分页访问。spring-doc.cadn.net.cn

搜索滚动命中结果<T>

由底层滚动 API 函数在 ElasticsearchRestTemplate 中返回,它使用 Elasticsearch 滚动 ID 来丰富 SearchHits<T>spring-doc.cadn.net.cn

SearchHitsIterator<T>

SearchOperations 接口的流式函数返回的迭代器。spring-doc.cadn.net.cn

响应式搜索结果集

ReactiveSearchOperations 拥有返回 Mono<ReactiveSearchHits<T>> 的方法,其中包含与 SearchHits<T> 对象相同的信息,但会将所包含的 SearchHit<T> 对象作为 Flux<SearchHit<T>> 提供,而不是作为列表。spring-doc.cadn.net.cn

查询

几乎在 SearchOperationsReactiveSearchOperations 接口中定义的所有方法都接受一个 Query 参数,该参数定义了用于搜索的查询。Query 是一个接口,Spring Data Elasticsearch 提供了三个实现:CriteriaQueryStringQueryNativeQueryspring-doc.cadn.net.cn

CriteriaQuery

CriteriaQuery 基础查询允许在无需了解 Elasticsearch 查询语法或基础知识的情况下创建查询以搜索数据。 它们允许用户通过简单地链接和组合指定搜索文档必须满足的条件的 Criteria 对象来构建查询。spring-doc.cadn.net.cn

在讨论组合条件时的 AND 或 OR 时,请记住,在 Elasticsearch 中,AND 会被转换为 must 条件,而 OR 会被转换为 should

Criteria 及其用法最好通过示例来解释(假设我们有一个带有 price 属性的 Book 实体):spring-doc.cadn.net.cn

示例 2. 获取指定价格的书籍
Criteria criteria = new Criteria("price").is(42.0);
Query query = new CriteriaQuery(criteria);

同一字段的条件可以链式调用,它们将通过逻辑 AND 进行组合:spring-doc.cadn.net.cn

示例 3. 获取指定价格的书籍
Criteria criteria = new Criteria("price").greaterThan(42.0).lessThan(34.0);
Query query = new CriteriaQuery(criteria);

当链式调用 Criteria 时,默认使用 AND 逻辑:spring-doc.cadn.net.cn

示例 4. 获取所有名为James且姓为Miller的人员:
Criteria criteria = new Criteria("lastname").is("Miller") (1)
  .and("firstname").is("James")                           (2)
Query query = new CriteriaQuery(criteria);
1 第一个 Criteria
2 and() 方法会创建一个新的 Criteria 并将其链接到第一个对象上。

如果您想创建嵌套查询,则需要为此使用子查询。 假设我们想要查找所有姓氏为Miller且名字为JackJohn的人员:spring-doc.cadn.net.cn

示例 5. 嵌套子查询
Criteria miller = new Criteria("lastName").is("Miller")  (1)
  .subCriteria(                                          (2)
    new Criteria().or("firstName").is("John")            (3)
      .or("firstName").is("Jack")                        (4)
  );
Query query = new CriteriaQuery(criteria);
1 为姓氏创建第一个 Criteria
2 这与子条件通过 AND 组合
3 此子条件是名字 John 的“或”组合条件。
4 且名字为 Jack

请参阅 Criteria 类的 API 文档,以获取所有可用操作的完整概述。spring-doc.cadn.net.cn

字符串查询

此类将 Elasticsearch 查询作为 JSON 字符串接收。 以下代码展示了一个搜索名字为“Jack”的人员的查询:spring-doc.cadn.net.cn

Query query = new StringQuery("{ \"match\": { \"firstname\": { \"query\": \"Jack\" } } } ");
SearchHits<Person> searchHits = operations.search(query, Person.class);

如果您已经有一个要使用的 Elasticsearch 查询,使用 StringQuery 可能是合适的。spring-doc.cadn.net.cn

原生查询

NativeQuery 是当您拥有复杂查询,或无法通过 Criteria API 表达的查询(例如构建查询和使用聚合时)应使用的类。 它允许使用 Elasticsearch 库中所有不同的 co.elastic.clients.elasticsearch._types.query_dsl.Query 实现,因此被称为“原生”实现。spring-doc.cadn.net.cn

以下代码展示了如何搜索具有给定 firstName 的人员,并对找到的文档执行术语聚合,以统计这些人员的 lastName 出现次数:spring-doc.cadn.net.cn

Query query = NativeQuery.builder()
	.withAggregation("lastNames", Aggregation.of(a -> a
		.terms(ta -> ta.field("lastName").size(10))))
	.withQuery(q -> q
		.match(m -> m
			.field("firstName")
			.query(firstName)
		)
	)
	.withPageable(pageable)
	.build();

SearchHits<Person> searchHits = operations.search(query, Person.class);

搜索模板查询

这是 Query 接口的一个特殊实现,需与存储的搜索模板结合使用。 请参阅 搜索模板支持 以获取更多信息。spring-doc.cadn.net.cn