• Elasticsearch概述


    Elasticsearch是什么

    The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。 能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。Elaticsearch,简称为 ES,ES 是一个开源的高扩展的分布式全文搜索引擎,是整个 Elastic Stack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据

    全文搜索引擎

    Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
    一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
    基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差的:

    • 搜索的数据对象是大量的非结构化的文本数据
    • 文件记录量达到数十万或数百万个甚至更多
    • 支持大量基于交互式文本的查询。
    • 需求非常灵活的全文搜索查询。
    • 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足
    • 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。 为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎

    Elasticsearch And Solr

    Lucene 是 Apache 软件基金会 Jakarta 项目组的一个子项目,提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在 Java 开发环境里 Lucene 是一个成熟的免费开源 工具。就其本身而言,Lucene 是当前以及最近几年最受欢迎的免费 Java 信息检索程序库。 但 Lucene 只是一个提供全文搜索功能类库的核心工具包,而真正使用它还需要一个完善的 服务框架搭建起来进行应用。
    目前市面上流行的搜索引擎软件,主流的就两款:Elasticsearch 和 Solr,这两款都是基 于 Lucene 搭建的,可以独立部署启动的搜索引擎服务软件。由于内核相同,所以两者除了 服务器安装、部署、管理、集群以外,对于数据的操作 修改、添加、保存、查询等等都十 分类似。
    在使用过程中,一般都会将 Elasticsearch 和 Solr 这两个软件对比,然后进行选型。这两 个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 Lucene 构建的,但它们又是不同的。像所有东西一样,每个都有其优点和缺点:

    无论选择 Solr 还是 Elasticsearch,首先需要了解正确的用例和未来需求。总结一下Elasticsearch的特点:

    • 由于易于使用,Elasticsearch 在新开发者中更受欢迎。一个下载和一个命令就可以启动一切
    • 如果除了搜索文本之外还需要它来处理分析查询,Elasticsearch 是更好的选择
    • 如果需要分布式索引,则需要选择 Elasticsearch。对于需要良好可伸缩性和以及性能分布式环境,Elasticsearch 是更好的选择
    • Elasticsearch 在开源日志管理用例中占据主导地位,许多组织在 Elasticsearch 中索引它们的日志以使其可搜索
    • 如果你喜欢监控和指标,那么请使用 Elasticsearch,因为相对于 Solr,Elasticsearch 暴露了更多的关键指标

    Elasticsearch 安装

    Elasticsearch 的官方地址:https://www.elastic.co/cn/

    目录结构如下:

    目录 含义
    bin 可执行脚本目录
    config 配置目录
    jdk 内置 JDK 目录
    lib 类库
    logs 日志目录
    modules 模块目录
    plugins 插件目录

    进入bin目录,启动elasticsearch即可启动服务

    [2021-04-13T13:19:55,134][INFO ][o.e.n.Node               ] [B-LW01J1WL-0028.local] initialized
    [2021-04-13T13:19:55,134][INFO ][o.e.n.Node               ] [B-LW01J1WL-0028.local] starting ...
    [2021-04-13T13:19:55,193][INFO ][o.e.x.s.c.PersistentCache] [B-LW01J1WL-0028.local] persistent cache index loaded
    [2021-04-13T13:20:00,475][INFO ][o.e.t.TransportService   ] [B-LW01J1WL-0028.local] publish_address {127.0.0.1:9300}, bound_addresses {[::1]:9300}, {127.0.0.1:9300}
    [2021-04-13T13:20:00,821][WARN ][o.e.b.BootstrapChecks    ] [B-LW01J1WL-0028.local] the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
    [2021-04-13T13:20:00,835][INFO ][o.e.c.c.ClusterBootstrapService] [B-LW01J1WL-0028.local] no discovery configuration found, will perform best-effort cluster bootstrapping after [3s] unless existing master is discovered
    [2021-04-13T13:20:03,845][INFO ][o.e.c.c.Coordinator      ] [B-LW01J1WL-0028.local] setting initial configuration to VotingConfiguration{havNlIPpSIKsyb4mq42F3Q}
    [2021-04-13T13:20:04,170][INFO ][o.e.c.s.MasterService    ] [B-LW01J1WL-0028.local] elected-as-master ([1] nodes joined)[{B-LW01J1WL-0028.local}{havNlIPpSIKsyb4mq42F3Q}{GWO-_Ju0TgKDaXcELngWqw}{127.0.0.1}{127.0.0.1:9300}{cdfhilmrstw}{ml.machine_memory=8589934592, xpack.installed=true, transform.node=true, ml.max_open_jobs=20, ml.max_jvm_size=4294967296} elect leader, _BECOME_MASTER_TASK_, _FINISH_ELECTION_], term: 1, version: 1, delta: master node changed {previous [], current [{B-LW01J1WL-0028.local}{havNlIPpSIKsyb4mq42F3Q}{GWO-_Ju0TgKDaXcELngWqw}{127.0.0.1}{127.0.0.1:9300}{cdfhilmrstw}{ml.machine_memory=8589934592, xpack.installed=true, transform.node=true, ml.max_open_jobs=20, ml.max_jvm_size=4294967296}]}
    [2021-04-13T13:20:04,256][INFO ][o.e.c.c.CoordinationState] [B-LW01J1WL-0028.local] cluster UUID set to [8s0OS-nhQHazoUw6adHJEw]
    [2021-04-13T13:20:04,324][INFO ][o.e.c.s.ClusterApplierService] [B-LW01J1WL-0028.local] master node changed {previous [], current [{B-LW01J1WL-0028.local}{havNlIPpSIKsyb4mq42F3Q}{GWO-_Ju0TgKDaXcELngWqw}{127.0.0.1}{127.0.0.1:9300}{cdfhilmrstw}{ml.machine_memory=8589934592, xpack.installed=true, transform.node=true, ml.max_open_jobs=20, ml.max_jvm_size=4294967296}]}, term: 1, version: 1, reason: Publication{term=1, version=1}
    [2021-04-13T13:20:04,431][INFO ][o.e.h.AbstractHttpServerTransport] [B-LW01J1WL-0028.local] publish_address {127.0.0.1:9200}, bound_addresses {[::1]:9200}, {127.0.0.1:9200}
    [2021-04-13T13:20:04,434][INFO ][o.e.n.Node               ] [B-LW01J1WL-0028.local] started
    
    

    9300端口为 Elasticsearch 集群间组件的通信端口,9200 端口为浏览器访问的 http 协议 RESTful 端口

    // 访问服务
    huanliu@B-LW01J1WL-0028 ~ % curl http://127.0.0.1:9200
    {
      "name" : "B-LW01J1WL-0028.local",
      "cluster_name" : "elasticsearch",
      "cluster_uuid" : "8s0OS-nhQHazoUw6adHJEw",
      "version" : {
        "number" : "7.12.0",
        "build_flavor" : "default",
        "build_type" : "tar",
        "build_hash" : "78722783c38caa25a70982b5b042074cde5d3b3a",
        "build_date" : "2021-03-18T06:17:15.410153305Z",
        "build_snapshot" : false,
        "lucene_version" : "8.8.0",
        "minimum_wire_compatibility_version" : "6.8.0",
        "minimum_index_compatibility_version" : "6.0.0-beta1"
      },
      "tagline" : "You Know, for Search"
    }
    

    数据格式


    Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。为了方便理解,我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比:ES 里的 Index 可以看做一个库,而 Types 相当于表,Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个type,Elasticsearch 7.X 中, Type的概念已经被删除了

    Elasticsearch 基本操作

    索引操作

    // 创建索引,对比关系型数据库,创建索引就等同于创建数据库
    PUT请求:http://127.0.0.1:9200/shopping
    {
        "acknowledged"【响应结果】: true, # true操作成功 
        "shards_acknowledged"【分片结果】: true, # 分片操作成功 
        "index"【索引名称】: "shopping"
    }
    
    // 如果重复添加索引,会返回错误信息
    {
        "error": {
            "root_cause": [
                {
                    "type": "resource_already_exists_exception",
                    "reason": "index [shopping/5upLIUrhTGWX6lWTG6BQBg] already exists",
                    "index_uuid": "5upLIUrhTGWX6lWTG6BQBg",
                    "index": "shopping"
                }
            ],
            "type": "resource_already_exists_exception",
            // 索引已存在
            "reason": "index [shopping/5upLIUrhTGWX6lWTG6BQBg] already exists",
            "index_uuid": "5upLIUrhTGWX6lWTG6BQBg",
            "index": "shopping"
        },
        "status": 400
    }
    
    // 查看所有索引
    GET请求:http://127.0.0.1:9200/_cat/indices?v
    /**
     * 这里请求路径中的_cat 表示查看的意思,indices 表示索引,所以整体含义就是查看当前 ES 服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉,服务器响应结果如下
     * health:当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常)
     * status:索引打开、关闭状态
     * index:索引名
     * uuid:索引统一编号
     * pri:主分片数量
     * rep:副本数量
     * docs.count:可用文档数量
     * docs.deleted:文档删除状态(逻辑删除)
     * store.size:主分片和副分片整体占空间大小
     * pri.store.size:主分片占空间大小
     */
    health status index    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
    yellow open   shopping 5upLIUrhTGWX6lWTG6BQBg   1   1          0            0       208b           208b
    
    // 查看单个索引
    GET请求:http://127.0.0.1:9200/shopping
    {
        // 索引名
        "shopping": {
            // 别名
            "aliases": {},
            // 映射
            "mappings": {},
           // 设置
            "settings": {
                // 索引
                "index": {
                    "routing": {
                        "allocation": {
                            "include": {
                                "_tier_preference": "data_content"
                            }
                        }
                    },
                    // 主分片数据量
                    "number_of_shards": "1",
                    // 索引名称
                    "provided_name": "shopping",
                    // 创建时间
                    "creation_date": "1618294231972",
                    // 副分片数量
                    "number_of_replicas": "1",
                    // 唯一标识
                    "uuid": "5upLIUrhTGWX6lWTG6BQBg",
                    // 版本
                    "version": {
                        "created": "7120099"
                    }
                }
            }
        }
    }
    
    // 删除索引
    DELETE请求:http://127.0.0.1:9200/shopping
    {
        "acknowledged": true
    }
    
    // 重复请求会报错
    {
        "error": {
            "root_cause": [
                {
                    "type": "index_not_found_exception",
                    "reason": "no such index [shopping]",
                    "resource.type": "index_or_alias",
                    "resource.id": "shopping",
                    "index_uuid": "_na_",
                    "index": "shopping"
                }
            ],
            "type": "index_not_found_exception",
            "reason": "no such index [shopping]",
            "resource.type": "index_or_alias",
            "resource.id": "shopping",
            "index_uuid": "_na_",
            "index": "shopping"
        },
        "status": 404
    }
    

    文档操作

    // 创建文档,索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数 据库中的表数据,添加的数据格式为 JSON 格式
    POST 请求 :http://127.0.0.1:9200/shopping/_doc
    请求体:
    // 这里数据创建后,由于没有指定数据唯一性标识(ID),默认情况下,ES 服务器会随机 生成一个。 如果想要自定义唯一性标识,需要在创建时指定:http://127.0.0.1:9200/shopping/_doc/1
    {
        "title":"小米手机",
        "category":"小米",
        "image":"https://www.xiaomi.com/1.jpg",
        "price":1999
    }
    
    {
        // 索引
        "_index": "shopping",
        // 类型-文档
        "_type": "_doc",
        // 唯一标识,可以类比为MySQL中的主键,随机生成
        "_id": "6GbxyXgBsiazCaso13gh",
        // 版本
        "_version": 1,
        // 结果,这里的create表示创建成功
        "result": "created",
        // 分片
        "_shards": {
            // 总数
            "total": 2,
            // 成功
            "successful": 1,
            // 失败
            "failed": 0
        },
        "_seq_no": 0,
        "_primary_term": 1
    }
    
    // 查看文档
    GET请求:http://127.0.0.1:9200/shopping/_doc/6GbxyXgBsiazCaso13gh
    {
        // 索引
        "_index": "shopping",
        // 文档类型
        "_type": "_doc",
        "_id": "6GbxyXgBsiazCaso13gh",
        "_version": 1,
        "_seq_no": 0,
        "_primary_term": 1,
        // 查询结果:true表示查找到,false表示未查找到
        "found": true,
        // 文档源信息
        "_source": {
            "title": "小米手机",
            "category": "小米",
            "image": "https://www.xiaomi.com/1.jpg",
            "price": 1999
        }
    }
    
    // 修改文档
    和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖
    POST 请求 :http://127.0.0.1:9200/shopping/_doc/6GbxyXgBsiazCaso13gh
    请求体内容为
    {
        "title": "华为手机",
        "category": "华为",
        "image": "https://www.huawei.com/1.jpg",
        "price": 2999
    }
    
    {
        "_index": "shopping",
        "_type": "_doc",
        "_id": "6GbxyXgBsiazCaso13gh",
        // 版本
        "_version": 2,
        // 结果,updated表示数据被更新
        "result": "updated",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 1,
        "_primary_term": 1
    }
    
    // 修改字段,修改数据时,也可以只修改某一给条数据的局部信息
    POST 请求 :http://127.0.0.1:9200/shopping/_update/6GbxyXgBsiazCaso13gh
    {
        "doc": {
            "price":3000.00 
        }
    }
    
    {
        "_index": "shopping",
        "_type": "_doc",
        "_id": "6GbxyXgBsiazCaso13gh",
        "_version": 3,
        "result": "updated",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 2,
        "_primary_term": 1
    }
    
    // 删除文档,删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。
    DELETE 请求 :http://127.0.0.1:9200/shopping/_doc/6GbxyXgBsiazCaso13gh
    {
        "_index": "shopping",
        "_type": "_doc",
        "_id": "1",
        //#对数据的操作,都会更新版本
        "_version" : 4,
        // deleted表示数据被标记为删除 
        "result"【结果】: "deleted",
        "_shards": {
               "total": 2,
               "successful": 1,
               "failed": 0
           },
           "_seq_no": 4,
           "_primary_term": 2
    }
    
    // 条件删除文档:一般删除数据都是根据文档的唯一性标识进行删除,实际操作时,也可以根据条件对多条数据进行删除
    POST 请求 :http://127.0.0.1:9200/shopping/_delete_by_query
    请求体内容为:
    {
        "query":{
            "match":{ 
                "price":4000.00
            } 
        }
    }
    
    {
        // 耗时
        "took": 175,
        // 是否超时 
        "timed_out": false, 
        // 总数
        "total": 2,
        // 删除数量 
        "deleted": 2,
        "batches": 1,
        "version_conflicts": 0,
        "noops": 0,
        "retries": {
               "bulk": 0,
               "search": 0
         },
        "throttled_millis": 0, 
        "requests_per_second": -1.0, 
        "throttled_until_millis": 0, 
        "failures": []
    }
    

    映射操作

    有了索引库,等于有了数据库中的 database。接下来就需要建索引库(index)中的映射了,类似于数据库(database)中的表结构(table)。 创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。

    // 创建映射
    PUT 请求 :http://127.0.0.1:9200/student/_mapping
    //
    // 映射说明:
    // 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
    // type:类型,Elasticsearch中支持的数据类型非常丰富,说几个关键的:
    //           String 类型,又分两种: 
    //                   text:可分词
    //                   keyword:不可分词,数据会作为完整字段进行匹配
    //           Numerical:数值类型,分两类
    //                   基本数据类型:long、integer、short、byte、double、float、half_float
    //                   浮点数的高精度类型:scaled_float
    //           Date:日期类型
    //           Array:数组类型
    //           Object:对象
    // index:是否索引,默认为true,也就是说你不进行任何配置,所有字段都会被索引。
    //           true:字段会被索引,则可以用来进行搜索
    //           false:字段不会被索引,不能用来搜索
    // store:是否将数据进行独立存储,默认为 false。原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储 的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置 "store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用 更多的空间,所以要根据实际业务需求来设置。
    // analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器
    {
        "properties": {
             "name":{
                 "type": "text",
                 "index": true
             }, 
             "sex":{
                 "type": "text",
                 "index": false
              },
              "age":{
                 "type": "long",
                 "index": false
              } 
        }
    }
    
    // 查看映射
    GET 请求 :http://127.0.0.1:9200/student/_mapping
    {
        "student": {
            "mappings": {
                "properties": {
                    "age": {
                        "type": "long",
                        "index": false
                    },
                    "name": {
                        "type": "text"
                    },
                    "sex": {
                        "type": "text",
                        "index": false
                    }
                }
            }
        }
    }
    
    // 索引映射关联
     PUT 请求 :http://127.0.0.1:9200/student1
    请求体:
    {
    	"settings": {},
    	"mappings": {
    		"properties": {
    			"name": {
    				"type": "text",
    				"index": true
    			},
    			"sex": {
    				"type": "text",
    				"index": false
    			},
    			"age": {
    				"type": "long",
    				"index": false
    			}
    		}
    	}
    }
    
  • 相关阅读:
    python 输入年月日,返回当天是星期几
    python isdigit()函数
    python 字典复制(存疑)
    python 文本文件操作
    python 字符串实例:检查并判断密码字符串的安全强度
    python isinstance()判断数据类型
    python 字符串方法
    python format使用方法
    python 关于异常处理 try...except... 的两个案例
    gparted 不能起作用的时候,用fdisk
  • 原文地址:https://www.cnblogs.com/ding-dang/p/14653418.html
Copyright © 2020-2023  润新知