ElasticSearch入门到springboot使用

文章目录

文章整理自:狂神说-es

1.存储引擎产品性能对比

1.Lucence
是一套信息检索工具包,jar包!不包含搜索引擎系统
包含:索引结构、读写索引的工具、排序、搜索规则等工具类

2.Lucence与ElasticSearch关系
ElasticSearch是基于Lucence做了一些封装和增加(上手简单)

3.ElasticSearch与solr的区别
性能对比:以下5图进行了对比
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
ElasticSearch VS solr 总结
1.es基本是开箱即用(解压就可以使用),非常简单。solr安装略微复杂
2.solr利用zookeeper进行分布式管理,而es自身带有分布式协调管理功能
3.solr支持更多数据格式,如JSON、XML、CSV,而es仅支持json文件格式(少而精)。
4.solr官方提供的功能更多,而es本身更注重于核心功能,高级功能多有第三方插件提供(如ik分词器,图形化界面需要kinaba支持)
5.solr查询快,但更新索引时慢(即插入/删除慢),用于电商等查询多的应用;

  • es建立索引快(即查询慢),即时查询快,用于facebook、新浪等搜索
  • solr是传统搜索应用的解决方案,但es更适用于新兴的实时搜索应用
    6.solr比较成熟,有个更大,更成熟的用户、开发和贡献社区,而es相对开发维护者少,更新太快,学习使用成本较高

2.es安装

环境要求:jdk 1.8及以上、es客户端、界面工具
java开发,es的版本和jdk版本要对应
es与kinaba下载版本要一致

1.创建目录

# 创建目录
#es
mkdir -p /opt/apps/es/elasticsearch/{
    
    config,data,plugins}

# kibana
mkdir -p /opt/apps/es/kibana/config

2.创建挂载的配置文件

es配置文件:
vi /opt/apps/es/elasticsearch/config/elasticsearch.yml

http.port: 9200
http.host: 0.0.0.0

http.cors.enabled: true
http.cors.allow-origin: "*"

kibana配置文件
vi/opt/apps/es/kibana/config/kibana.yml

server.name: kibana
# kibana的主机地址 0.0.0.0可表示监听所有IP
server.host: "0.0.0.0"
# kibana访问es的URL
elasticsearch.hosts: [ "http://localhost:9200" ]
#elasticsearch.username: 'kibana'
#elasticsearch.password: '123456'
# 显示登陆页面
#xpack.monitoring.ui.container.elasticsearch.enabled: true
# 语言
i18n.locale: "zh-CN"

3.编写docker-compose

vi /opt/apps/es/docker-compose.yml

version: '3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.9.3
    container_name: elasticsearch
    environment:
      - "discovery.type=single-node"
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./elasticsearch/data:/usr/share/elasticsearch/data 
      - ./elasticsearch/plugins:/usr/share/elasticsearch/plugins
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - 9200:9200
      - 9300:9300
    restart: always
    network_mode: 'host'
  kibana:
    image: docker.elastic.co/kibana/kibana:7.9.3
    volumes:
      - ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
    environment:
      - ELASTICSEARCH_URL=http://localhost:9200
    ports:
      - 5601:5601
    restart: always
    network_mode: 'host'

  es-head:
    image: tobias74/elasticsearch-head:6
    container_name: es-head
    restart: always
    ports:
      - "9100:9100"

4.添加文件夹权限

chmod -R 777 /opt/apps/es/elasticsearch/data

5.启动es与kibana

cd /opt/apps/es
docker-compose up -d

6.开放端口

firewall-cmd --add-port=9200/tcp --permanent
firewall-cmd --add-port=5601/tcp --permanent
firewall-cmd --reload

7.测试访问

es访问地址:
http://ip:9200/
http://192.168.229.132:9200/

kibana访问地址:
http://ip:5601/
http://192.168.229.132:5601/

es-head访问地址:
http://192.168.229.132:9100/

8.安装IK分词器

# 进到es plugins的目录
cd /opt/apps/es/elasticsearch/plugins/

# 创建ik 目录
mkdir ik

# 进到ik
cd /opt/apps/es/elasticsearch/plugins/ik

# 下载方式1:分词器,很慢; 
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.9.3/elasticsearch-analysis-ik-7.9.3.zip

#下载方式2:可以windows直接下载zip包后上传到linux。
# 在谷歌浏览器输入
#https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.9.3/elasticsearch-analysis-ik-7.9.3.zip

# 解压分词器
unzip elasticsearch-analysis-ik-7.9.3.zip

#重启es
docker restart 容器id

kibana入门教程

3.es核心概念

集群、节点、索引、类型、文档、分片、映射是什么

es是面向文档,关系型数据库和es概念对比

