美文网首页
Elasticsearch入门

Elasticsearch入门

作者: 王小板爱吃鱼 | 来源:发表于2021-06-01 16:37 被阅读0次
    基本概念:索引、文档和RESTAPI
    • 基本概念
      索引:名词:一类相似文档的集合,类比与mysql的一张表 动词:把数据保存到es的过程
      文档:json格式,类比于mysql的一条记录,每个文档有一个Unique ID,可以自己指定也可以由es生成

    • 文档的元数据(用于标注文档的相关信息)

    {
      "_index": "movies", // 文档所属的索引名
      "_type": "_doc", // 文档所属类型名,es7.0后已无意义,用_doc占位
      "_id": "1",  // 文档唯一ID
      "_score": 14.56256,  // 相关性打分
      "_version": 2,  // 文档的版本信息
      "_source": {  // 文档原始json数据
          "user_id": 9527,
          "username": "阿凯"
      }
    }
    
    • 索引的mapping和setting
      mapping定义文档字段的类型,类比于mysql的表结构
      setting定义不同数据的分布,定义索引分布的分片信息

    • 使用场景
      es: 相关性/高性能全文检索
      关系型数据库:事务性/Join
      有时候需要把es和关系型数据库结合使用

    集群、节点、分片和副本
    • 集群
      es集群是分布式的,节点结合负载均衡与数据的水平拆分

    • 节点
      节点是一个es实例(本质是一个java进程,建议生产环境一台机器只运行一个es实例,不要多个)
      data node: 保存数据的节点,当存储不够用时,可以增加data node进行扩容
      coordinating node:负责接收client的请求,分发到合适的节点并汇总结果,每个节点默认都起到coordinating node的职责
      hot&warm node:不同硬件配置的data node,实现冷热架构,降低机器成本
      machine learning node:负责跑机器学习的job,用来做异常检测
      生产环境应尽量配置单一职责的节点,通过elasticsearch.yml文件配置

    • 分片及副本

    主分片:用于解决数据水平扩展,可以将数据分布到不同节点上,主分片数在索引创建时指定,后续不允许修改,除非reindex,类比于mysql的分表
    副本:主分片的拷贝,用于解决高可用,即负载均衡

    分片数过小,后续无法增加节点扩展,分片数过大,影响结果的相关性打分,影响准备性,单个节点分片过多也会造成资源浪费,影响性能。7.0的默认主分片是1。

    文档的CURD和批量操作
    • create 创建一个文档,如果对应id的文档已存在,会报错
    PUT users/_create/1  // 索引名/_create/_id
    {
        "user_id": 1,
        "username": "jack"
    }
    
    • get 获取一个文档
    GET users/_doc/1  // 索引名/_type/_id
    
    • index 索引一个文档,如果对应id的文档不存在,则创建文档,如果已存在,则删除原文档再创建文档,版本号+1
    PUT users/_doc/1  // 索引名/_type/_id
    {
        "user_id": 1,
        "username": "jack"
    }
    
    • update 更新一个文档
    POST users/_update/1
    {
        "doc": {
             "username": "jack"
        }
    }
    
    • delete 删除一个文档
    DELETE users/_doc/1  // 索引名/_type/_id
    
    • Bulk API 支持一次调用中,对不同索引进行写操作,支持index create update delete,单条失败不影响其他操作
    POST _bulk
    {"index": {"_index": "hb_user", "_id": 3}}
    {"user_id": 2, "username": "周月"}
    {"create": {"_index": "hb_user","_id": 4}}
    {"user_id": 9300,"username": "夸哥","salary": 50000}
    {"delete": {"_index": "hb_user","_id": 1}}
    {"update": {"_index": "hb_user","_id": 4}}
    {"doc": {"user_id": "9300","username": "阿夸"}}
    
    • mget 批量获取
    GET _mget
    {
      "docs": [
           {"_index": "hb_user", "_id": 3},
           {"_index": "hb_login_history", "_id": 4}
      ]
    }
    
    倒排索引

    以书本为例,书的目录就是正排索引,书最后的索引的词条就是倒排索引

    文档中 正排索引是文档ID到文档内容,倒排索引是文档内容中的词条到文档ID

    倒排索引包含两个部分:
    单词词典:记录文档中的所有单词,单词到倒排列表的对应关系
    倒排列表:由倒排索引项组成:文档ID,词频,位置,偏移

    例子:

    单词词典

    字段 倒排列表id
    超人 1,2,3
    蝙蝠侠 4,5

    倒排列表

    倒排列表id 文档ID 词频TF 位置 偏移
    1 52562 1 1 <10,23>
    2 542562 2 1 <11,23>
    3 542562 1 1 <12,23>
    4 542562 1 1 <13,23>
    5 542562 1 1 <14,23>

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

    通过Analyzer进行分词

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

    Analyzer由三部分组成:

    • Character Filter 针对原始文本进行处理,es自带的:去除html标签,字符串替换,正则匹配替换,会影响tokenizer的position和offset信息
    • Tokenizer 按照规则切分为单词
    • Token Filter 将切分的单词进行加工,小写,删除stopwords,增加同义词

    ik分析器安装:
    bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.1.0/elasticsearch-analysis-ik-7.1.0.zip

    kibana 演示:

    POST _analyze
    {
      "analyzer": "ik_smart",
      "text": "中华人民共和国国歌"
    }
    
    POST _analyze
    {
      "analyzer": "ik_max_word",
      "text": "中华人民共和国国歌"
    }
    
    • ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;

    • ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询

    Search API

    • URI Search : 在URI中使用查询参数
    • Request Body Search: DSL

    指定查询的索引:

    • /index1/_search
    • /index1,index2/_search
    • /index*/_search

    URI查询示例:

    curl -XGET "http://xxxxxxxxxx/index1/_search?q=customer_first_name:Eddie"
    

    DSL查询示例

    curl -XGET "http://xxxxxxxxxx/index1/_search" -H 'Content-Type:application/json' -d'
    {
      "query": {
          "match_all": {}
      }
    }'
    

    相关性指标

    • Percision(查准率):正确的内容/全部返回的结果,尽可能返回较少的无关文档
    • Recall(查全率):正确的内容/全部应该返回的结果,尽量返回较多的相关文档
    • Ranking 是否能按照相关度进行排序

    es提供很多参数来改善Percision和Recall

    URI Search

    GET /movies/_search?q=2012&df=title&sort=year:desc&from=0&size=10&timeout=1s
    {
        "profile": "true"
    }
    
    • q指定查询语句,使用query string syntax
    • df默认字段,不指定时,会对所有字段进行查询
    • sort排序/from和size用于分页
    • profile可以查询时如何被执行的
    • 指定字段查询
    GET /movies/_search?q=title:2012
    
    GET /movies/_search?q=2012&df=title
    
    • 泛查询,对所有字段查询,性能不好
    GET /movies/_search?q=2012
    
    • Term和Phrase

    • Beautiful Mind 等效于 Beautiful OR Mind

    • ”Beautiful Mind“ 等效于 Beautiful AND Mind。Phrase查询,还要求前后顺序保持一致

    • 分组和引号

    title:(Beautiful Mind) 默认含义Beautiful OR Mind
    title:"Beautiful Mind"等同于title:(Beautiful AND Mind)

    title:(Beautiful NOT Mind)
    这里分组中的OR AND NOT等同于 && || !
    也可以用+ -来实现,+表示must, - 表示must not
    title:(+Beautiful -Mind)

    • 范围查询, []闭区间,{}开区间
      year:{2019 TO 2018}
      year:[* TO 2018]

    • 算数符号
      year:>2010
      year:(>2010 && <=2018)
      year:(+>2010 && +<=2018)

    • 通配符查询(查询效率低,占用内存大,不建议使用。特别是放在最前面)
      ?代表1个字符,代表0或者多个字符:title:mi?d title:be

    • 正则表达
      title:[bt]oy

    • 模糊匹配与近似匹配
      title:beautifl~1
      title:"lord rings"~2

    Request Body Search

    一些复杂的查询只能通过DSL实现,推荐使用DSL

    POST /movies/_search
    {
        "_source":  ["order_date", "category.keyword"],
        "sort": [{"order_date": "desc"}],
        "from": 10,
        "size": 20,
        "query": {
            "match_all": {}
        }
    }
    
    • 获取靠后的翻页成本较高
    • 最好在数字型与日期型的字段上排序
    • 如果_source没有存储,那就只返回匹配的文档的元数据
    • _source支持通配符,"name*"

    脚本字段

    GET /movies/_search
    {
        "script_fields":  {
            "dollor_price": {
                "script": {
                    "lang": "painless",
                    "source": "doc['order_date'].value+'hello'"
                }
            }
        }
        "from": 10,
        "size": 20,
        "query": {
            "match_all": {}
        }
    }
    

    DSL实现Term Query和Phrase Query

    GET /movies/_search
    {
        "query": {
          "match": {
            "comment": "Last Christmas" // Last OR Christmas
          }
        }
    }
    
    GET /movies/_search
    {
        "query": {
          "match": {
            "comment": {
                "query": "Last Christmas",
                "operator": "AND"
            }
          }
        }
    }
    
    GET /movies/_search
    {
        "query": {
          "match_phrase": {
            "comment": {
                "query": "Last Christmas",  // 在match_phrase查询里,每个词必须是按顺序出现的
                "slop": 1
            }
          }
        }
    }
    

    query string&simple query string查询

    POST users/_search
    {
      "query": {
        "query_string": {
          "default_field": "name",
          "query": "Ruan AND Yiming"
        }
      }
    }
    
    POST users/_search
    {
      "query": {
        "query_string": {
          "fields": ["name", "about"],
          "query": "(Ruan AND Yiming) OR (Java AND Elasticsearch)"
        }
      }
    }
    
    POST users/_search
    {
      "query": {
        "simple_query_string": {
          "fields": ["name", "about"],
          "query": "Ruan Yiming",
          "default_operator": "AND"
        }
      }
    }
    
    • simple_query_string不支持AND OR NO,会当作字符串处理,支持(+替代AND,代替OR, -代替NOT)Term之前的关系默认是OR,可以指定operator

    Dynamic Mapping和常见字段类型

    mapping类似数据库中的schema(表结构),作用如下:
    • 定义索引中字段的名称
    • 定义字段的数据类型,例如字符串,数字,布尔......
    • 字段,倒排索引的相关配置(Analyzed or Not Analyzed, Analyzer)
    字段的数据类型
    • 简单类型:Text/Keyword Date Integer/Floating Boolean IPv4&IPv6
    • 复杂类型:对象类型/嵌套类型
    • 特殊类型(地理位置):geo_point & geo_shape / percolator

    Dynamic Mapping:es根据文档信息,自动推断字段的类型,但可能不是最正确的

    json类型 es类型
    字符串 1. 匹配日期格式,设置为Date 2. 配置数字设置为float或者long,该选项默认关闭 3. 设置为Text,并且增加keyword子字段
    布尔值 boolean
    浮点数 float
    整数 long
    对象 object
    数组 由第一个非空数值的类型所决定
    空值 忽略
    更改mapping的字段类型
    • 新增字段
    1. Dynamic设为true时,一旦有新增字段的文档写入,mapping也同时被更新
    2. Dynamic设为false时, mapping不会被更新,新增字段的数据无法被索引,但是信息会出现在_source中
    3. Dynamic设为strict时,文档写入失败
    • 已有字段
      一旦已经有数据写入,就不再支持修改字段定义,如果要修改,必须调用Reindex API,重建索引。
    PUT /hb_user/_mapping
    {
      "dynamic": false
    }
    
    GET /hb_user/_mapping
    

    显式mapping设置和常见参数

    PUT my_index
    {
      "mappings": {
        "properties": {
          "first_name": {
            "type": "text",
            "copy_to": "full_name"  // 可以用full_name进行搜索,但是full_name不会出现在_source中
          },
          "last_name": {
            "type": "text",
            "copy_to": "full_name"
          },
          "mobile": {
            "type": "text",
            "index": false
          },
          "bio": {
            "type": "text",
            "index_options": "offsets"
          },
          "alias": {  // 需要对null值进行搜索,只有keyword类型支持null_value
            "type": "keyword",
            "null_value": "NULL"
          },
          "interests": {
            "type": "text"
          }
        }
      }
    }
    

    四种不同级别的Index Option配置,可以控制倒排索引记录的内容

    • docs:记录doc id
    • freqs: 记录doc id / term frequencies
    • position: 记录doc id / term frequencies/ term position
    • offsets: 记录doc id / term frequencies / term position / character offects

    Text类型默认记录positions,其他默认为docs
    记录内容越多,占用存储空间越大

    多字段特性及Mapping中配置自定义Analyzer

    多字段特性
    PUT products
    {
      "mappings": {
        "properties": {
          "company": {
            "type": "text",
            "fields": {
              "company_keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "comment": {
            "type": "text",
            "fields": {
              "english_comment": {
                "type": "text",
                "analyzer": "english",
                "search_analyzer": "english"
              }
            }
          }
        }
      }
    }
    

    Exact Value:无需分词,包括数字/日期/具体一个字符串,es中的keyword
    Full Text:全文本,需要分词,es中的text

    配置自定义Analyzer
    GET _analyze
    {
      "tokenizer": "whitespace",
      "filter": ["lowercase", "stop"],
      "text": ["The gilrs in China are playing this game!"]
    }
    
    PUT my_index1
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_custom_analyzer": {
              "type": "custom",
              "char_filter": [
                "emotions"
              ],
              "tokenizer": "punctuation",
              "filter": [
                "lowercase",
                "english_stop"
              ]
            }
          },
          "char_filter": {
            "emotions":{
              "type": "mapping",
              "mappings": [
                ":) => _happy_",
                "(: => _sad_"
              ]
            }
          },
          "tokenizer":{
            "punctuation":{
              "type":"pattern",
              "pattern": "[ .,!?]"
            }
          },
          "filter":{
            "english_stop":{
              "type":"stop",
              "stopwords":"_english_"
            }
          }
        }
      }
    }
    
    GET my_index1/_analyze
    {
      "analyzer": "my_custom_analyzer",
      "text": "I`m a :) person,and you?"
    }
    

    Index Template和Dynamic Template

    什么是Index Template

    Index Template帮你设置mappings和settings,并按照一定规则,自动匹配到新创建的索引之上

    • 修改模板不会影响已创建的索引
    • 你可以创建多个索引模板,这些设置会被”merge“在一起
    • 你可以指定”order“的数值,控制”merge“过程
    PUT _template/template_default
    {
      "index_patterns": ["test*"],
      "order": 0,
      "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 2
      },
      "mappings": {
        "date_detection": false,
        "numeric_detection": true
      }
    }
    

    当一个索引被新创建时

    • 应用es默认的settings和mappings
    • 应用order数值低的Index Template中的设定
    • 应用order数值高的Index Template中的设定,之前的设定会被覆盖
    • 应用创建索引时,用户所指定的settings和mappings,并覆盖之前的设定

    查看index template

    GET _template/template_default
    
    什么是Dynamic Template

    根据es识别的数据类型,结合字段名称,来动态设定字段类型,比如:

    • 所有的字符串类型都设定成keyword,或者关闭keyword字段
    • is开头的字段都设置成boolean
    • long_开头的字段都设定成long类型

    目的:让es的动态字段类型推断符合你的预期

    PUT test_index2
    {
      "mappings": {
        "dynamic_templates":[
          {
            "full_name":{
              "path_match": "name.*",
              "path_unmatch": "*.middle",
              "mapping":{
                "type":"text",
                "copy_to":"full_name"
              }
            }
          },
          {
            "string_as_boolean": {
              "match_mapping_type": "string",
              "match": "is*",
              "mapping": {
                "type": "boolean"
              }
            }
          }
        ]
      }
    }
    
    PUT test_index2/_doc/1
    {
      "name":{
        "first":"chen",
        "middle":"liang",
        "last":"hui"
      },
      "is_vip":"true"
    }
    
    GET test_index2/_search?q=full_name:(chen)
    

    es的聚合查询简介

    • Bucket Aggregation 一些满足特定条件的文档的集合 类似sql中 group by
    • Metric Aggregation 一些数学运算,可以对文档字段进行统计分析,如sql中的 select count(*)
    • Pipeline Aggregation 对其它聚合查询进行二次聚合
    • Matrix Aggregation 支持对多个字段的操作并提供一个结果矩阵
    GET hb_user/_search
    {
      "size": 0,
      "aggs": {
        "gender_group": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "avg_birth_year": {
              "avg": {
                "field": "birth_year"
              }
            },
            "max_birth_year": {
              "max": {
                "field": "birth_year"
              }
            },
            "min_birth_year": {
              "min": {
                "field": "birth_year"
              }
            },
            "birth_month_group":{
              "terms": {
                "field": "birth_month"
              }
            }
          }
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:Elasticsearch入门

          本文链接:https://www.haomeiwen.com/subject/giusdltx.html