Elasticsearch的基本使用

Elasticsearch的思想

  1. 将需要存入的数据,除去存入数据库外,另存入Elasticsearch服务器中一份,并对数据中的属性进行分词
  2. Elasticsearch服务器中存储进行分词后的各种数据,使用键值对进行保存。键为分割的词,值为存储的数据
  3. 当需要查询数据时候,查询Elasticsearch服务器,服务器会将输入的查询数据进行分词,并对自己内部保存的键值对的键进行匹配,将键值匹配的所有的值返回,就可以得到模糊匹配的搜索结果

ps:小弟总结的,不对的话大佬们请指出

Elasticsearch的核心概念

  1. 索引库(Indices):索引库里面存储索引,一个索引库对应一个DataBase(数据库)。

  2. 类型(Type):索引库里面存储索引,一个索引库对应一个DataBase(数据库),那么索引库里面的一个索引就对应数据库里面的一张表,而Type其实就是索引名(表名)一样。

  3. 文档(Document):就是索引里面的一条数据,一般都是Json数据。和数据库对比,就是表中的一行数据,在java 里面就对应一个对象。

  4. 字段(Field):Json中的属性,对象的属性,对应数据库表中的列。

  5. Mappings:字段的映射,相当于表中列的类型约束(int,varchar…)

    ElasticsearchMysql
    Indices(索引库)DataBase(数据库)
    Type_doc–Index(索引)Table(表)
    Document(文档)–JSONRow(行)
    Field(字段)Column(列)
    Mappings(映射)列的类型约束(int,varchar…)
  6. 节点:一台运行elasticsearch的服务器,被称为一个节点。

  7. 集群:多个节点组成一个集群。

  8. 分片:一个索引可以存储在多个主分片上,有负载均衡的作用,还有从分片是主分片的一个副本。

  9. 副本:一份数据可以有多个副本,做数据冗余(安全),一般放在从分片里面。

Elasticsearch基本使用

Elasticsearch是基于Restful风格的http应用。
Restful风格就是使用http动词形式对url资源进行操作(GET(查)、POST(改)、PUT(增)、DELETE(删))。

