使用spring-data-elasticsearch从索引中获取所有文档

Anu*_*sha 3 spring elasticsearch spring-data-elasticsearch

我正在尝试使用Spring Boot连接到我的外部ElasticSearch服务器。

如果我在命令行中进行卷曲,则可以得到预期的结果。

curl "http://ipAddr:9200/indexName/TYPE/_search?pretty=true"
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试通过Spring Boot访问它时出现此错误。

<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Mon Sep 11 12:39:15 IST 2017</div><div>There was an unexpected error (type=Internal Server Error, status=500).</div><div>Could not write JSON: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]-&gt;org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl[&quot;facets&quot;])</div></body></html>
Run Code Online (Sandbox Code Playgroud)

不知道为什么NullPointerException和什么aggregartion.impl

这是我的春季申请:

控制器:

@RestController
public class PojoController {

    @Autowired
    PojoService pojoService;

    @RequestMapping(value = "/", method=RequestMethod.GET)
    public @ResponseBody String index() {
        return new String("Welcome:)");
    }

    @RequestMapping(value = "/all", method = RequestMethod.GET,
            produces = { MediaType.APPLICATION_JSON_VALUE })
    @ResponseBody List<POJO> findAll() {
        try {
            List<POJO> pojoObj = pojoService.findAll();
            return pojoObj;
        } catch (Exception exp) {
            exp.printStackTrace();
            return null;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

仓库:

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {

    List<POJO> findAll();

}
Run Code Online (Sandbox Code Playgroud)

服务:

@Service
public class POJOServiceImpl implements POJOService{

    private POJORepository pojoRepository;

    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    public void setPojoRepository(PojoRepository pojoRepository) {
        this.pojoRepository = pojoRepository;
    }

    public POJO findOne(String id) {
        return pojoRepository.findOne(id);
    }

    public List<POJO> findAll() {
        return (List<POJO>) pojoRepository.findAll();
    }

}
Run Code Online (Sandbox Code Playgroud)

POJO类:

@Document(indexName = "INDEX", type = "TYPE")
public class POJO {

     @Id
     private Integer id;
     private String name;

     public POJO(){
         // empty
     }



    public POJO(Integerid, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    // getters and setters
}
Run Code Online (Sandbox Code Playgroud)

我应该能够查询索引中的所有文档。稍后,我将尝试使用过滤器等。

任何帮助表示赞赏。谢谢 :)

Joa*_*nna 6

杰克逊(Jackson)似乎在处理您的POJO时遇到问题(可能与此问题有关:DATAES-274)-问题所在是从存储库到的Iterable转换List

更新资料

对于存储库,spring-data-elasticsearch的行为与您预期的有所不同。以您的示例为例:

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {
    List<POJO> findAll();
}
Run Code Online (Sandbox Code Playgroud)

并在调用rest控制器后:

List<POJO> pojoObj = pojoService.findAll();
Run Code Online (Sandbox Code Playgroud)

在调试器中,您将看到以下内容:

在此处输入图片说明

您可能希望该pojoObj列表包含POJO类的对象。令人惊讶的是pojoObj-ArrayList包含一个AggregatedPageImpl类型的对象,其content字段是包含POJO对象的正确列表。这就是为什么您得到:

Could not write JSON: ... java.util.ArrayList[0]->org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl[\"facets\"])
Run Code Online (Sandbox Code Playgroud)

如我之前所写,Jackson无法在序列化POJO对象时处理此问题。

解决方案1

让存储库返回Iterable集合(默认情况下)。

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {

}
Run Code Online (Sandbox Code Playgroud)

将转换部分移到服务上,但使用一些实用程序方法(在此使用Guava)以使其具有如下效果:

import com.google.common.collect.Lists;

public List<POJO> findAll() {
    return Lists.newArrayList(pojoRepository.findAll());
}
Run Code Online (Sandbox Code Playgroud)

解决方案2

Page在存储库中使用(此处为不带参数的简化版本):

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {
    Page<TestDto> findAll();
}
Run Code Online (Sandbox Code Playgroud)

如果您仍要对列表进行操作-从服务中的页面获取内容:

public List<POJO> findAll() {
    return testDtoRepository.findAll().getContent();
}
Run Code Online (Sandbox Code Playgroud)