栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

ElasticSearch-Springboot-Data使用

ElasticSearch-Springboot-Data使用

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版本,如果不一样,需改变版本


    org.springframework.boot
    spring-boot-starter-parent
    2.0.5.RELEASE


    
    
        org.springframework.boot
        spring-boot-starter-data-elasticsearch
    
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
    
        org.springframework.boot
        spring-boot-starter-test
    
    
    
        org.projectlombok
        lombok
    
    
    
        com.alibaba
        fastjson
        1.1.15
    

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);
    }
    // 修改文档:和添加文档一样,只不过id必须相同
    @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 students = esRepository.findAll();
        students.forEach(student -> {
            System.out.println(student);
        });
        System.out.println("=============");
        // 根据id获取
        Optional studentOptional = esRepository.findById(1L);
        Student student = studentOptional.get();
        System.out.println(student);
    }

    // 保存一堆数据
    @Test
    public void testAddMutilDoc(){
        ArrayList 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();
        // 必须满足sname匹配lisi字符
        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对象
        Page studentPage = esRepository.search(searchQuery);
        // 总条数
        System.out.println(studentPage.getTotalElements());
        // 总分页
        System.out.println(studentPage.getTotalPages());

        // 获取到真正需要的对象
        List students = studentPage.getContent();
        // 循环打印
        students.forEach(student -> {
            System.out.println(student);
        });
    }
}
7.文档高亮搜素 7.1SpringbootData中没有对高亮结果处理,所以要自己写结果处理器,并交给spring管理
@Component
public class HighlightResultMapper implements SearchResultMapper {

    @Override
    public  AggregatedPage mapResults(SearchResponse response, Class aClass, Pageable pageable) {
        // 记录总条数
        long totalHits = response.getHits().getTotalHits();
        // 记录列表(泛型) - 构建Aggregate使用
        List list = Lists.newArrayList();
        // 获取搜索结果(真正的的记录)
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits) {
            if(hits.getHits().length <= 0){
                return null;
            }
            // 将原本的JSON对象转换成Map对象
            Map map = hit.getSourceAsMap();
            // 获取高亮的字段Map
            Map highlightFields = hit.getHighlightFields();
            for (Map.Entry highlightField : highlightFields.entrySet()) {
                // 获取高亮的Key
                String key = highlightField.getKey();
                // 获取高亮的Value
                HighlightField value = highlightField.getValue();
                // 实际fragments[0]就是高亮的结果,无需遍历拼接
                Text[] fragments = value.getFragments();
                StringBuilder sb = new StringBuilder();
                for (Text text : fragments) {
                    sb.append(text);
                }
                // 因为高亮的字段必然存在于Map中,就是key值
                // 可能有一种情况,就是高亮的字段是嵌套Map,也就是说在Map里面还有Map的这种情况,这里没有考虑
                map.put(key, sb.toString());
            }
            // 把Map转换成对象
            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("").postTags("");
        // 将高亮设置进去
        searchQueryBuilder.withHighlightFields(highlightBuilder);
        // 构建出具体条件
        NativeSearchQuery searchQuery = searchQueryBuilder.build();

        //开始查询(以高亮的方式查询)
        AggregatedPage page = elasticsearchTemplate.queryForPage(searchQuery, Student.class, highlightResultMapper);

        // 打印结果
        System.out.println(page.getTotalElements());
        System.out.println(page.getTotalPages());
        List students = page.getContent();
        students.forEach(student -> {
            System.out.println(student);
        });
    }

}
8.聚合查询 8.1聚合查询也是一样,springboot没有处理器需要自己创建

其实跟高亮那个处理器一样,只不过在返回值时多加了一个聚合

@Component
public class AggregationResultMapper implements SearchResultMapper {

    @Override
    public  AggregatedPage mapResults(SearchResponse response, Class aClass, Pageable pageable) {
        // 记录总条数
        long totalHits = response.getHits().getTotalHits();
        // 记录列表(泛型) - 构建Aggregate使用
        List list = Lists.newArrayList();
        // 获取搜索结果(真正的的记录)
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits) {
            if(hits.getHits().length <= 0){
                return null;
            }
            // 将原本的JSON对象转换成Map对象
            Map map = hit.getSourceAsMap();
            // 获取高亮的字段Map
            Map highlightFields = hit.getHighlightFields();
            for (Map.Entry highlightField : highlightFields.entrySet()) {
                // 获取高亮的Key
                String key = highlightField.getKey();
                // 获取高亮的Value
                HighlightField value = highlightField.getValue();
                // 实际fragments[0]就是高亮的结果,无需遍历拼接
                Text[] fragments = value.getFragments();
                StringBuilder sb = new StringBuilder();
                for (Text text : fragments) {
                    sb.append(text);
                }
                // 因为高亮的字段必然存在于Map中,就是key值
                // 可能有一种情况,就是高亮的字段是嵌套Map,也就是说在Map里面还有Map的这种情况,这里没有考虑
                map.put(key, sb.toString());
            }
            // 把Map转换成对象
            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 page = elasticsearchTemplate.queryForPage(searchQuery, Student.class, aggregationResultMapper);


        StringTerms terms = (StringTerms) page.getAggregation("paixu");
        List buckets = terms.getBuckets();
        //把机构名字聚合,搜集成字符串里集合
        List sages = buckets.stream().map(bucket -> bucket.getKeyAsString()).collect(Collectors.toList());
        System.out.println(sages);

    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/326372.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号