开发者

搜索一文入门ElasticSearch(节点 分片 CRUD 倒排索引 分词)

开发者 https://www.devze.com 2023-03-24 10:37 出处:网络 作者: stark张宇
目录ElasticSearch基本概念:索引、文档和REST Apijson文档文档的元数据索引分布式系统的可用性和扩展性分布式特性节点分片查看集群的健康状况CRUD文档的CRUDCreate 一个文档GET 一个文档Index 文档Update 文档删除文
目录
  • ElasticSearch
  • 基本概念:索引、文档和REST Api
    • json文档
    • 文档的元数据
    • 索引
  • 分布式系统的可用性和扩展性
    • 分布式特性
    • 节点
    • 分片
    • 查看集群的健康状况
  • CRUD
    • 文档的CRUD
      • Create 一个文档
      • GET 一个文档
      • Index 文档
      • Update 文档
      • 删除文档
      • Bulk API / 批量读取 mGet / 批量查询 msearch
    • 倒排索引
      • Analysis 与 Analyzer
      • Analyzer的组成
    • Search Api
      • URI Search详解
        • 指定字段查询 Vs 泛查询
        • Term Vs Phrase
        • 布尔操作 、分组
        • 范围查询 、算术符号
        • 通配符查询 、正则表达式 、模糊匹配与近似查询

      ElasticSearch

      ElasticSearch是非常重要的检索工具,利用分词、索引(倒排索引)、分词从众多检索工具中脱颖而出,本章是入门基础学习篇内容。

      基本概念:索引、文档和REST Api

      ElasticSearch是面向文档的,文档是所有可搜索数据的最小单位

      • 日志文件中的日志项
      • 一本电影的具体信息 / 一张唱片的详细信息
      • Mp3播放器的一首歌 / 一篇PDF文档中的具体内容

      文档会被序列化成Josn格式,保存在ElasticSearch中

      • Json对象由字段组成
      • 每个字段都有对应的字段类型(字符串/数值/布尔/日期/二进制/范围类型)

      每个文档都有一个UniqueID

      你可以自己指定ID

      或者通过ElasticSearch自动生成

      Json文档

      • 一篇文档包含了一系列的字段
      • Json文档,格式灵活,不需要预先定义格式
        • 字段的类型可以指定或通过ElasticSearch自动推算
        • 支持数组、支持嵌套

      文档的元数据

      {
          "_index" : ".kibana_1",
          "_type" : "_doc",
          "_id" : "space:default",
          "_score" : 1.0,
          "_source" : {
              "space" : {
              "name" : "默认值",
              "descripti编程客栈on" : "这是您的默认空间!",
              "color" : "#00bfb3",
              "_reserved" : true
              },
              "type" : "space",
              "references" : [ ],
              "updated_at" : "2022-05-13T09:16:16.465Z"
          }
      }
      
      • 元数据,用于标注文档的相关信息
        • _index : 文档所属的索引名
        • _type : 文档所属的类型名
        • _id : 文档唯一ID
        • _source : 文档的原始Json数据
        • _version : 文档的版本信息
        • _score : 相关性打分

      索引

      • index :索引是文档的容器,是一类文档的结合
        • index体现了逻辑空间的概念,每个索引js都有自己的Mapping定义,用于定义包含的文档的字段名和字段类型
        • Shard 体现了物理空间的概念,索引中的数据分散在Shard上
      • 索引的Mapping与Settings
        • Mapping定义文档的字段类型
        • Setting定义不同的数据分布
      //查看索引相关信息
      GET kibana_sample_data_ecommerce
      //查看索引的文档总数
      GET kibana_sample_data_ecommerce/_count
      //查看前10条文档,了解文档格式
      POST kibana_sample_data_ecommerce/_search
      {
      }
      //_cat indices API
      //查看indices
      GET /_cat/indices/kibana*?v&s=index
      //查看状态为绿的索引
      GET /_cat/indices?v&health=green
      //按照文档个数排序
      GET /_cat/indices?v&s=docs.count:desc
      //查看具体的字段
      GET /_cat/indices/kibana*?pri&v&h=health,index,pri,rep,docs.count,mt
      //How much memory is used per index?
      GET /_cat/indices?v&h=i,tm&s=tm:desc
      

      分布式系统的可用性和扩展性

      • 高可用性
        • 服务可用性 :允许有节点停止服务
        • 数据可用性 :部分节点丢失,不会丢失数据
      • 可扩展性
        • 请求量提升 / 数据的不断增长(将数据分布都所有接点上)

      分布式特性

      • elasticsearch的分布式架构的好处
        • 存储的水平扩容
        • 提高系统的可用性,部分节点停止服务,整个集群的服务不受影响
      • elasticsearch的分布式架构
        • 不同的集群通过不同的名字来区分,默认名字"elasticsearch"
        • 通过配置文件修改,或者在命令行中-E cluster.name=stark进行设定
        • 一个集群可以有一个或多个节点

      节点

      • 节点是elasticsearch的实例
        • 本质上就是一个Java进程
        • 一台机器上可以运行多个elasticsearch进程,但是生产环境一般建议一台机器上只运行一个elasticsearch实例
      • 每一个节点都有名字,通过配置文件配置,或者启动的时候-E node.name=node1指定
      • 每一个节点在启动之后,会分配一个UID,保存在data目录下

      分片

      • 主分片,用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上
        • 一个分片是一个运行的Lucene的实例
        • 主分片数在索引创建时指定,后续不允许修改,除非Reindex
      • 副本 ,用以解决数据高可用的问题,分片是主分片的拷贝
        • 副本分片数,可以动态调整
        • 增加副本数,还可以在一WWZfME定程度上提高服务的可用性
      {
          "settings": {
              "number_of_shards": 1,
              "number_of_replicas": 1
          }
      }
      

      查看集群的健康状况

      • Green - 主分片与副本都正常分配
      • Yellow - 主分片全部正常分配,有副本分片未能正常分片
      • Red - 有主分片未能分配

      CRUD

      1.使用PostMan创建一个名字叫stark的索引

      http://127.0.0.1:9200/stark?pretty
      // 返回值
      {
          "acknowledged": true,
          "shards_acknowledged": true,
          "index": "stark"
      }
      

      文档的CRUD

      • Type名,约定都用_doc
      • Create ,如果ID已经存在,会失败
      • Index ,如果ID不存在,创建新的文档。否则先删除现有文档,再创建新的文档,版本会增加。
      • Update ,文档必须已经存在,更新只会对相应字段做增量修改。

      Create 一个文档

      支持自动生成文档ID和指定文档ID两种方式:

      • 使用POST /indexName/_doc,系统会自动生成Document ID
      • 使用PUT /indexName/_create/ID创建时,URI中显示指定_create,此时如果该ID的文档已经存在,操作失败

      GET 一个文档

      GET http://127.0.0.1:9200/IndexName/_doc/ID

      • 找到文档,返回Http 200
        • 文档元信息,同一个ID的文档,即使被删除,Version号也会不断增加
        • _source 中默认包含了文档的所有原始信息
      • 找不到文档,返回Http 404

      Index 文档

      PUT IndexName/_doc/1
      {
          "tags":["name","age","sex"]
      }
      

      Index和Create不一样的地方:如果文档存在,就索引新的文档。否则现有文档会被删除,新的文档被索引,版本信息(Version) + 1。

      Update 文档

      Update方法不会删除原来的文档,而是实现真正的数据更新,POST方法 ,Payload需要包含在doc中。

      POST IndexNmae/_update/1
      {
          "doc":{
              "albums":["aaa","bbb"]
          }
      }
      

      删除文档

      DELETE IndexName/_doc/ID

      Bulk API / 批量读取 mGet / 批量查询 msearch

      Bulk Api 支持在一次Api调用中,对不同的索引进行操作,支持四种类型操作,Index\Create\Update\Delete。

      可以在URI中指定Index,也可以在请求的Payload中进行,操作单挑操作失败,并不影响其他操作,返回结果包括了每一条操作执行的结果。

      //对同一个索引进行操作
      POST /IndexName/_doc/_bulk 
      //对不同的索引进行操作
      POST _bulk
      { "index" : { "_index" : "test", "_id" : "1" } }
      { "field1" : "value1" }
      { "delete" : { "_index" : "test", "_id" : "2" } }
      { "create" : { "_index" : "test2", "_id" : "3" } }
      { "field1" : "value3" }
      { "update" : {"_id" : "1", "_index" : "test"} }
      { "doc" : {"field2" : "value2"} }
      

      mGet批量操作,可以减少网络链接所产生的开销,提高性能。

      #URI中指定index
      GET /IndxName/_mget
      {
          "docs" : [
              {
                  "_id" : "1"
              },
              {
                  "_id" : "2"
              }
          ]
      }
      //对不同的索引进行操作
      GET /_mget
      {
          "docs" : [
              {
                  "_index" : "test",
                  "_id" : "1"
              },
              {
                  "_index" : "test",
                  "_id" : "2"
              }
          ]
      }
      

      批量查询 msearch

      // msearch 操作
      POST kibana_sample_data_ecommerce/_msearch
      {"query" : {"match_all" : {}},"size":1}
      {"index" : "kibana_sample_datajs_flights"}
      {"query" : {"match_all" : {}},"size":2}
      

      倒排索引

      倒排索引的核心组成

      • 倒排索引包含两个部分
        • 单词词典,记录所有文档的单词,记录单词到倒排列表的关联关系
          • 单词词典一般比较大,可以通过B+树或哈希拉链法实现,以满足高性能的插入和查询
        • 倒排列表,记录了单词对应的文档结合,由倒排索引组成
          • 倒排索引项
            • 文档ID
            • 词频TF - 该单词在文档中出现的次数,用于相关性评分
            • 位置,单词在文档中分词的位置,用于语句搜索
            • 偏移,记录单词的开始结束位置,实现高亮显示

      Es的倒排索引

      • Es的Json文档中的每个字段,都有自己的倒排索引
      • 可以指定对某些字段不做索引
        • 优点:节省存储空间
        • 缺点:字段无法被搜索

      Analysis 与 Analyzer

      • Analysis,文本分析是把全文本转换成一系列单词(term / token)的过程,也叫分词。
      • Analysis 是通过 Analyzer 来实现的,可使用elasticsearch内置的分析器 / 或者按需定制化分析器。
      • 除了在数据写入时转换词条,匹配Query语句时候也需要用相同的分析器对查询进行查询语句进行分析。

      Analyzer的组成

      • 分词器是专门处理分词的组件,Analyzer由三部分组成:
        • ① 针对原始文本处理,例如去除html
        • ② 按照规则切分单词
        • ③ 将切分的单词进行加工,小写,删除stopworlds,增加同义词

      Search Api

      • URI Search ,在URL中使用查询参数
      • Request Body Search ,使用es提供的,基于Json格式的更加完备的Query Domain Specific Language(DSL)

      1.指定查询的索引

      集群上所有的索引:

      GET /_search //集群上所有的索引
      GET /Index1/_search  //index1
      GET /Index1,Index2/_search  //index1和index2
      GET /index*/_search  //以index开头的索引
      

      2.URI查询

      • 使用"q",指定字符串查询
      • "query string syntax",KV键值对

      用q表示查询内容,搜索叫做stark的客户GET /IndexName/_search?q=keyName:stark

      3.Request Body

      Request Body 支持 POST/GET两种方法,-H代表的是header参数 -d 代表的是body的请求参数。

      curl -XGET "http://127.0.0.1:9200/IndexName/_search"
      -H 'Content-Type:application/json' 
      -d
      '
      {
       "query":{
           "match_all":{}
       }    
      }
      '
      

      4.搜索Response

      搜索Response有几个关键的描述需要在这里解释一下:

      • took: 花费的时间
      • total: 符合条件的总文档数
      • hits:结果集,默认前10个文档
      • _index:索引名
      • _id:文档的ID
      • _score: 相关度评分
      • _source:文档原始信息

      URI Search详解

      指定字段查询 Vs 泛查询

      q是关键字,df是指定字段,泛查询就是查询所有字段中包含关键字的结果

      //指定字段
      GET /IndexName/_search?q=2020&df=title
      GET /IndexName/_search?q=title:2020
      {
          "profile":"true"
      }
      //泛查询
      GET /IndexName/_search?q=2020
      {
          "profile":"true"
      }
      

      Term Vs Phrase

      Hello World 等效于 Hello Or World

      "Hello World",等效于Hello AND World 。Phrase查询,还要求前后顺序保持一致

      分组和引号

      • title:(Hello AND World)
      • title = "Hello World"
      //分组,Bool查询
      GET /IndexName/_search?q=title:(Hello World)
      {
          "profile":"true"
      }
      //泛查询
      GET /IndexName/_search?q=title:Hello World
      {
          "profile":"true"
      }
      

      布尔操作 、分组

      • 布尔操作
        • AND / OR / NOT 或者 && / || / !
          • 必须大写
          • title:(Hello NOT World)
      • 分组
          • 表示 must
          • 表示 must_not
        • title:(+Hello -World)
      //检索title里有Hello ,没有World的词条
      GET /IndexName/_search?q=title:(Hello NOT World)
      {
          "profilejs":"true"
      }
      //检索title里必须有Hello ,必须没有World的词条
      GET /IndexName/_search?q=title:(+Hello -World)
      {
          "profile":"true"
      }
      

      范围查询 、算术符号

      URI Search支持范围查询和算术符号查询。

      • 范围查询
        • 区间表示:[]闭区间,{}开区间
        • year:{2019 TO 2020}
        • year:[* TO 2020]
      • 算数符号
      GET /IndexName/_search?q=year:>2020
      {
          "profile":"true"
      }
      

      通配符查询 、正则表达式 、模糊匹配与近似查询

      通配符查询 、正则表达式 、模糊匹配与近似查询效率低,占用内存大,不建议使用,这部分大家有个了解就好。

      以上就是搜索一文入门ElasticSearch(节点 分片 CRUD 倒排索引 分词)的详细内容,更多关于ElasticSearch搜索入门的资料请关注我们其它相关文章!

      0

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      关注公众号