3

我需要提供允许用户搜索许多不同的域元素并将结果作为组合列表查看的功能。因此,在 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;
    }
 ...  

但是当调用第二个函数 - 负责返回实际文档的函数时,会引发以下异常:

无法识别索引名称。GlobalSearchDTO 不是文档。确保使用 @Document(indexName="foo") 注释文档类

我尝试将任何域实体作为类参数传递,但我只从相应索引中检索元素,而不是全部。例如调用:

return elasticsearchTemplate.queryForPage(searchQuery, Shop.class, new GlobalSearchResultMapper()).getContent();

仅从“商店”索引中检索元素。似乎由于某种原因没有使用动态提供的索引。

所以问题是:是否有可能检索这样的数据?为什么指定 '.withIndices("car", "garage", "shop")' 是不够的?

也许我应该考虑其他解决方案,例如:

  1. 在循环中搜索索引(一个接一个),连接结果并按分数排序

  2. 使用“globalsearch”索引创建单独的 GlobalSearch 实体并
    在那里复制数据

提前致谢!

克日什托夫

4

1 回答 1

2

我已经设法为我的问题找到合适的解决方法。事实证明,当使用“滚动”和“扫描”功能时,会使用动态提供的索引,这意味着查询按预期工作。解决方案代码:

 @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
                }
}   
...  
于 2015-07-06T20:44:14.157 回答