fan*_*fan 2 java spring-data spring-data-elasticsearch
从Spring-Data查询Elasticsearch时,我希望得到_score
如果我们采用以下简单的类:
@Document(indexName = "test", type = "el_test")
public static class ElTest{
private long id;
private String myField;
}
Run Code Online (Sandbox Code Playgroud)
使用JUnit测试
@Test
public void testScore() throws Exception {
elasticsearchTemplate.index(new IndexQueryBuilder()
.withIndexName("test")
.withObject(new ElTest("first value"))
.build());
elasticsearchTemplate.index(new IndexQueryBuilder()
.withIndexName("test")
.withObject(new ElTest("second value"))
.build());
elasticsearchTemplate.index(new IndexQueryBuilder()
.withIndexName("test")
.withObject(new ElTest("third"))
.build());
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("myField","second value"))
.build();
List<ElTest> els = elasticsearchTemplate.queryForList(query, ElTest.class);
assertEquals(2, els.size());
}
Run Code Online (Sandbox Code Playgroud)
这将在Elasticsearch中创建3个条目.查询将检索具有不同分数的两个值.
如果我们将请求直接放在Elasticsearch中:
POST /test/_search
{
"query": {
"match" : {
"myField" : {
"query" : "second value",
"type" : "boolean"
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
以及Elasticsearch的回复:
{
"took": 15,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 0.8838835,
"hits": [
{
"_index": "test",
"_type": "el_test",
"_id": "AVKmmYCL3xnXT_BGRA3T",
"_score": 0.8838835,
"_source": {
"id": 0,
"myField": "second value"
}
},
{
"_index": "test",
"_type": "el_test",
"_id": "AVKmmYCI3xnXT_BGRA3S",
"_score": 0.028130025,
"_source": {
"id": 0,
"myField": "first value"
}
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
当我得到一个ElTest对象列表时,我无法检索_score值(0.8838835和0.028130025).有没有办法获得Spring数据的价值?
我会想象类似的东西
@Document(indexName = "test", type = "el_test")
public static class ElTest{
private long id;
private String myField;
@Score
private double score;
}
Run Code Online (Sandbox Code Playgroud)
Score是一个注释,表明该字段由Elasticsearch填充.
我想要得分的原因是在gui中对列表进行排序.
由于从Elasticsearch到gui的许多dto映射,列表在某个地方都没有排序.因此它不可靠.
我当然可以手动添加分数值,但是需要迭代列表.这不是很好.
我使用Spring-data-elasticsearch版本1.2.0,因此使用Elasticsearch 1.4.4
小智 13
我一直在寻找相同的东西.
我发现在ElasticsearchTemplate类中使用了DefaultResultMapper的实例:
@Override
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
long totalHits = response.getHits().totalHits();
List<T> results = new ArrayList<T>();
for (SearchHit hit : response.getHits()) {
if (hit != null) {
T result = null;
if (!Strings.isNullOrEmpty(hit.sourceAsString())) {
result = mapEntity(hit.sourceAsString(), clazz);
} else {
result = mapEntity(hit.getFields().values(), clazz);
}
setPersistentEntityId(result, hit.getId(), clazz);
results.add(result);
}
}
List<FacetResult> facets = new ArrayList<FacetResult>();
if (response.getFacets() != null) {
for (Facet facet : response.getFacets()) {
FacetResult facetResult = DefaultFacetMapper.parse(facet);
if (facetResult != null) {
facets.add(facetResult);
}
}
}
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
}
Run Code Online (Sandbox Code Playgroud)
分数存储在SearchHit实例中,但在hit.sourceAsString()中会被忽略...
作为一种解决方法,我创建了一个简单的界面:
/**
* Object to have score from elastic search
*/
public interface Scoreable {
float getScore();
void setScore(float score);
}
Run Code Online (Sandbox Code Playgroud)
和扩展的DefaultResultMapper:
/**
* Results mapper with score support
*/
public class ScoreResultsMapper extends DefaultResultMapper {
public ScoreResultsMapper(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
super(mappingContext);
}
@Override
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
FacetedPage<T> resultPage = super.mapResults(response, clazz, pageable);
Iterator<T> it = resultPage.getContent().iterator();
for (SearchHit hit : response.getHits()) {
if (hit != null) {
T next = it.next();
if (next instanceof Scoreable) {
((Scoreable) next).setScore(hit.score());
}
}
}
return resultPage;
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我只是检查返回的类型是否是Scoreable的实例,如果是,我将得分
所以现在我可以使用新的mapper 配置ElasticsearchTemplate(我使用的是spring-boot):
@Bean
public ElasticsearchTemplate elasticsearchTemplate() {
MappingElasticsearchConverter converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
ScoreResultsMapper mapper = new ScoreResultsMapper(converter.getMappingContext());
return new ElasticsearchTemplate(client(), converter, mapper);
}
Run Code Online (Sandbox Code Playgroud)
当然,我所有得分的文件都必须延伸Scorable.我们可能必须覆盖DefaultResultMapper的其他一些方法,以便在其他类型的查询中获得分数支持.
| 归档时间: |
|
| 查看次数: |
2598 次 |
| 最近记录: |