zoukankan      html  css  js  c++  java
  • ES的使用

    知识点
    ES全名Elasticsearch,功能是搜索功能,跟他同款的有个Solr,都是基于Lucene封装的数据库,他们都是数据库,都是需要先在本地安装数据库,然后往里面存,再按要求取的整个过程

    es7.x和6.x区别很大,看准学习7.x的

    文章来自
    Repository
    Repository,高亮
    Template,高亮
    狂神说,高亮

    下载安装

    • 查看【ELK/安装】笔记,安装上ES就行,另外两个不需要安装

    整合Java

    • maven依赖
    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.6.1</elasticsearch.version>
    </properties>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    
    • 配置,不能用文件的配置
    @Configuration
    public class conf {
    
        @Bean
        RestHighLevelClient elasticsearchClient() {
            ClientConfiguration configuration = ClientConfiguration.builder()
                    .connectedTo("localhost:9200")
                    //.withConnectTimeout(Duration.ofSeconds(5))
                    //.withSocketTimeout(Duration.ofSeconds(3))
                    //.useSsl()
                    //.withDefaultHeaders(defaultHeaders)
                    //.withBasicAuth(username, password)
                    // ... other options
                    .build();
            RestHighLevelClient client = RestClients.create(configuration).rest();
            return client;
        }
    }
    
    • 创建bean
    /**
      * 加上了@Document注解之后,默认情况下这个实体中所有的属性都会被建立索引、并且分词
      * index:是否设置索引, store是否存储数据,type:数据类型,analyzer:分词粒度选择,searchAnalyzer:查询进行分词处理
      * ik_smart:进行最小粒度分词,ik_max_word进行最大粒度分词
      *
    */
    @Document(indexName = "item",type = "docs", shards = 1, replicas = 0)
    public class Item {
        @Id
        private Long id;
    
        @Field(type = FieldType.Text, analyzer = "ik_max_word")
        private String title; //标题
    
        @Field(type = FieldType.Keyword)
        private String category;// 分类
    
        @Field(type = FieldType.Keyword)
        private String brand; // 品牌
    
        @Field(type = FieldType.Double)
        private Double price; // 价格
    
        @Field(index = false, type = FieldType.Keyword)
        private String images; // 图片地址
    
    

    对es的操作有三种方式

    • 使用template / ElasticsearchRestTemplate
    • 使用repository
    • 使用client / restHighLevelClient

    这里主要使用的是repository 和 restHighLevelClient

    创建索引和映射

    public class ElasticSearctTest {
        @Autowired
        private ElasticsearchTemplate  elasticsearchTemplate;
    
        @Test
        public void testCreate() {
            // 创建索引,会根据Item类的@Document注解信息来创建
            elasticsearchTemplate.createIndex(Item.class);
            // 配置映射,会根据Item类中的id、Field等字段来自动完成映射
            elasticsearchTemplate.putMapping(Item.class);
        }
    }
    

    简单操作,类似于MybatisPlus的MapperDao接口

    public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
       // 留空
    }
    
    public class ES {
        @Autowired
        private ItemRepository itemRepository;
    
        public void testAdd() {
            Item item = new Item(1L, "小米手机7", " 手机",
                    "小米", 3499.00, "http://image.leyou.com/13123.jpg");
            itemRepository.save(item);
        }
    
        // 修改(id存在就是修改,否则就是插入)
        public void testUpdate() {
            Item item = new Item(1L, "小米手机7777", " 手机",
                    "小米", 9499.00, "http://image.leyou.com/13123.jpg");
            itemRepository.save(item);
        }
    
        public void indexList() {
            List<Item> list = new ArrayList<>();
            list.add(new Item(2L, "坚果手机R1", " 手机", "锤子", 3699.00, "http://image.leyou.com/123.jpg"));
            list.add(new Item(3L, "华为META10", " 手机", "华为", 4499.00, "http://image.leyou.com/3.jpg"));
            // 接收对象集合,实现批量新增
            itemRepository.saveAll(list);
        }
    
        public void testDelete() {
            itemRepository.deleteById(1L);
        }
    
        public void testQuery(){
            Optional<Item> optional = itemRepository.findById(2L);
            System.out.println(optional.get());
        }
    
        public void testFind(){
            // 查询全部,并按照价格降序排序
            Iterable<Item> items = this.itemRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
            items.forEach(item-> System.out.println(item));
        }
    }
    

    简单操作之自定义方法,通过规定的方法名创建方式就行,方法名的创建方式查看最上面的原文,或者百度

    public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
    
        /**
         * 根据价格区间查询
         * @param price1
         * @param price2
         * @return
         */
        List<Item> findByPriceBetween(double price1, double price2);
    }
    
    public class ES {
        @Autowired
        private ItemRepository itemRepository;
    
        public void queryByPriceBetween(){
            List<Item> list = this.itemRepository.findByPriceBetween(2000.00, 3500.00);
            for (Item item : list) {
                System.out.println("item = " + item);
            }
        }
    }
    

    复杂操作

    public class ES {
        @Autowired
        private ItemRepository itemRepository;
    
        // SearchSourceBuilder 条件构造
        // HighlightBuilder 构建高亮
        // TermQueryBuilder 精确查询
        // MatchAllQueryBuilder
    
        public void testBaseQuery(){
            // 词条查询
            MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "小米");
            // 执行查询
            Iterable<Item> items = itemRepository.search(queryBuilder);
            items.forEach(System.out::println);
        }
    
        public void testNativeQuery(){
            // 构建查询条件
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 添加基本的分词查询
            queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米"));
            // 执行搜索,获取结果
            Page<Item> items = itemRepository.search(queryBuilder.build());
            // 打印总条数
            System.out.println(items.getTotalElements());
            // 打印总页数
            System.out.println(items.getTotalPages());
            items.forEach(System.out::println);
        }
    
        public void testNativeQuery2(){
            // 构建查询条件
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 添加基本的分词查询
            queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
    
            // 初始化分页参数
            int page = 0;
            int size = 3;
            // 设置分页参数
            queryBuilder.withPageable(PageRequest.of(page, size));
    
            // 执行搜索,获取结果
            Page<Item> items = itemRepository.search(queryBuilder.build());
            // 打印总条数
            System.out.println(items.getTotalElements());
            // 打印总页数
            System.out.println(items.getTotalPages());
            // 每页大小
            System.out.println(items.getSize());
            // 当前页
            System.out.println(items.getNumber());
            items.forEach(System.out::println);
        }
    
        public void testSort(){
            // 构建查询条件
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 添加基本的分词查询
            queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
    
            // 排序
            queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
    
            // 执行搜索,获取结果
            Page<Item> items = itemRepository.search(queryBuilder.build());
            // 打印总条数
            System.out.println(items.getTotalElements());
            items.forEach(System.out::println);
        }
    
    
        public void testAgg(){
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 不查询任何结果
            queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
            // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
            queryBuilder.addAggregation(
                    AggregationBuilders.terms("brands").field("brand"));
            // 2、查询,需要把结果强转为AggregatedPage类型
            AggregatedPage<Item> aggPage = (AggregatedPage<Item>) itemRepository.search(queryBuilder.build());
            // 3、解析
            // 3.1、从结果中取出名为brands的那个聚合,
            // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
            StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
            // 3.2、获取桶
            List<StringTerms.Bucket> buckets = agg.getBuckets();
            // 3.3、遍历
            for (StringTerms.Bucket bucket : buckets) {
                // 3.4、获取桶中的key,即品牌名称
                System.out.println(bucket.getKeyAsString());
                // 3.5、获取桶中的文档数量
                System.out.println(bucket.getDocCount());
            }
        }
    
        public void testSubAgg(){
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            // 不查询任何结果
            queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
            // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
            queryBuilder.addAggregation(
                    AggregationBuilders.terms("brands").field("brand")
                            .subAggregation(AggregationBuilders.avg("priceAvg").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值
            );
            // 2、查询,需要把结果强转为AggregatedPage类型
            AggregatedPage<Item> aggPage = (AggregatedPage<Item>) itemRepository.search(queryBuilder.build());
            // 3、解析
            // 3.1、从结果中取出名为brands的那个聚合,
            // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
            StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
            // 3.2、获取桶
            List<StringTerms.Bucket> buckets = agg.getBuckets();
            // 3.3、遍历
            for (StringTerms.Bucket bucket : buckets) {
                // 3.4、获取桶中的key,即品牌名称  3.5、获取桶中的文档数量
                System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");
    
                // 3.6.获取子聚合结果:
                InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");
                System.out.println("平均售价:" + avg.getValue());
            }
    
        }
    }
    

    高亮搜索

    public class ES {
        @Resource
        private RestHighLevelClient restHighLevelClient;
    
        @RequestMapping("/highlight")
        public List highlight(@RequestParam("search") String search) throws IOException {
            SearchRequest searchRequest = new SearchRequest();
            //搜索体(可以添加多个搜索参数)
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    
            QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder(search);
            queryBuilder.field("title");
    
            //构建高亮体
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("title");
            highlightBuilder.preTags("<span style="color:red">");
            highlightBuilder.postTags("</span>");
    //        highlightBuilder.requireFieldMatch(false);
    
            //搜索体(添加多个搜索参数)
            searchSourceBuilder.highlighter(highlightBuilder);
            searchSourceBuilder.query(queryBuilder);
            searchSourceBuilder.from(1).size(10);
            searchRequest.source(searchSourceBuilder);
    
    
            //执行查询
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
    
            //获取搜索的文档结果
            List<Map<String,Object>> list = new ArrayList<>();
            for (SearchHit documentFields : searchResponse.getHits().getHits()) {
                Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
                HighlightField title = highlightFields.get("title");
                Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
                sourceAsMap.put("title",title);
                System.out.println(title);
                list.add(sourceAsMap);
            }
            return list;
        }
    
    }
    

    同款

  • 相关阅读:
    PHP 包含文件路径问题
    PHP显示今天、今月、上月、今年的起点/终点时间戳
    PHP Web基础教程
    php如何生成随机密码的几种方法
    You don't have permission to access /~whpc on this server.
    linux 网络 PING IP可以通,ping域名ping不通
    CPU : 二级缓存容量
    简单建立个人WEB网站
    MKL程序编译与连接:Lapack篇
    ldd命令原理与使用
  • 原文地址:https://www.cnblogs.com/pengdt/p/13523332.html
Copyright © 2011-2022 走看看