本案例使用springboot2.1.0,和ES6.5.0整合。
-
项目结构和maven配置如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
- 根据ES配置以及内部索引结构建立相应实体类、dao和配置:
1、实体类(注:一定要有Id属性,不然绑定相应repository持久化接口会抛异常) - 文档类Coder
@Document(indexName = "persons", type = "coder")
public class Coder implements Serializable {
private Long id;
private String name;
private Integer age;
private Map<String,Friend> friends = new HashMap<>();
private List<String> address= new ArrayList<>();
private SubCoder subCoder = new SubCoder();
public Map<String, Friend> getFriends() {
return friends;
}
public void setFriends(Map<String, Friend> friends) {
this.friends = friends;
}
public List<String> getAddress() {
return address;
}
public void setAddress(List<String> address) {
this.address = address;
}
public SubCoder getSubCoder() {
return subCoder;
}
public void setSubCoder(SubCoder subCoder) {
this.subCoder = subCoder;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- SubCoder 类
public class SubCoder implements Serializable {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2、application.yml配置
说明:一、yaml语法冒号后面一定要加空格
二、节点客户端(Node client)
节点客户端作为一个非数据节点加入到本地集群中。换句话说,它本身不保存任何数据,但是它知道数据在集群中的哪个节点中,并且可以把请求转发到正确的节点。
三、传输客户端(Transport client)
轻量级的传输客户端可以将请求发送到远程集群。它本身不加入集群,但是它可以将请求转发到集群中的一个节点上。
所以两个 Java 客户端都是通过 9300 端口并使用 Elasticsearch 的原生 传输 协议和集群交互。集群中的节点通过端口 9300 彼此通信。如果这个端口没有打开,节点将无法形成一个集群。Restful api交互使用9200端口
spring:
data:
elasticsearch:
cluster-name: eden-cluster01
cluster-nodes: //相应的访问路径,如:0.0.0.0:9300,0.0.0.1:9500
3、Repository持久化接口配置,无需加@repository注解,因为需要实例化相应对象时会,通过反射接口实例化一个代理对象。
public interface CoderEsRepository extends ElasticsearchRepository<Coder, Long> {
/**
* 相当于ES查询语句
* <code>
*
* { "bool" :
* { "must" : [
* { "field" : {"name" : "?"} },
* { "field" : {"age" : "?"} }
* ]
* }
* }
* </code>
* @param name
* @param age
* @return
*/
List<Coder> findByNameAndAge(String name, Integer age);
/**
* 相当于ES查询语句
* <code>
*
*
* {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"age" : "?"}} ]}}
*
* </code>
* @param name
* @param age
* @return
*/
List<Coder> findByNameOrAge(String name, Integer age);
/**
* {"bool" : {"must" : {"field" : {"name" : "?"}}}}
* @param name
* @return
*/
List<Coder> findByName(String name);
/**
* {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
* @param name
* @return
*/
List<Coder> findByNameNot(String name);
/**
* {"bool" : {"must" : {"range" : {"age" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
* @param fromAge
* @param toAge
* @return
*/
List<Coder> findByAgeBetween(Integer fromAge,Integer toAge);
/**
*
* {"bool" : {"must" : {"range" : {"age" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
* @param age
* @return
*/
List<Coder> findByAgeLessThanEqual(Integer age);
/**
* {"sort" : [{ "age" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"name" : ?}}}}
* @param name
* @return
*/
List<Coder> findByNameIsLikeOrderByAgeDesc(String name);
/**
* Query 注解查询方式
* @param name
* @param pageable
* @return
*/
@Query("{\"bool\" : {\"must\" : {\"term\" : {\"name\" : \"?0\"}}}}")
Page<Coder> findByName(String name, Pageable pageable);
}
4、编写相应的查询操作
@RestController
@RequestMapping("/persons/coder")
public class CoderController {
@Autowired
CoderEsRepository coderEsRepository;
/**
*
* @return
*/
@GetMapping
public ResponseEntity get() {
//单个属性查询
// List<Coder> coderByName= coderEsRepository.findByName("lf666'");
//单个属性分页查询
// Page<Coder> coderByPaging = coderEsRepository.findByName("lf666", PageRequest.of(0, 10));
List<Coder> byAgeDesc = coderEsRepository.findByNameIsLikeOrderByAgeDesc("l");
//属性是对象时查询
SubCoder subCoder = new SubCoder();
subCoder.setAge(20);
subCoder.setName("subEden");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("subCoder.name", subCoder.getName()))
.must(QueryBuilders.matchQuery("subCoder.age",subCoder.getAge()));
Iterable<Coder> search = coderEsRepository.search(boolQueryBuilder);
//属性集合中是否包含指定值查询
BoolQueryBuilder zsan = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("address", "bj"));
Iterable<Coder> search1 = coderEsRepository.search(zsan);
//复杂查询自定义排序规则
BoolQueryBuilder builder = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("age").from(10).to(200));
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder().withFilter(builder)
.withSort(SortBuilders.fieldSort("age").order(SortOrder.ASC));
Iterable<Coder> coders = coderEsRepository.search(nativeSearchQueryBuilder.build());
return new ResponseEntity(coders, HttpStatus.OK);
}