Query methods
Query lookup strategies
Elasticsearch 模块支持所有基本查询构建功能,例如字符串查询、原生搜索查询、基于标准的查询或者从方法名派生查询。
Declared queries
总是从方法名称派生查询并不足够,或者可能导致无法读取的方法名称。在这种情况下,人们可以使用`@Query`注解(请参阅Using @Query Annotation)。
Query creation
总的来说,Elasticsearch 的查询创建机制的工作方式如 repositories/query-methods-details.adoc 中所述。下面是一个有关 Elasticsearch 查询方法如何转换的简短示例:
interface BookRepository extends Repository<Book, String> {
List<Book> findByNameAndPrice(String name, Integer price);
}
上面的方法名将转换成以下 Elasticsearch JSON 查询
{
"query": {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } },
{ "query_string" : { "query" : "?", "fields" : [ "price" ] } }
]
}
}
}
下面列出了 Elasticsearch 支持的关键字列表。
Keyword | Sample | Elasticsearch Query String |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
如果需要在存储库中使用此类函数,则不支持生成采用 |
Method return types
可以定义存储库方法以具有以下返回类型,以返回多个元素:
-
List<T>
-
Stream<T>
-
SearchHits<T>
-
List<SearchHit<T>>
-
Stream<SearchHit<T>>
-
SearchPage<T>
Using @Query Annotation
@Query
annotation.传递给该方法的参数可以插入到查询字符串中的占位符中。对于第一个、第二个、第三个参数等,占位符的格式为 ?0
、?1
、?2
等。
interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("{\"match\": {\"name\": {\"query\": \"?0\"}}}")
Page<Book> findByName(String name,Pageable pageable);
}
作为注解参数设置的 String 必须是有效的 Elasticsearch JSON 查询。它将作为查询元素的值发送到 Elasticsearch 中;例如,如果使用参数 John 调用该函数,它将生成以下查询体:
{
"query": {
"match": {
"name": {
"query": "John"
}
}
}
}
@Query
annotation on a method taking a Collection argument这样的存储库方法
@Query("{\"ids\": {\"values\": ?0 }}")
List<SampleEntity> getByIds(Collection<String> ids);
将执行 IDs query 以返回所有匹配的文档。因此,使用 List
值 ["id1", "id2", "id3"]
调用方法将产生请求正文
{
"query": {
"ids": {
"values": ["id1", "id2", "id3"]
}
}
}
Using SpEL Expressions
@Query
annotation with SpEL expression.在 @Query
中定义查询时也支持 SpEL expression。
interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("""
{
"bool":{
"must":[
{
"term":{
"name": "#{#name}"
}
}
]
}
}
""")
Page<Book> findByName(String name, Pageable pageable);
}
例如,如果使用参数 John 调用该函数,它将生成以下查询体:
{
"bool":{
"must":[
{
"term":{
"name": "John"
}
}
]
}
}
假设我们有以下类作为查询参数类型:
public record QueryParameter(String value) {
}
我们可以通过 #
符号轻松地访问参数,然后使用简单的 .
引用属性 value
:
interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("""
{
"bool":{
"must":[
{
"term":{
"name": "#{#parameter.value}"
}
}
]
}
}
""")
Page<Book> findByName(QueryParameter parameter, Pageable pageable);
}
现在,我们可以将 new QueryParameter("John")
作为参数传递,它将生成与上面相同的查询字符串。
也支持访问 Bean property。假设有一个名为 queryParameter
的类型为 QueryParameter
的 Bean,我们可以用符号 @
而不是 #
访问 Bean,并且无需在查询方法中声明类型为 QueryParameter
的参数:
interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("""
{
"bool":{
"must":[
{
"term":{
"name": "#{@queryParameter.value}"
}
}
]
}
}
""")
Page<Book> findByName(Pageable pageable);
}
Collection
param.Collection
参数也受支持,并且与普通 String
一样容易使用,例如以下 terms
查询:
interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("""
{
"bool":{
"must":[
{
"terms":{
"name": #{#names}
}
}
]
}
}
""")
Page<Book> findByName(Collection<String> names, Pageable pageable);
}
声明 Elasticsearch JSON 查询时,不应该对集合值加上引号。
类似 List.of("name1", "name2")
的 names
集合将生成以下 terms 查询:
{
"bool":{
"must":[
{
"terms":{
"name": ["name1", "name2"]
}
}
]
}
}
Collection
param.当 Collection
参数中的值不是简单的 String
时,使用 SpEL Collection Projection 很方便:
interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("""
{
"bool":{
"must":[
{
"terms":{
"name": #{#parameters.![value]}
}
}
]
}
}
""")
Page<Book> findByName(Collection<QueryParameter> parameters, Pageable pageable);
}
这将从 QueryParameter
集合中提取所有 value
属性值作为新的 Collection
,从而产生与上述相同的效果。
@Param
通过 SpEL 访问参数时,在 Sping Data 中通过 @Param
注解将参数名更改为另一个参数名也很有用:
interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("""
{
"bool":{
"must":[
{
"terms":{
"name": #{#another.![value]}
}
}
]
}
}
""")
Page<Book> findByName(@Param("another") Collection<QueryParameter> parameters, Pageable pageable);
}