在这里插入图片描述
es集群中可包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)

**物理设计 **:
es在后台把每个索引划分成多个分片,每份分片可以在集群中不同的服务器进行迁移

** 逻辑设计**:

1.文档:就是一条数据

es是面向文档的,意味着索引和搜索数据的最小单位是文档,es中文档有几个重要属性

  • 自我包含,一篇文档同时好汉字段和对应的值,也就是同时包含key:value
  • 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的(就是json对象,通过fastjson自动转换)
  • 灵活的结构,文档不依赖预先定义的模式,在关系型数据库中,要提前定义字段才能使用,在es中对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态添加一个新的字段

尽管可以随意的新增或忽略某个子弹,但是每个字段的类型非常重要,比如年龄字段类型,可以是字符或整形。
因为es会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在es中,类型有时候也称为映射类型

2.类型:表字段和类型

3.索引:就是数据库

物理设计:
一个集群至少一个节点,而一个节点就是一个es进程,默认的节点可以有多个索引,如果创建索引,索引将会由5个分片构成(主分片),每个主分片会有一个副本(复制分片)

如下创建了1个索引:P,副本R,分片结果如下:
在这里插入图片描述
上图是一个有3个节点的es集群,可以看到主分片和对应的复制分片都不会再同一个节点内,这样就利于某个节点挂了,数据也不至于丢失。实际上,一个分片就是一个lucence索引,一个包含倒排索引的文件目录,倒排索引的结构使得es在不扫描全部文档的情况下,就能知道哪些文档包含特定的关键字。

倒排索引,优化效率

es使用的一种称为倒排索引的结构,采用lucence倒排索引作为底层。这种结构试用与快速的全文搜索,一个索引由文档中所有不重复的列构成,对于每一个词,都有一个包含他的文档列表。例如现有两个文档,内容如下

sduty every day , good good up to forever # 文档1包含的内容
To forever ,study every day ,good good up  # 文档2包含的内容

为了创建倒排索引,我们首先要将每个文档拆分成独立的词语(或称为词条或tokens),然后创建一个包含所有不重复的词条的排列,单号列出每个词条再哪个文档:
在这里插入图片描述
现在试图搜索to forever,需要查看包含每个词条的文档,如下:
在这里插入图片描述

具体例子:
如现在要搜索linux,那么就根本不会去查询id为1和2的文档,效率非常高
在这里插入图片描述

4.IK分词器

1.概念

分词:即把一段中文或别的划分成一个个关键字,在搜索时候会把自己的信息进行分词,会把数据库中或索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是每个字分为一个词;
比如“小鸡爱吃大米”会分成“小、鸡、爱、吃、大、米”,这显然无法达到分词要求,所以需要安装中文分词起ik分词器来解决

IK提供了两个分词算法:ik_smart和ik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度切分

2.安装

1.ik分词器下载
2.下载后放到es插件包即可
3.解压就可以使用
4.重启es相关服务
在这里插入图片描述

3.测试

kibana上进行操作,测试ik分词器

3.1 ik_smart:最少切分

在这里插入图片描述

3.1 ik_max_word:最细粒度切分

在这里插入图片描述

3.3 ik分词器增加自定义 名词

现象:如“别搞了”,希望分词时出现“别搞了”
在这里插入图片描述
处理方式

3.3.1 在ik目录下增加自己词典

当前目录ik分词器配置目录如下:

/opt/apps/es/elasticsearch/plugins/ik/config

在这里插入图片描述
增加词典:bie.dic

3.3.1 在词典中增加 名词

vi bie.dic
别搞了
#保存

3.3.2 将词典配置到ik配置中

配置文件名:IKAnalyzer.cfg.xml
在这里插入图片描述

3.3.4 重启es,重新加载ik

3.3. 再次测试“别搞了”

在这里插入图片描述

5.Rest风格说明

一种软件架构风格,而不是标准,只是提供了一组设计原则和约束原则。它主要用于客户端和服务器交互类的软件。基于这个风格设计软件可以更加简洁,更有层次,更易于实现缓存等机制。

在这里插入图片描述

6.索引(表)基本操作

6.1 创建

put创建索引

PUT /索引名/类型名/文档id #未来类型名会被去掉
{请求提}

在这里插入图片描述

kibana索引管理:http://192.168.229.132:5601/app/management/data/index_management/indices
在这里插入图片描述

es-head查看索引
在这里插入图片描述

6.2 修改

设定数据类型
为testbie2索引的字段指定数据类型
在这里插入图片描述

