在上文《Spring boot整合ElasticSearch教程》中,我们简单介绍了Elasticsearch的基本知识,并通过spring boot整合Elasticsearch搭建一个简单案例。然而,该案例中测试案例简单,因此本文将讲解以下两点
(1) 如何自定义接口方法进行数据查询
(2) 如何通过DSL语法进行Elasticsearch数据搜索。
1、依赖配置
依赖配置中引入了elasticsearch、web、lombok等依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2、yml配置
cluster-name:es服务名
cluster-nodes:es端口数据
repositories.enabled:true 启用repository访问方式
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 127.0.0.1:9200
repositories:
enabled: true
3、实体对象
@Document注解:指定了Elasticsearch的索引名和类型名
@Field注解:指定了索引的字段类型和分词器
@Data注解:使用这个注解,就不用再去手写Getter,Setter,equals,canEqual,hasCode,toString等方法了,注解后在编译时会自动加进去;
@Data
@Document(indexName = "person_index",indexStoreType = "person_type")
public class Person implements Serializable {
public Person() {
}
public Person(long id, String name, Integer age, String sex, String desc) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.desc = desc;
}
// 必须指定一个id,
@Id
private long id;
// 这里配置了分词器,字段类型,可以不配置,默认也可
@Field(analyzer = "ik_smart", type = FieldType.Text)
private String name;
private Integer age;
@Field(analyzer = "ik_smart", type = FieldType.Text)
private String sex;
@Field(analyzer = "ik_smart", type = FieldType.Text)
private String desc;
}
4、服务方法
4.1 Repository接口
此案例中定义接口PersonRepository接口
(1) PersonRepository接口继承了ElasticsearchRepository接口
(2) ElasticsearchRepository接口继承了PagingAndSortingRepository接口
(3) 接口PagingAndSortingRepository继承了CrudRepository接口
(4) 接口CrudRepository继承了Repository接口。
因此服务可以调用PersonRepository继承自CrudRepository的CRUD方法对索引进行操作,CRUD方法通过AbstractElasticsearchRepository抽象类进行实现。
public interface PersonRepository extends ElasticsearchRepository<Person,Long> {
List<Person> findByName(String name);
List<Person> findByNameOrDesc(String name,String desc);
}
4.2 Service接口
public interface PersonService {
Iterable<Person> findAll();
void save(List<Person> list);
void save(Person bean);
void deleteById(Long id);
List<Person> findByName(String text);
List<Person> findByNameOrDesc(String text);
Page<Person> queryByPage(int pageNo);
}
4.3 Service接口实现PersonServiceImpl
在本文中自定义了以下方法:
(1) findByName:根据姓名查询用户信息
(2) findByNameOrDesc:根据用户名或备注信息查询用户信息
(3) queryByPage:自定义DSL方法根据年龄分页查询用户信息
Service
public class PersonServiceImpl implements PersonService {
@Autowired
private PersonRepository personRepository;
@Override
public Iterable<Person> findAll() {
return personRepository.findAll();
}
@Override
public void save(Person bean) {
personRepository.save(bean);
}
@Override
public void deleteById(Long id) {
personRepository.deleteById(id);
}
// 通过name查询用户信息
@Override
public List<Person> findByName(String text) {
return personRepository.findByName(text);
}
// 根据name或备注查询用户信息
@Override
public List<Person> findByNameOrDesc(String text) {
return personRepository.findByNameOrDesc(text,text);
}
// 自定义DSL方法分页查询用户信息
@Override
public Page<Person> queryByPage(int pageNo) {
// 查询条件构建器
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
// DSL查询条件
BoolQueryBuilder bool = QueryBuilders.boolQuery();
// DSL过滤器
List<QueryBuilder> filters = bool.filter();
// 范围查询过滤器
filters.add(QueryBuilders.rangeQuery("age").gte(0).lte(30));
builder.withQuery(bool);
// 设置排序规则
builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.ASC));
// 设置分页参数
builder.withPageable(PageRequest.of(pageNo,10));
// 设置返回字段
builder.withSourceFilter(new FetchSourceFilter(new String[]{"name","age"},null));
NativeSearchQuery query = builder.build();
// 根据DSL查询条件查询
return personRepository.search(query);
}
}
5、Web接口
@RestController
@RequestMapping("/person")
public class PersonController {
@Autowired
private PersonService personService;
// 查找全部,注意elasticsearch默认记录数
@RequestMapping("findAll")
public Iterable<Person> findAll() {
return personService.findAll();
}
// 批量新增索引数据
@RequestMapping("list")
public String save() {
personService.save(new ArrayList<>());
return "success";
}
// 单笔新增索引数据
@RequestMapping("save")
public void save(Person bean) {
personService.save(bean);
}
// 根据Id删除索引数据
@RequestMapping("/deleteById")
public void deleteById(Long id){
personService.deleteById(id);
}
// 根据name筛选数据
@RequestMapping("findByName")
public List<Person> findByName(String name) {
return personService.findByName(name);
}
// 根据name和desc筛选数据
@RequestMapping("findByNameOrDesc")
public List<Person> findByNameOrDesc(String text) {
return personService.findByNameOrDesc(text);
}
@RequestMapping("/page")
public Page<Person> queryByPage(int pageNo){
return personService.queryByPage(pageNo);
}
}
6、运行结果
findByNameOrDesc:
queryByPage: