当前位置 博文首页 > 努力充实,远方可期:【谷粒商城】ElasticSearch、上架与检索

    努力充实,远方可期:【谷粒商城】ElasticSearch、上架与检索

    作者:[db:作者] 时间:2021-08-11 09:58

    • 笔记-基础篇-1(P1-P28):https://blog.csdn.net/hancoder/article/details/106922139

    • 笔记-基础篇-2(P28-P100):https://blog.csdn.net/hancoder/article/details/107612619

    • 笔记-高级篇(P340):https://blog.csdn.net/hancoder/article/details/107612746

    • 笔记-vue:https://blog.csdn.net/hancoder/article/details/107007605

    • 笔记-elastic search、上架、检索:https://blog.csdn.net/hancoder/article/details/113922398

    • 笔记-认证服务:https://blog.csdn.net/hancoder/article/details/114242184

    • 笔记-分布式锁与缓存:https://blog.csdn.net/hancoder/article/details/114004280

    • 笔记-集群篇:https://blog.csdn.net/hancoder/article/details/107612802

    • springcloud笔记:https://blog.csdn.net/hancoder/article/details/109063671

    • 笔记版本说明:2020年提供过笔记文档,但只有P1-P50的内容,2021年整理了P340的内容。请点击标题下面分栏查看系列笔记

    • 声明:

      • 可以白嫖,但请勿转载发布,笔记手打不易
      • 本系列笔记不断迭代优化,csdn:hancoder上是最新版内容,10W字都是在csdn免费开放观看的。
      • 离线md笔记文件获取方式见文末。2021-3版本的md笔记打完压缩包共500k(云图床),包括本项目笔记,还有cloud、docker、mybatis-plus、rabbitMQ等个人相关笔记
    • sql:https://github.com/FermHan/gulimall/sql文件

    • 本项目其他笔记见专栏:https://blog.csdn.net/hancoder/category_10822407.html

    请直接ctrl+F搜索内容

    一、ELASTIC SEARCH

    0、简介

    mysql用作持久化存储,ES用作检索

    基本概念:index库>type表>document文档

    1. index索引

    动词:相当于mysql的insert

    名词:相当于mysql的db

    1. Type类型

    在index中,可以定义一个或多个类型

    类似于mysql的table,每一种类型的数据放在一起

    1. Document文档

    保存在某个index下,某种type的一个数据document,文档是json格式的,document就像是mysql中的某个table里面的内容。每一行对应的列叫属性

    为什么ES搜索快?倒排索引

    保存的记录

    • 红海行动
    • 探索红海行动
    • 红海特别行动
    • 红海记录片
    • 特工红海特别探索

    将内容分词就记录到索引中

    记录
    红海1,2,3,4,5
    行动1,2,3
    探索2,5
    特别3,5
    纪录片4,
    特工5

    检索:

    1)、红海特工行动?查出后计算相关性得分:3号记录命中了2次,且3号本身才有3个单词,2/3,所以3号最匹配
    2)、红海行动?

    关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用,但ES中不是这样的。elasticsearch是基于Lucene开发的搜索引擎,而ES中不同type下名称相同的filed最终在Lucene中的处理方式是一样的。

    • 两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed,你必须在两个不同的type中定义相同的filed映射。否则,不同type中的相同字段名称就会在处理中出现冲突的情况,导致Lucene处理效率下降。
    • 去掉type就是为了提高ES处理数据的效率。
    • Elasticsearch 7.xURL中的type参数为可选。比如,索引一个文档不再要求提供文档类型。
    • Elasticsearch 8.x不再支持URL中的type参数。
      解决:将索引从多类型迁移到单类型,每种类型文档一个独立索引

    1、安装elastic search

    dokcer中安装elastic search

    (1)下载ealastic search(存储和检索)和kibana(可视化检索)

    docker pull elasticsearch:7.4.2
    docker pull kibana:7.4.2
    版本要统一
    

    (2)配置

    # 将docker里的目录挂载到linux的/mydata目录中
    # 修改/mydata就可以改掉docker里的
    mkdir -p /mydata/elasticsearch/config
    mkdir -p /mydata/elasticsearch/data
    
    # es可以被远程任何机器访问
    echo "http.host: 0.0.0.0" >/mydata/elasticsearch/config/elasticsearch.yml
    
    # 递归更改权限,es需要访问
    chmod -R 777 /mydata/elasticsearch/
    

    (3)启动Elastic search

    # 9200是用户交互端口 9300是集群心跳端口
    # -e指定是单阶段运行
    # -e指定占用的内存大小,生产时可以设置32G
    docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
    -e  "discovery.type=single-node" \
    -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
    -v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
    -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
    -v  /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
    -d elasticsearch:7.4.2 
    
    
    # 设置开机启动elasticsearch
    docker update elasticsearch --restart=always
    

    因为容器里的文件映射到了外面,所以删除容器和新建容器数据还在

    第一次查docker ps启动了,第二次查的时候发现关闭了,docker logs elasticsearch

    http://192.168.56.10:9200

    数据挂载到外面,但是访问权限不足

    把/mydata/elasticsearch下文件夹的权限设置好,上面已经设置过了

    遇到了更新阿里源也下载不下来kibana镜像的情况,先在别的网络下载下来后传到vagrant中

    docker save -o kibana.tar kibana:7.4.2 
    
    docker load -i kibana.tar 
    
    # 如何通过其他工具链接ssh
    
    修改/etc/ssh/sshd_config
    修改 PasswordAuthentication yes
    
    systemctl restart sshd.service  或 service sshd restart
    
    # 连接192.168.56.10:22端口成功,用户名root,密码vagrant
    
    也可以通过vagrant ssh-config查看ip和端口,此时是127.0.0.1:2222
    

    在安装离线docker镜像的时候还提示内存不足,看了下是因为外部挂载的内存也算在了vagrant中,即使外部删了很多文件,vagrant中df -h硬盘占用率也不下降。我在外部删完文件后在内部又rm -rf XXX 强行接触占用

    (4)启动kibana:

    # kibana指定了了ES交互端口9200  # 5600位kibana主页端口
    docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.56.10:9200 -p 5601:5601 -d kibana:7.4.2
    
    
    # 设置开机启动kibana
    docker update kibana  --restart=always
    

    (5)测试

    查看elasticsearch版本信息: http://192.168.56.10:9200

    {
        "name": "66718a266132",
        "cluster_name": "elasticsearch",
        "cluster_uuid": "xhDnsLynQ3WyRdYmQk5xhQ",
        "version": {
            "number": "7.4.2",
            "build_flavor": "default",
            "build_type": "docker",
            "build_hash": "2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
            "build_date": "2019-10-28T20:40:44.881551Z",
            "build_snapshot": false,
            "lucene_version": "8.2.0",
            "minimum_wire_compatibility_version": "6.8.0",
            "minimum_index_compatibility_version": "6.0.0-beta1"
        },
        "tagline": "You Know, for Search"
    }
    

    显示elasticsearch 节点信息http://192.168.56.10:9200/_cat/nodes

    127.0.0.1 14 99 25 0.29 0.40 0.22 dilm * 66718a266132
    
    66718a266132代表上面的结点
    *代表是主节点
    
    kibana

    访问Kibana: http://192.168.56.10:5601/app/kibana

    2、初步检索

    1)检索es信息

    (1)GET /_cat/nodes:查看所有节点

    如:http://192.168.56.10:9200/_cat/nodes

    可以直接浏览器输入上面的url,也可以在kibana中输入GET /_cat/nodes

    127.0.0.1 12 97 3 0.00 0.01 0.05 dilm * 66718a266132
    
    66718a266132代表结点
    *代表是主节点
    

    (2)GET /_cat/health:查看es健康状况

    如: http://192.168.56.10:9200/_cat/health

    1613741055 13:24:15 elasticsearch green 1 1 0 0 0 0 0 0 - 100.0%
    

    注:green表示健康值正常

    (3)GET /_cat/master:查看主节点

    如: http://192.168.56.10:9200/_cat/master

    089F76WwSaiJcO6Crk7MpA 127.0.0.1 127.0.0.1 66718a266132
    
    主节点唯一编号
    虚拟机地址
    

    (4)GET/_cat/indicies:查看所有索引 ,等价于mysql数据库的show databases;

    如:http://192.168.56.10:9200/_cat/indices

    green  open .kibana_task_manager_1   DhtDmKrsRDOUHPJm1EFVqQ 1 0 2 3 40.8kb 40.8kb
    green  open .apm-agent-configuration vxzRbo9sQ1SvMtGkx6aAHQ 1 0 0 0   230b   230b
    green  open .kibana_1                rdJ5pejQSKWjKxRtx-EIkQ 1 0 5 1 18.2kb 18.2kb
    
    这3个索引是kibana创建的
    

    2)新增文档

    保存一个数据,保存在哪个索引的哪个类型下(哪张数据库哪张表下),保存时用唯一标识指定

    # # 在customer索引下的external类型下保存1号数据
    PUT customer/external/1
    
    # POSTMAN输入
    http://192.168.56.10:9200/customer/external/1
    
    {
     "name":"John Doe"
    }
    
    PUT和POST区别
    • POST新增。如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号;
      • 可以不指定id,不指定id时永远为创建
      • 指定不存在的id为创建
      • 指定存在的id为更新,而版本号会根据内容变没变而觉得版本号递增与否
    • PUT可以新增也可以修改。PUT必须指定id;由于PUT需要指定id,我们一般用来做修改操作,不指定id会报错。
      • 必须指定id
      • 版本号总会增加
    • 怎么记:put和java里map.put一样必须指定key-value。而post相当于mysql insert

    seq_no和version的区别:

    • 每个文档的版本号"_version" 起始值都为1 每次对当前文档成功操作后都加1
    • 而序列号"_seq_no"则可以看做是索引的信息 在第一次为索引插入数据时为0,每对索引内数据操作成功一次sqlNO加1, 并且文档会记录是第几次操作使它成为现在的情况的

    可以参考https://www.cnblogs.com/Taeso/p/13363136.html

    下面是在postman中的测试数据:

    创建数据成功后,显示201 created表示插入记录成功。

    返回数据:
    带有下划线开头的,称为元数据,反映了当前的基本信息。  
    {
        "_index": "customer", 表明该数据在哪个数据库下;
        "_type": "external", 表明该数据在哪个类型下;
        "_id": "1",  表明被保存数据的id;
        "_version": 1,  被保存数据的版本
        "result": "created", 这里是创建了一条数据,如果重新put一条数据,则该状态会变为updated,并且版本号也会发生变化。
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 0,
        "_primary_term": 1
    }
    

    下面选用POST方式:

    添加数据的时候,不指定ID,会自动的生成id,并且类型是新增:

    {
        "_index": "customer",
        "_type": "external",
        "_id": "5MIjvncBKdY1wAQm-wNZ",
        "_version": 1,
        "result": "created",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 11,
        "_primary_term": 6
    }
    

    再次使用POST插入数据,不指定ID,仍然是新增的:

    {
        "_index": "customer",
        "_type": "external",
        "_id": "5cIkvncBKdY1wAQmcQNk",
        "_version": 1,
        "result": "created",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 12,
        "_primary_term": 6
    }
    

    添加数据的时候,指定ID,会使用该id,并且类型是新增:

    {
        "_index": "customer",
        "_type": "external",
        "_id": "2",
        "_version": 1,
        "result": "created",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 13,
        "_primary_term": 6
    }
    

    再次使用POST插入数据,指定同样的ID,类型为updated

    {
        "_index": "customer",
        "_type": "external",
        "_id": "2",
        "_version": 2,
        "result": "updated",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 14,
        "_primary_term": 6
    }
    

    3)查看文档

    GET /customer/external/1

    http://192.168.56.10:9200/customer/external/1

    {
        "_index": "customer",
        "_type": "external",
        "_id": "1",
        "_version": 10,
        "_seq_no": 18,//并发控制字段,每次更新都会+1,用来做乐观锁
        "_primary_term": 6,//同上,主分片重新分配,如重启,就会变化
        "found": true,
        "_source": {
            "name": "John Doe"
        }
    }
    

    乐观锁用法:通过“if_seq_no=1&if_primary_term=1”,当序列号匹配的时候,才进行修改,否则不修改。

    实例:将id=1的数据更新为name=1,然后再次更新为name=2,起始1_seq_no=18,_primary_term=6

    (1)将name更新为1

    PUT http://192.168.56.10:9200/customer/external/1?if_seq_no=18&if_primary_term=6

    (2)将name更新为2,更新过程中使用seq_no=18

    PUT http://192.168.56.10:9200/customer/external/1?if_seq_no=18&if_primary_term=6

    结果为:

    {
        "error": {
            "root_cause": [
                {
                    "type": "version_conflict_engine_exception",
                    "reason": "[1]: version conflict, required seqNo [18], primary term [6]. current document has seqNo [19] and primary term [6]"