Springboot创建索引

  1. pom文件

            <!--        引入elasticsearch的启动器依赖-->
    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
    
  2. 配置文件:application.properties

    #连接ES
    spring.elasticsearch.rest.uris=http://192.168.9.128:9200
    
  3. 创建索引

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    /*
     * @Document() 注解的 主要属性
     * indexName:设置索引名称;格式一般为类名_index
     * refreshInterval:设置索引的刷新间隔
     * shards:设置创建几个主片
     * replicas:设置每个主片有几个从片
     */
    @Document(indexName = "good_index")
    public class Goods {
        
        /*
            @Field() 注解的 主要属性:
                1)name/value属性:指定实体类的属性映射的索引的字段名,如果不指定默认就是实体类的属性名;
                2)type:指定索引的数据类型,值是FieldType的枚举值
                    一般给id字段的类型是FieldType.Keyword,表示关键字,且不会分词
                    属性的数据类型为String时候,对应的FieldType的枚举值为FieldType.Text
                    属性的数据类型为Date时候,对应的FieldType的枚举值为FieldType.Date,并且指明格式化方式
                3)format = DateFormat.date;当参数的数据类型为Date时候,改参数为设置Date的格式化方式
                4)analyzer = "ik_max_word":表示给字段添加数据时使用ik_max_word模式进行分词{添加属性后对改属性的值进行分词};
                5)searchAnalyzer = "ik_max_word":表示搜索字段也使用ik_max_word模式进行分词{添加属性后对改属性的值进行分词};
            @Id 注解:表示goodsId属性是索引的文档id(主键id);
         */
        @Id
        @Field(value = "goodsId", type = FieldType.Keyword)
        private Integer goodsId;
    
        @Field(value = "goodsName", type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
        private String goodsName;
    
        /*
        价格因为不用进行分词,所以就不需要添加analyzer属性和searchAnalyzer属性了
         */
        @Field(value = "goodsPrice")
        private Double goodsPrice;
        
        @Field(value = "goodsUpTime", type = FieldType.Date, format = DateFormat.date)
        private Date goodsUpTime;
    }
    
  4. 创建接口,继承ElasticsearchRepository接口;标记@Repository注解

    /*
      继承的接口ElasticsearchRepository的泛型:
        1)索引映射的实体类类型
        2)索引的主键id的类型
     */
    @Repository
    public interface CreateGoodsIndex extends ElasticsearchRepository<Goods, Integer> {
    
    }
    
  5. 在启动项目的时候,就会根据实体类中声明的属性,创建索引

Springboot针对索引的基本的CRUD

添加信息:

//注入继承接口ElasticsearchRepository的那个自定义的接口
    @Autowired
    private CreateGoodsIndex generateGoodsIndex;
generateGoodsIndex.save(new Goods(1, "张三峰", 1000D, new Date()));
//添加单行数据
//一次添加多行数据
        ArrayList<Goods> goods = new ArrayList<>();
        goods.add(new Goods(2, "张四峰", 1000D, new Date()));
        goods.add(new Goods(3, "张五峰", 1000D, new Date()));
        goods.add(new Goods(4, "张六峰", 1000D, new Date()));
        goods.add(new Goods(5, "张七峰", 1000D, new Date()));
        goods.add(new Goods(6, "张八峰", 1000D, new Date()));
        generateGoodsIndex.saveAll(goods);

删除信息

        //删除单个
        generateGoodsIndex.delete(new Goods(2, "张四峰","西巴 奥里给 小日本",strings, 1000D, new Date()));
        //删除所有
        generateGoodsIndex.deleteAll();
        //删除主键为?的指定
        generateGoodsIndex.deleteById(3);
        //删除列表的所有数据
        generateGoodsIndex.deleteAll(new ArrayList<Goods>());

修改信息===没有直接修改方法,得先查,再改,最后再保存


查询信息:

		//无条件查询所有
        generateGoodsIndex.findAll();
        //查询所有并分页 generateGoodsIndex.findAll(Pageable pageable);
        //generateGoodsIndex.findAll(Sort sort)  查询,并排序
        

复杂查询{DSL查询}

查询条件:

  1. match:会通过分词器对查询内容进行分词,然后再通过分词进行查询。例如:搜索联想电脑,会分词成’联想’和’电脑’,再把包含’联想’和’电脑’的都查出来。
  2. term:不做分词,通过Keyword类型的关键字进行精确查找。例如:搜索商品id为5的商品。
  3. matchPhrase:不做分词,通过指定内容进行精确查找。例如:搜索联想电脑,就只查名称包含联想电脑。
  4. range:范围查询。例如:查询价格在5000到8000的商品。
  5. match 和 rang 如果同时使用,需要通过bool将二者组合起来查询。

查询常用类:

  1. QueryBuilders:用于构造条件对象,如match条件对象matchQuery、range条件对象rangeQuery、matchPhrase条件对象matchPhrase()、boolQuery等。
  2. NativeSearchQueryBuilder:用于组装条件(对象),组装后使用build()构建出查询对象NativeSearchQuery。
  3. HighlightBuilder:用于设置高亮的字段,需使用到它的静态内部类Field。
  4. FunctionScoreQueryBuilder:用于权重查询,需使用它的静态内部类FilterFunctionBuilder。

注入ES模板 — 来实现DSL查询

    //注入ES模板 --- DSL查询
    @Autowired
    private ElasticsearchRestTemplate esTemplate;

math查询:

@Test
    public void testA(){

        //第一步:创建了个match条件的对象 --- 
        //参数一:想要查询索引列的名称
        //参数二:要查询的数据
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("goodsName", "华为手机");

        //第二步:创建条件组装的构建器
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        //第三步:组装条件
        searchQueryBuilder.withQuery(matchQuery);

        //第四步:构建出条件的封装对象
        NativeSearchQuery searchQuery = searchQueryBuilder.build();

        //第五步:查询
        //参数一:第四步创建的封装条件的对象
        //参数二:返回值的泛型类
        SearchHits<Goods> searchHits = esTemplate.search(searchQuery, Goods.class);

        //第六步:从查询结果中提取数据 --- 每个SearchHit<Goods>对象就代表从索引中查询到的一条数据 -- 而每个SearchHit又都封装了一个Goods对象
        List<SearchHit<Goods>> searchHitList = searchHits.getSearchHits();
        for (SearchHit<Goods> searchHit : searchHitList) {
            //取每个SearchHit封装的Goods对象
            Goods goods = searchHit.getContent();
            System.out.println(goods);
        }
    }

term关键字精确查询

    @Test
    public void testB(){

        //第一步:创建了个term条件的对象 --- 
        //参数一:想要查询索引列的名称
        //参数二:要查询的数据
        TermQueryBuilder termQuery = QueryBuilders.termQuery("goodsId", 10);

        //通过条件组装器组装条件并返回封装了条件的对象,链式调用
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(termQuery)
                .build();

        //查询
        //参数一:第四步创建的封装条件的对象
        //参数二:返回值的泛型类
        SearchHits<Goods> searchHits = esTemplate.search(searchQuery, Goods.class);

        //从查询结果中提取数据 --- 每个SearchHit<Goods>对象就代表从索引中查询到的一条数据 -- 而每个SearchHit又都封装了一个Goods对象
        List<SearchHit<Goods>> searchHitList = searchHits.getSearchHits();
        for (SearchHit<Goods> searchHit : searchHitList) {
            //取每个SearchHit封装的Goods对象
            Goods goods = searchHit.getContent();
            System.out.println(goods);
        }
    }

多条查询 — 分词查询 范围查询 分页查询 排序

	@Test
    public void testD(){

        //创建一个match条件对象
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("goodsName", "华为小米");

        //创建一个range条件的对象 --- 根据goodsPrice字段,查询商品价格在4500到5500之间的商品
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("goodsPrice").from(4500D).to(5500D);

        //创建一个bool条件对象,将match条件对象和range条件的对象关联起来
        BoolQueryBuilder boolQuery = QueryBuilders
            //创建bool条件对象
            .boolQuery()
            //链接上边创建的match对象
            .must(matchQuery)
            //链接上边创建的range对象
            .must(rangeQuery);

        //创建条件组装器组装所有条件并构建出封装了所有条件的对象
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            	//组装的bool条件(其实是match和range条件)
                .withQuery(boolQuery)
            	//分页条件(ES分页页码从0开始)
                .withPageable(PageRequest.of(1, 5))
            	//排序条件,根据传入的列名进行排序
                .withSort(SortBuilders.fieldSort("goodsPrice")
                          		//按照goodsPrice降序排序
                          		.order(SortOrder.DESC))
                .build();

        //查询
        SearchHits<Goods> searchHits = esTemplate.search(searchQuery, Goods.class);

        //从查询结果中提取数据 --- 每个SearchHit<Goods>对象就代表从索引中查询到的一条数据 -- 而每个SearchHit又都封装了一个Goods对象
        List<SearchHit<Goods>> searchHitList = searchHits.getSearchHits();
        for (SearchHit<Goods> searchHit : searchHitList) {
            //取每个SearchHit封装的Goods对象
            Goods goods = searchHit.getContent();
            System.out.println(goods);
        }
    }

高亮字段处理

/*
	高亮处理的说明:
      1)输入的内容是什么,一般就是对什么内容做高亮处理
      2)高亮处理的本质就是文本两端添加了可以进行高亮显示的html的标签文本
*/
@Test
    public void testE(){

        //创建个match条件对象
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("goodsName", "华为");

        /*
          配置高亮字段 --- 上边match条件是按照goodsName字段,分词查询商品名称中包含华为分词的商品,
          所以此处配置的高亮字段也是goodsName,且只对字段goodsName中的内容华为做高亮处理;
         */
        HighlightBuilder.Field goodsNameField = new HighlightBuilder.Field("goodsName");
        //配置需要高亮字段的前缀span标签
        goodsNameField.preTags("<span style='color:red;'>");
        //配置需要高亮字段的后缀span标签
        goodsNameField.postTags("</span>");

        //创建条件组装器并组装条件然后构建出封装了所有条件的对象
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(matchQuery)
            	//组装配置的高亮字段
                .withHighlightFields(goodsNameField)
                .build();

        //查询
        SearchHits<Goods> searchHits = esTemplate.search(searchQuery, Goods.class);

        //从查询结果中提取数据 --- 每个SearchHit<Goods>对象就代表从索引中查询到的一条数据 -- 而每个SearchHit又都封装了一个Goods对象
        List<SearchHit<Goods>> searchHitList = searchHits.getSearchHits();
        for (SearchHit<Goods> searchHit : searchHitList) {
            //取每个SearchHit封装的Goods对象
            Goods goods = searchHit.getContent();

            //再取出每个SearchHit进行了高亮处理的字段
            String highLightGoodsName = searchHit.getHighlightField("goodsName").get(0);
            //使用进行了高亮处理的goodsName字段替换Goods对象中goodsName字段
            goods.setGoodsName(highLightGoodsName);

            System.out.println(goods);
        }
    }

权重查询

@Test
    public void testF(){
        //搜索的内容包含商品名称和描述
        String keyWords = "华为发热";

        //创建权重数组,根据需要搜索的内容的数量进行排序
        FunctionScoreQueryBuilder.FilterFunctionBuilder[] functionBuilders =
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[2];

        //设置商品名称的权重为5
        functionBuilders[0] = (new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                QueryBuilders.matchQuery("goodsName", keyWords),
                ScoreFunctionBuilders.weightFactorFunction(10)
        ));

        //设置商品描述的权重为10
        functionBuilders[1] = (
                new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                        QueryBuilders.matchQuery("goodsDesc", keyWords),
                        ScoreFunctionBuilders.weightFactorFunction(5)
                ));

        FunctionScoreQueryBuilder functionScoreQueryBuilder =
                new FunctionScoreQueryBuilder(functionBuilders);

        functionScoreQueryBuilder.setMinScore(2)//设置最小分数
                .scoreMode(FunctionScoreQuery.ScoreMode.FIRST);//设置计分方式

        //构建出查询对象NativeSearchQuery
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(functionScoreQueryBuilder)
                .build();

        //查询
        SearchHits<Goods> searchHits = esTemplate.search(nativeSearchQuery, Goods.class);

        //提取查询结果
        List<SearchHit<Goods>> searchHitList = searchHits.getSearchHits();
        for (SearchHit<Goods> searchHit : searchHitList) {
            Goods goods = searchHit.getContent();
            System.out.println(goods);
        }
    }

SpringBoot操作ES的总结:

1.环境搭建: 1>导入ES的场景启动器 2>配置文件中配置连接的ES服务器的url地址

2.用boot应用程序创建索引: 1>搞个实体类 — 映射索引 — 重点全在实体类中用到的注解

2>搞个Dao接口 — 需要继承ES场景启动器提供的一个接口ElasticsearchRepository:
1)就继承了ElasticsearchRepository接口中提供的一些操作ES索引的方法
2)我们搞的Dao接口把ElasticsearchRepository接口一继承,然后在Boot应用启动我们搞的Dao接口
加入IOC容器的时候,就会自动根据实体类给我们创建索引

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值