Spring data elasticsearch如何为关键字字段创建存储库方法
Spring data elasticsearch how to create repository method for keyword field
假设我有这样的映射,我想通过“requestId.keyword”字段进行搜索以获取精确匹配请求。如何在不使用 @Query 注释的情况下使用 Spring Data Elasticsearch 存储库实现它?
"requestId": {
"type": "text",
"analyzer": "1_to_15_analyzer_without_space",
"search_analyzer": "all_symbols_and_fold_analyzer",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
这对于通过内省方法名称构建查询的机制是不可能的。第一个想法是有类似的东西(我在这里使用 Foo
实体):
SearchHits<Foo> searchByRequestId_Keyword(String keyword);
方法名称的分析在 spring-data-common 模块中完成,该模块仅使用实体的 Java 属性的 属性 名称(可能是嵌套的)。但是 keyword 子字段仅存在于 Elasticsearch 中,并且 - 如果不是自动创建的 - 在 @MultiField
注释中。但是解析方法名的代码不使用 store-specific 信息,所以像这样的方法将不起作用并且会失败,错误是 keyword
is not a 属性 of text
- 这适用于 Java 对象。
您可以做的是首先添加自定义存储库片段接口:
public interface FooKeywordRepository {
SearchHits<Foo> searchByRequestIdKeyword(String keyword);
}
并提供一个必须像接口一样命名的实现,后缀为Impl:
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
public class FooKeywordRepositoryImpl implements FooKeywordRepository {
private final ElasticsearchOperations operations;
public FooKeywordRepositoryImpl(ElasticsearchOperations operations) {
this.operations = operations;
}
@Override
public SearchHits<Foo> searchByRequestIdKeyword(String keyword) {
Query query1 = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.termQuery("requestId.keyword", keyword))
.build();
Query query2 = new CriteriaQuery(Criteria.where("requestId.keyword").is(keyword));
return operations.search(query1, Foo.class); // could be query2 as well
}
}
您有一个 ElasticsearchOperations
注入并使用它来执行您构建的查询。我使用了两种方法来构建查询,都有效。
您要使用的存储库定义将是:
public interface FooRepository extends ElasticsearchRepository<Foo, String>, FooKeywordRepository {
// other custom methods if needed
}
假设我有这样的映射,我想通过“requestId.keyword”字段进行搜索以获取精确匹配请求。如何在不使用 @Query 注释的情况下使用 Spring Data Elasticsearch 存储库实现它?
"requestId": {
"type": "text",
"analyzer": "1_to_15_analyzer_without_space",
"search_analyzer": "all_symbols_and_fold_analyzer",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
这对于通过内省方法名称构建查询的机制是不可能的。第一个想法是有类似的东西(我在这里使用 Foo
实体):
SearchHits<Foo> searchByRequestId_Keyword(String keyword);
方法名称的分析在 spring-data-common 模块中完成,该模块仅使用实体的 Java 属性的 属性 名称(可能是嵌套的)。但是 keyword 子字段仅存在于 Elasticsearch 中,并且 - 如果不是自动创建的 - 在 @MultiField
注释中。但是解析方法名的代码不使用 store-specific 信息,所以像这样的方法将不起作用并且会失败,错误是 keyword
is not a 属性 of text
- 这适用于 Java 对象。
您可以做的是首先添加自定义存储库片段接口:
public interface FooKeywordRepository {
SearchHits<Foo> searchByRequestIdKeyword(String keyword);
}
并提供一个必须像接口一样命名的实现,后缀为Impl:
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
public class FooKeywordRepositoryImpl implements FooKeywordRepository {
private final ElasticsearchOperations operations;
public FooKeywordRepositoryImpl(ElasticsearchOperations operations) {
this.operations = operations;
}
@Override
public SearchHits<Foo> searchByRequestIdKeyword(String keyword) {
Query query1 = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.termQuery("requestId.keyword", keyword))
.build();
Query query2 = new CriteriaQuery(Criteria.where("requestId.keyword").is(keyword));
return operations.search(query1, Foo.class); // could be query2 as well
}
}
您有一个 ElasticsearchOperations
注入并使用它来执行您构建的查询。我使用了两种方法来构建查询,都有效。
您要使用的存储库定义将是:
public interface FooRepository extends ElasticsearchRepository<Foo, String>, FooKeywordRepository {
// other custom methods if needed
}