ElasticSearch-Springboot-Data使用
之前说过ElasticSearch一共支持4种Api,本篇文章主要讲解Springboot数据层集成ElasticSearch的Api简单使用。先看看下面这个Spring集成数据层框架图
可以看到Spring Data系列集成了非常多数据层框架,JDBC,Redis,ElasticSearch,Hadoop,Solr,MongoDB等,非常多啊,感觉spring是要一统天下啊,多的不说了,看看我们这个es怎么做
注意:我这里es的版本是5.6.2,由于es官方更新较快(现在已经7.15),相关api的使用,内部方法也在变,所以别的版本可能会有些变化
1.创建springboot项目,导入相关依赖
首先parent父工程,我这里是2.0.5版本,对应里面的es版本刚好是5.x版本,如果不一样,需改变版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.15</version>
</dependency>
</dependencies>
2.创建好启动类(不做演示),以及yaml配置文件
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 127.0.0.1:9300
3.创建实体类,做es的文档对象
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "student",type = "infro")
public class Student {
@Id
private Long id;
@Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String sname;
@Field(type = FieldType.Keyword)
private int sage;
@Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String intro;
}
@Document(indexName = “student”,type = “infro”)
indexName:指定索引名
type:指定类型名
@Id:代表文档id
@Field(type = FieldType.Text,analyzer = “ik_max_word”,searchAnalyzer = “ik_max_word”)
type:自定该字段的类型(Text和KeyWord都是String类型,Text代表分词,KeyWord代表不分词)
analyzer:指定存储时使用什么分词策略
searchAnalyzer:指定搜索时使用什么分词策略
4.创建索引测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESApp.class)
public class EsIndexTest {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Test
public void testCreateIndex(){
elasticsearchTemplate.createIndex(Student.class);
elasticsearchTemplate.putMapping(Student.class);
}
}
5.创建文档测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESApp.class)
public class EsSimpleDocTest {
@Autowired
private EsRepository esRepository;
@Test
public void testAddDoc(){
Student student = new Student(1L, "zhangsan", 18, "法外狂徒张三");
esRepository.save(student);
}
@Test
public void testUpdateDoc(){
Student student = new Student(1L, "lisi", 20, "法外狂徒李四");
esRepository.save(student);
}
@Test
public void testDelDoc(){
esRepository.deleteById(1L);
}
@Test
public void testSearchDoc(){
Iterable<Student> students = esRepository.findAll();
students.forEach(student -> {
System.out.println(student);
});
System.out.println("=============");
Optional<Student> studentOptional = esRepository.findById(1L);
Student student = studentOptional.get();
System.out.println(student);
}
@Test
public void testAddMutilDoc(){
ArrayList<Student> students = new ArrayList<>();
students.add(new Student(1L,"zhangsan",18,"法外狂徒张三"));
students.add(new Student(2L,"lisi",20,"那真是绝了"));
students.add(new Student(3L,"王五",28,"法外狂徒张三"));
students.add(new Student(4L,"周勇",30,"不会吧"));
students.add(new Student(5L,"何总",25,"可恶"));
students.add(new Student(6L,"lisi",18,"秀儿"));
esRepository.saveAll(students);
}
}
6.文档高级搜索
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESApp.class)
public class EsMutilSearchDocTest {
@Autowired
private EsRepository esRepository;
@Test
public void testMutilSearch(){
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("sname","lisi"));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("sage").gte(18).lte(30));
builder.withQuery(boolQueryBuilder);
builder.withSort(new FieldSortBuilder("sage").order(SortOrder.ASC));
builder.withPageable(PageRequest.of(0,10));
NativeSearchQuery searchQuery = builder.build();
Page<Student> studentPage = esRepository.search(searchQuery);
System.out.println(studentPage.getTotalElements());
System.out.println(studentPage.getTotalPages());
List<Student> students = studentPage.getContent();
students.forEach(student -> {
System.out.println(student);
});
}
}
7.文档高亮搜素
7.1SpringbootData中没有对高亮结果处理,所以要自己写结果处理器,并交给spring管理
@Component
public class HighlightResultMapper implements SearchResultMapper {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
long totalHits = response.getHits().getTotalHits();
List<T> list = Lists.newArrayList();
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
if(hits.getHits().length <= 0){
return null;
}
Map<String, Object> map = hit.getSourceAsMap();
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
for (Map.Entry<String, HighlightField> highlightField : highlightFields.entrySet()) {
String key = highlightField.getKey();
HighlightField value = highlightField.getValue();
Text[] fragments = value.getFragments();
StringBuilder sb = new StringBuilder();
for (Text text : fragments) {
sb.append(text);
}
map.put(key, sb.toString());
}
T item = JSON.parseObject(JSONObject.toJSONString(map),aClass);
list.add(item);
}
return new AggregatedPageImpl<>(list, pageable, totalHits);
}
}
7.2文档高亮测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESApp.class)
public class EsHighlightMutilSearchTest {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private HighlightResultMapper highlightResultMapper;
@Test
public void testHighlightSearch(){
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
HighlightBuilder.Field highlightBuilder = new HighlightBuilder.Field("sname").preTags("<font color='red'>").postTags("</font>");
searchQueryBuilder.withHighlightFields(highlightBuilder);
NativeSearchQuery searchQuery = searchQueryBuilder.build();
AggregatedPage<Student> page = elasticsearchTemplate.queryForPage(searchQuery, Student.class, highlightResultMapper);
System.out.println(page.getTotalElements());
System.out.println(page.getTotalPages());
List<Student> students = page.getContent();
students.forEach(student -> {
System.out.println(student);
});
}
}
8.聚合查询
8.1聚合查询也是一样,springboot没有处理器需要自己创建
其实跟高亮那个处理器一样,只不过在返回值时多加了一个聚合
@Component
public class AggregationResultMapper implements SearchResultMapper {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
long totalHits = response.getHits().getTotalHits();
List<T> list = Lists.newArrayList();
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
if(hits.getHits().length <= 0){
return null;
}
Map<String, Object> map = hit.getSourceAsMap();
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
for (Map.Entry<String, HighlightField> highlightField : highlightFields.entrySet()) {
String key = highlightField.getKey();
HighlightField value = highlightField.getValue();
Text[] fragments = value.getFragments();
StringBuilder sb = new StringBuilder();
for (Text text : fragments) {
sb.append(text);
}
map.put(key, sb.toString());
}
T item = JSON.parseObject(JSONObject.toJSONString(map),aClass);
list.add(item);
}
return new AggregatedPageImpl<>(list, pageable, totalHits,response.getAggregations());
}
}
8.2聚合查询测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESApp.class)
public class EsAggregationSearchTest {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private AggregationResultMapper aggregationResultMapper;
@Test
public void testAggregationSearch(){
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("paixu").field("sage").order(Terms.Order.count(false));
searchQueryBuilder.addAggregation(termsAggregationBuilder);
NativeSearchQuery searchQuery = searchQueryBuilder.build();
AggregatedPage<Student> page = elasticsearchTemplate.queryForPage(searchQuery, Student.class, aggregationResultMapper);
StringTerms terms = (StringTerms) page.getAggregation("paixu");
List<StringTerms.Bucket> buckets = terms.getBuckets();
List<String> sages = buckets.stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());
System.out.println(sages);
}
}
|