获取规则
GET testbie2
在这里插入图片描述
GET命令查看es索引情况
在这里插入图片描述
PUT修改,body里面的类容就是最终值(更新所有)
修改之前testbie/test/1的值,version代表修改版本变化次数
在这里插入图片描述
GET验证修改是否成功:
在这里插入图片描述
post更新/新增
_update后缀,只更新出现的属性
在这里插入图片描述
没有_update后缀,依然是更新所有的属性
在这里插入图片描述

6.3 删除

DELETE删除

删除索引,后缀精确到索引;删除文档行,后缀精确到文档行
在这里插入图片描述

7.文档(数据行)基本操作

7.1 简单查询

GET

GET testbie/test/_search?q=name:

在这里插入图片描述

7.2 复杂查询

select (排序、分页、高亮、模糊查询、精准查询)
查询匹的配度:_score(权重)
在这里插入图片描述

GET复杂查询语法

GET /索引/类型/_search
{ 
#具体查询条件
}

如下图:
在这里插入图片描述
其中hits对应java中的Hits对象,包含以下内容

hit:
1.索引和文档信息
2.查询的结果总数
3.查询出来的具体文档信息
4.查询的数据都可以遍历出来
5.分数越大匹配度越大

返回指定的文档属性

_source与query平级
在这里插入图片描述

排序

sort,与query平级
sort排升序:
在这里插入图片描述

分页

一定要有这两个参数,相当于mysql的limit两个参数
from:0 #从哪里开始
sizi: 10 #取多少条值

在这里插入图片描述

布尔值查询

多条件bool值查询,
must匹配相当于mysql的and操作,所有条件都要符合
must_not 匹配相当于mysql的 != 操作
should 匹配相当于mysql的or操作
在这里插入图片描述

过滤

filter与must平级
gt大于,lt小于,gte大于等于,lte小于等于
在这里插入图片描述

多条件查询

match自带模糊查询,多个条件用空格隔开
在这里插入图片描述

精确查询

term:精确查询
match:模糊查询
term与match平级

两个类型,在设定字段类型时要注意
text:会被分词器解析成多个词
keyworkd:不会被分词器解析
在这里插入图片描述

多条件精确查询

在这里插入图片描述

高亮查询

highlight与query平级,高亮的字段都会用"em"标签包裹返回
在这里插入图片描述
自定义高亮标签:
在这里插入图片描述

8.springboot集成es

es官网 https://www.elastic.co/guide/index.html#viewall
es客户端:
在这里插入图片描述
使用java rest客户端
在这里插入图片描述
es使用java rest客户端对应官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/index.html

1.添加pom依赖

依赖版本需要和es服务端版本一致

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.9.3</version>
</dependency>

2.找对应的Java对象

在这里插入图片描述

3.分析RestHighLevelClient对象的方法

4.es java API操作

1.创建空项目

2.添加springboot innilizer

3.添加默认Developere Tools

4.添加spring data es

5.配置javac的环境1.8,javascript环境es6

在这里插入图片描述

6.更改springboot版本

在这里插入图片描述

7.查看es依赖版本是否与es服务端7.9.3一致

在这里插入图片描述
版本不匹配

8.自定义es依赖版本

在这里插入图片描述

9.再次查看es版本是否已经依赖成功

在这里插入图片描述

10.简单分析es客户端源码

在这里插入图片描述
核心类:RestClietConfigartions

11.配置RestHighLevelClient对象

package com.bie.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author bjh
 * @date 2022/12/9
 */

@Configuration
public class ElasticSearchClientConfig {
    
    

    @Bean
    public RestHighLevelClient restHighLevelClient() {
    
    
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("192.168.229.132", 9200, "http")));
        return client;
    }
}

12.java代码es创建数据

package com.bie;

import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;

/**
 * es 7.9.3客户端api测试
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class JavaEsApiApplicationTests {
    
    

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    /**
     * 创建索引
     * Request
     */
    @Test
    public void createIndex() throws IOException {
    
    
        // 1.创建索引请求
        CreateIndexRequest bieIndex = new CreateIndexRequest("bie_index");
        // 2.执行索引请求
        CreateIndexResponse createIndexResponse =
                this.client.indices().create(bieIndex, RequestOptions.DEFAULT);

        System.out.println(createIndexResponse.toString());
    }
}

13.查看es是否插入成功:成功

在这里插入图片描述

14.获取索引

