如何使用Spring Data从Elasticsearch中读取文档?

时间:2018-10-29 14:51:44

标签: java elasticsearch spring-data-elasticsearch

我创建了一个索引(房屋),其类型为“公寓”,其中包含20个文档。我使用邮递员将Json作为二进制文件上传到elasticsearch中。我有一个具有以下类的Spring Boot项目:

  1. EsConfig.java -我已经配置了集群名称,这是application.properties文件中的默认名称。

    @Configuration
    @EnableElasticsearchRepositories(basePackages = "com.search.repository")
    public class EsConfig {
    
    @Value("${elasticsearch.clustername}")
    private String EsClusterName;
    
    @Bean
    public Client esClient() throws UnknownHostException {
        Settings esSettings = Settings.builder()
                .put("cluster.name", EsClusterName)
                .put("client.transport.sniff", true)
                .put("client.transport.ignore_cluster_name", false)
                .build();
    
    
       TransportClient  client = new PreBuiltTransportClient(esSettings)
        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
        return client;
    
    }
    
    @Bean
    public ElasticsearchOperations elasticsearchTemplate() throws Exception{
        return new ElasticsearchTemplate(esClient()); 
      }
    }
    
  2. Apartments.java -这是我的数据模型。这些文档在elasticsearch中具有以下字段。

    @Document(indexName = "house", type = "apartments")
    @JsonIgnoreProperties(ignoreUnknown=true)
    public class Apartments {
    
       @Id
       private String id;
       @JsonProperty("Apartment_Name")
       private String apartmentName;
       @JsonProperty("Apartment_ID")
       private String apartmentId;
       @JsonProperty("Area_Name")
       private String areaName;
    
       //constructors along with getters and setters
    }
    
  3. ApartmentSearchRepository.java -这是扩展ElasticsearchRepository接口以执行原始操作的接口。

    public interface ApartmentSearchRepository extends ElasticsearchRepository<Apartments, String> {
    List<Apartments> findByApartmentName(String apartmentName);
    }
    
  4. EsApartmentService.java -

    @Service
    public class EsApartmentService {
    
    @Autowired
    ApartmentSearchRepository apartmentSearchRepository;
    
    public List<Apartments> getApartmentByName(String apartmentName) {
        return apartmentSearchRepository.findByApartmentName(apartmentName);
       }
    }
    
  5. ApartmentController.java -我创建了一个端点,该端点应从elasticsearch中退回那20个文档。 (另外,Apartment是我的项目中的POJO,而Apartments是数据模型。)

    @Autowired
    EsApartmentService esApartmentService;
    @GetMapping(path = "/search",produces = "application/json")
    public Set<Apartment> searchApartmentByName(
      @RequestParam(value = "apartmentName", defaultValue = "") String apartmentName) throws IOException {
      List<Apartment> apartments= new ArrayList<>();
      esApartmentService.getApartmentByName(apartmentName).forEach(apartment-> {
            apartments.add(new Apartment(apartment.getApartmentName(), apartment.getApartmentId(), apartment.getAreaName()));
        });
      return apartments.stream()
              .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Apartment::getApartmentId))));
    }
    

此代码返回状态200,但响应为空。我尝试调试,但似乎无法从elasticsearch读取这些文档。我经历了几个解决方案,但是大多数解决方案都是从代码本身内部设置文档数据的。

我无法通过点击控制器中指定的端点来检索这些文档。有人可以让我知道我可能会错过的东西吗?谢谢! :)

编辑:以下屏幕截图显示了Postman中的查询和响应。 enter image description here

2 个答案:

答案 0 :(得分:1)

据我所知,您可以使用@JsonProperty来将POJO映射到查询响应,但是您失去了使用弹簧数据的动态查找器方法(findBy *)的能力。弹簧数据的动态查找器生成依赖于反射,并且POJO中的字段名称在其中变得很重要。

您介意更改POJO或文档中的字段名称以进行验证吗?或者只是定义一个自定义查询?还有一个功能强大的Java API,您可以在其中定义更复杂的查询:https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.misc.filter

答案 1 :(得分:0)

如上所述,@ ibexit删除了@JsonProperty,并在服务中使用了本机搜索查询构建器。另外,当我给apartment_Name时,它并没有使用Apartment_Name并起作用。 (好像Elasticsearch遇到大小写问题,所以我在Camel Case中提供了它。)

我的更改:

  1. Apartments.java -已删除@JsonProperty

    @Document(indexName = "house", type = "apartments")
    //@JsonIgnoreProperties(ignoreUnknown=true)
    public class Apartments {
    
     @Id
     private String id;
    
     //@JsonProperty("apartment_ID")
     private String apartment_ID;
    
     //@JsonProperty("Area_Name")
     private String area_Name;
    
     //@JsonProperty("Apartment_Name")
     private String apartment_Name;
    }
    
  2. EsApartmentService.java -

    @Service
    public class EsApartmentService {
    @Autowired
    private  ElasticsearchTemplate elasticsearchTemplate; 
    
    public List<Apartments> getApartmentByName(String apartmentName) {
       SearchQuery searchQuery = new NativeSearchQueryBuilder()           
      .withQuery(org.elasticsearch.index.query.QueryBuilders
        .matchQuery("apartment_Name", apartmentName)).build();
    Page<Apartments> sampleEntities = 
        elasticsearchTemplate.queryForPage(searchQuery,Apartments.class);      
    return sampleEntities.getContent();
      }
    }
    
  3. 已删除 ApartmentSearchRepository.java 文件。

这些更改给了我所需的回复! :)