spring-data-elasticsearch 搜索不同 enttities/indicies
spring-data-elasticsearch searching through different enttities/indicies
我需要提供允许用户搜索许多不同域元素并将结果作为组合列表查看的功能。因此,在 UI 中,他只需填写一个文本字段,而不是检索结果。
为了形象化,假设我在域中有 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;
}
...
但是当调用第二个函数 - 负责返回实际文档的函数时,抛出以下异常:
Unable to identify index name. GlobalSearchDTO is not a Document. Make
sure the document class is annotated with @Document(indexName="foo")
我试过将任何域实体作为 class 参数传递,但我只从相应的索引中检索元素,而不是所有元素。例如调用:
return elasticsearchTemplate.queryForPage(searchQuery, Shop.class, new GlobalSearchResultMapper()).getContent();
结果仅从 'shop' 索引中检索元素。似乎出于某种原因未使用动态提供的索引。
所以问题是:是否可以像那样检索数据?为什么指定 '.withIndices("car", "garage", "shop")' 是不够的?
也许我应该考虑其他解决方案,例如:
循环搜索索引(一个再一个),连接结果并按分数排序
使用 'globalsearch' 索引创建单独的 GlobalSearch 实体
并在那里复制数据
提前致谢!
克日什托夫
我已经设法找到适合我的问题的解决方法。事实证明,当使用 'scroll' 和 'scan' 功能时,会使用动态提供的索引,这意味着查询按预期工作。解决方案代码:
@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 中 class:
...
for (SearchHit hit : response.getHits()) {
switch(hit.getIndex()) {
case "car": //map to DTO
case "shop": //map to DTO
case "garage": //map to DTO
}
}
...
我需要提供允许用户搜索许多不同域元素并将结果作为组合列表查看的功能。因此,在 UI 中,他只需填写一个文本字段,而不是检索结果。
为了形象化,假设我在域中有 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;
}
...
但是当调用第二个函数 - 负责返回实际文档的函数时,抛出以下异常:
Unable to identify index name. GlobalSearchDTO is not a Document. Make sure the document class is annotated with @Document(indexName="foo")
我试过将任何域实体作为 class 参数传递,但我只从相应的索引中检索元素,而不是所有元素。例如调用:
return elasticsearchTemplate.queryForPage(searchQuery, Shop.class, new GlobalSearchResultMapper()).getContent();
结果仅从 'shop' 索引中检索元素。似乎出于某种原因未使用动态提供的索引。
所以问题是:是否可以像那样检索数据?为什么指定 '.withIndices("car", "garage", "shop")' 是不够的?
也许我应该考虑其他解决方案,例如:
循环搜索索引(一个再一个),连接结果并按分数排序
使用 'globalsearch' 索引创建单独的 GlobalSearch 实体
并在那里复制数据
提前致谢!
克日什托夫
我已经设法找到适合我的问题的解决方法。事实证明,当使用 'scroll' 和 'scan' 功能时,会使用动态提供的索引,这意味着查询按预期工作。解决方案代码:
@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 中 class:
...
for (SearchHit hit : response.getHits()) {
switch(hit.getIndex()) {
case "car": //map to DTO
case "shop": //map to DTO
case "garage": //map to DTO
}
}
...