我需要提供允许用户搜索许多不同域元素并将结果视为组合列表的功能。所以在用户界面中,他只需要填写一个文本字段,而不是回溯结果。
要想象,假设我在域中有3个实体:
@Document(indexName="car")
public class Car {
private int id;
private String type;
}
@Document(indexName="garage")
public class Garage{
private int id;
private String address;
}
@Document(indexName="shop")
public class Shop{
private int id;
private String name;
}
现在我认为我可以达到这样的要求:
...
@Inject
private ElasticsearchTemplate elasticsearchTemplate;
...
@RequestMapping(value = "/_search/all/{query}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public List<?> search(@PathVariable String query) {
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(queryString(query))
.withIndices("car", "garage", "shop")
.build();
//THIS WORKS
elasticsearchTemplate.queryForIds(searchQuery);
//THIS THROWS ERROR ABOUT WRONG INDEXES
return elasticsearchTemplate.queryForPage(searchQuery, GlobalSearchDTO.class, new GlobalSearchResultMapper()).getContent();
}
...
class GlobalSearchDTO {
public Long id;
public String type;
public Object obj;
}
...
但是当调用第二个函数 - 负责返回实际文档的函数时,抛出以下异常:
无法识别索引名称。 GlobalSearchDTO不是文档。使 确保文档类使用@Document(indexName =“foo”)
进行注释
我尝试将任何域实体作为类参数传递,但是我只从相应的索引中查找元素,而不是全部。比如说:
return elasticsearchTemplate.queryForPage(searchQuery, Shop.class, new GlobalSearchResultMapper()).getContent();
仅从'shop'索引获得retrivng元素的结果。似乎由于某种原因,动态提供的指标未被使用。
所以问题是:是否有可能像这样回溯数据?为什么指定'.withIndices(“car”,“garage”,“shop”)'还不够?
也许我应该考虑其他解决方案,如:
在循环中搜索索引(一个一个),加入结果并按分数排序
使用'globalsearch'索引创建单独的GlobalSearch实体 那里有重复的数据
提前致谢!
的Krzysztof
答案 0 :(得分:2)
我已经设法为我的问题找到合适的解决方法。事实证明,当使用&#39;滚动&#39;并且&#39;扫描&#39;功能动态提供使用的标记,这意味着查询按预期工作。解决方案代码:
@RequestMapping(value = "/_search/all/{query}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public List<?> search(@PathVariable String query) {
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(queryString(query))
.withIndices("car", "garage", "shop")
.withPageable(new PageRequest(0,1))
.build();
String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false);
List<GlobalSearchDTO> sampleEntities = new ArrayList<GlobalSearchDTO>();
boolean hasRecords = true;
while (hasRecords){
Page<GlobalSearchDTO> page = elasticsearchTemplate.scroll(scrollId, 5000L , new ResultMapper());
if(page != null) {
sampleEntities.addAll(page.getContent());
hasRecords = page.hasNext();
}
else{
hasRecords = false;
}
}
return sampleEntities;
}
}
并在ResultMapper类中:
...
for (SearchHit hit : response.getHits()) {
switch(hit.getIndex()) {
case "car": //map to DTO
case "shop": //map to DTO
case "garage": //map to DTO
}
}
...