/**
     * 获取索引
     * @throws IOException
     */
    @Test
    public void getIndex() throws IOException {
    
    
        // 1.创建获取索引请求
        GetIndexRequest bieIndex = new GetIndexRequest("bie_index");
        // 2.执行索引请求
        boolean exists = this.client.indices().exists(bieIndex, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

15.删除索引

/**
     * 删除索引
     *
     * @throws IOException
     */
    @Test
    public void deleteIndex() throws IOException {
    
    
        // 1.创建获取索引请求
        DeleteIndexRequest bieIndex = new DeleteIndexRequest("bie_index");
        // 2.执行索引请求
        boolean isDeleteSuccess = this.client.indices().delete(bieIndex, RequestOptions.DEFAULT).isAcknowledged();
        System.out.println(isDeleteSuccess);
    }

16.创建文档

 /**
     * 添加文档
     *
     * @throws IOException
     */
    @Test
    public void addDoc() throws IOException {
    
    
        // 1.创建 索引请求对象
        IndexRequest indexRequest = new IndexRequest("bie_index");
        indexRequest.timeout(TimeValue.timeValueSeconds(1));
        indexRequest.id("1");

        // 2.创建user对象
        User user = new User();
        user.setAge(18);
        user.setName("java从入门到入魔");

        // 3.对象数据转json
        indexRequest.source(JSON.toJSONString(user), XContentType.JSON);

        // 4.执行请求
        IndexResponse response = this.client.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());  // 返回操作的状态,初次是CREATED,后续修改返回OK
        System.out.println(response.toString());
    }
    
    /**
     * 获取文档,判断是否存在
     *
     * @throws IOException
     */
    @Test
    public void docExist() throws IOException {
    
    
        //1.创建索引请求对象
        GetRequest getRequest = new GetRequest("bie_index", "2");
        //不获取返回的_source上下文,效率高
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        //不排序
        getRequest.storedFields("_none_");

        // 2.执行请求
        boolean exists = this.client.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

17.crud文档


    /**
     * 获取文档信息
     */
    @Test
    public void getDoc() throws IOException {
    
    
        //1.创建索引请求对象
        GetRequest getRequest = new GetRequest("bie_index", "1");
        //2.执行请求
        GetResponse response = this.client.get(getRequest, RequestOptions.DEFAULT);
        //3.获取文档内容
        String sourceAsString = response.getSourceAsString();
        System.out.println(sourceAsString);
    }

    /**
     * 更新文档信息
     */
    @Test
    public void updateDoc() throws IOException {
    
    
        //1.创建 更新索引请求对象
        UpdateRequest updateRequest = new UpdateRequest("bie_index", "1");
        updateRequest.timeout(TimeValue.timeValueSeconds(1));
        //2.封装修改数据
        UpdateRequest request = updateRequest.doc(JSON.toJSONString(new User().setName("哈哈 java")), XContentType.JSON);
        //3.执行请求
        UpdateResponse response = this.client.update(request, RequestOptions.DEFAULT);
        System.out.println(response);
    }

    /**
     * 删除文档信息
     */
    @Test
    public void deleteDoc() throws IOException {
    
    
        DeleteRequest deleteRequest = new DeleteRequest("bie_index", "qVMa-oQBSvq_7IxZDk-f");
        deleteRequest.timeout(TimeValue.timeValueSeconds(1));

        DeleteResponse response = this.client.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }

18.批量操作

/**
     * 批量 操作数据
     */
    @Test
    public void bulkDoc() throws IOException {
    
    
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout(TimeValue.timeValueSeconds(10));    //数据越多,设置操作时间越大

        List<User> users = Arrays.asList(new User("bie", 18), new User("bie3", 28));
        for (int i = 0; i < users.size(); i++) {
    
    
            bulkRequest.add(new IndexRequest("bie_index")
                    .id(String.valueOf(i + 1))
                    .source(JSON.toJSONString(users.get(i)), XContentType.JSON));
        }

        BulkResponse response = this.client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }

19.搜索

常用搜索

  • 精确查询:TermQueryBuilder
  • 全匹配查询:MatchAllQueryBuilder
  • 分页:sourceBuilder.from();sourceBuilder.size()
  • 高亮:sourceBuilder.highlighter()
/**
     * 搜索
     * 常用查询操作:.
     * <p>
     * 精确查询:TermQueryBuilder
     * 全匹配查询:MatchAllQueryBuilder
     * 分页:sourceBuilder.from();sourceBuilder.size()
     * 高亮:sourceBuilder.highlighter()
     */
    @Test
    public void searchDoc() throws IOException {
    
    
        SearchRequest searchRequest = new SearchRequest("bie_index");
        //构建搜索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //QueryBuilders快速构建查询条件。
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", 18);
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(TimeValue.timeValueSeconds(1));

        searchRequest.source(sourceBuilder);

        SearchResponse response = this.client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(response.getHits()));
        for (SearchHit hit : response.getHits().getHits()) {
    
    
            System.out.println(JSON.toJSONString(hit.getSourceAsMap()));
        }
    }

9. 实战京东搜索模拟

猜你喜欢

转载自blog.csdn.net/User_bie/article/details/128191597