ES基础学习二

学习地址为极客时间《Elasticsearch核心技术与实战》,这只是我做的笔记,仅供参考;

三、Elasticsearch入门

1. Elasticsearch基本概念

1.1 文档

  • Elasticsearch是面向文档的,<font size = 3 color = red>文档是所有可搜索数据的最小单位</font>
    • 日志文件中的日志项
    • 一本电影的具体信息/一张唱片的详细信息
    • MP3播放器里的一首歌/一篇PDF文档中的具体内容
  • 文档会被序列化成Json格式,保存在Elasticsearch
    • Json对象由字段组成
    • 每个字段都有对应的字段类型(字符串/数值/布尔/日期/二进制/范围类型)
  • 每个文档都有一个UniqueID
    • 你可以自己指定ID
    • 或者通过Elasticsearch自动生成

1.1.1 Json文档

  • 一篇文档包含了一系列的字段。类似数据库表中一条记录
  • Json文档,格式灵活,不需要预先定义格式
    • 字段的类型可以指定或者通过Elasticsearch自动推算
    • 支持数据/支持嵌套

1.1.2 文档元数据

{
    "index" : "movies",
    "_type" : "_doc",
    "_id" : "1",
    "_score" : 14.69302,
    "_source" : {
        "year" : 1995,
        "@version" : "1",
        "genre" : [
            "Adventure",
            "Animation",
            "Children",
            "Comedy",
            "Fantasy"
        ],
        "id" : "1",
        "title" : "Toy Story"
    }
},
  • 元数据,用于标注文档的相关信息
    • _index: 文档所属的索引名
    • _type: 文档所属的类型名
    • _id: 文档唯一ID
    • _source: 文档的原始JSON数据
    • _all: 整合所有字段内容到该字段,已被废除
    • _version: 文档的版本信息
    • _score: 相关性打分

1.2 索引

{
  "movies" : {
    "settings" : {
      "index" : {
        "creation_date" : "1604218204918",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "F9-uy1bUTemm1Hs_LaDMQQ",
        "version" : {
          "created" : "7010099"
        },
        "provided_name" : "movies"
      }
    }
  }
}
  • index: 索引是文档的容器,是一类文档的结合
    • index体现了逻辑空间的概念:每个索引都有自己的Mapping定义,用于定义包含文档的字段名和字段类型
    • Shard体现了物理空间的概念:索引中的数据分散在Shard
  • 索引的MappingSetting
    • Mapping定义文档字段的类型
    • Setting定义不同的数据分布

1.2.1 索引的不同语义

image
  • 名词:一个Elasticsearch集群中,可以创建很多不同的索引
  • 动词:保存一个文档到Elasticsearch的过程也叫索引(indexing)
    • ES中,创建一个倒排索引的过程
  • 名词:一个B树索引,一个倒排索引

1.2.2 Type(这个我也不知道是干什么的)

image

1.2.3 ESRDBMS对比

RDBMS Elasticsearch
Table index(Type)
Row Document
Column Filed
Schema Mapping
SQL DSL
  • 传统关系型数据库和Elasticsearch的区别
    • Elasticsearch
      • Schemaless:数据组织更加灵活
      • 相关性:算相关度
      • 高性能全文检索
    • RDBMS
      • 事务
      • Join

1.3 REST API

image

1.4 kibana上索引管理

image

image
//查看索引相关信息
GET movies

//查看索引的文档总数
GET movies/_count

//查看前10条文档,了解文档格式
POST movies/_search{
  
}

//_cat indices API
//查看indices
GET /_cat/indices/movies*?v&s=index

//查看状态未绿的索引
GET /_cat/indices?v&health=green

//按照文档个数排序
GET /_cat/indices?v&s=docs.count:desc

//查看具体的字段
GET /_cat/indices/movies*?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

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

1.5.1 高可用

  • 服务可用性-运行有节点停止服务
  • 数据可用性-部分节点丢失,不会丢失数据

1.5.2 可扩展性

  • 请求量提升/数据的不断增长(将数据分布到所有节点上)

1.6 ES的分布式特性

1.6.1 ES的分布式架构的好处

  • 存储的水平扩容
  • 提高系统的可用性,部分节点停止服务,整个集群的服务不受影响

1.6.2 ES的分布式架构

  • 不同的集群通过不同的名字来区分,默认名字elasticsearch
  • 通过配置文件修改,或者在命令行中 -E cluster.name=node1进行设定
  • 一个集群可以有一个或者多个节点

1.7 ES节点

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

1.8 Master-eligible nodesMaster Node

  • 每个节点启动后,默认就是一个Master eligible节点
    • 可以设置 node.master:false禁止
  • Master-eligible节点可以参加选主流程,成为Master节点
  • 当第一个节点启动时候,它会将自己选举成Master节点
  • 每个节点上都保存了集群的状态,只有Master节点才能修改集群的状态信息
    • 集群状态(Cluster State),维护了一个集群中,必要的信息
      • 所有的节点信息
      • 所有的索引和其相关的MappingSetting信息
      • 分片的路由信息
    • 任意节点都能修改信息会导致数据的不一致性

1.8 Data Node & Coordinating Node

  • Data Node
    • 可以保存数据的节点,叫做Data Node。负责保存分片数据。在数据扩展上起到了至关重要的作用
  • Coordinating Node
    • 负责接受Client的请求,将请求分发到合适的节点,最终把结果汇集到一起
    • 每个节点默认都起到了Coordinating Node的职责

1.9 其他节点类型

  • HotWarm Node
    • 不同硬件配置的 Data Node,用来实现 HotWarm架构,降低集群部署的成本
  • Machine Learing Node
    • 负责跑机器学习的 Job,用来做异常检测
  • Tribe Node
    • (5.3开始使用Cross Cluster Serarch)Tribe Node 连接到不同的Elasticsearch集群,并且支持将这些集群当成一个单独的集群处理

1.10 配置节点类型

  • 开发环境中一个节点可以承担多种角色
  • 生产环境中,应该设置单一的角色的节点(dedicated node)
节点类型 配置参数 默认值
master eligible node.master true
data node.data true
ingest node.ingest true
coordinating only 每个节点默认都是 coordinating 节点。设置其他类型全部为false
machine learing node.ml true(需 enable x-pack)

1.11 分片(Primary Shard & Replica Shard)

  • 主分片,用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上
    • 一个分片是一个运行的Lucene的实例
    • 主分片数在索引创建时指定,后续不允许修改,除非Reindex
  • 副本,用以解决数据高可用的问题。分片时主分片的拷贝
    • 副本分片数,可以动态的调整
    • 增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐)
  • 一个三节点的集群中,blogs索引的分片分布情况
    • 思考:增加一个节点或改大主分片数对系统的影响?


      image

1.12 分片的设定(主分片是在创建时设定的,后期不能改,除非reindex

  • 对与生产环境中分片的设定,需要提前做好容量规划
    • 分片数设置过小
      • 导致后续无法增加节点实现水平扩展
      • 单个分片的数据量太大,导致数据重新分配耗时(数据倾斜)
    • 分片数设置过大,7.0 开始,默认主分片设置成1,解决了over-sharding的问题
      • 影响搜索结果的相关性打分,影响统计结果的准确性
      • 单个节点上过多的分片,会导致资源浪费,同时也会影响性能

1.13 查看集群的健康状况

GET _cluster/health
image

image
  • Green:主分片与副本都正常分配
  • Yellow:主分片全部正常分配,有副本分片未能正常分配
  • Red:有主分片未能分配
    • 例如:当服务器的磁盘容量超过85%时,去创建了一个新的索引

2. 文档的基本CRUD与批量操作

2.1 文档的CRUD

类型 API
Index PUT my_index/_doc/1
{"user":"mike","comment":"xxxx"}
Create PUT my_index/_create/1
{"user":"mike","comment":"xxxx"}
POST my_index/_doc(不指定ID,自动生成)
{"user":"mike","comment":"xxxx"}
Read GET my_index/_doc/1
Update POST my_index/_update/1
{"doc":{"user":"mike","comment":"xxxx"}}
Delete DELETE my_index/_doc/1
  • Type名,约定都用_doc
  • Create:如果ID已经存在,会失败
  • Index:如果ID不存在,创建新的文档。否则,先删除现有的文档,再创建新的文档,版本会增加
  • Update:文档必须已经存在,更新只会对相应字段做增量修改

2.1.1 Create一个文档

image
  • 支持自动生成文档Id和指定文档Id两种方式
  • 通过调用post users/_doc
    • 系统会自动生成document Id
  • 使用HTTP PUT user/_create/1创建时,URI中显示指定_create,此时如果该id的文档已经存在,操作失败
    image

    image
//create document. 自动生成 _id
POST users/_doc
{
  "user" : "Mike",
    "post_date" : "2020-11-15T19:38:42",
    "message" : "trying out Kibana"
}
//create document. 指定Id。如果id已经存在,报错
PUT users/_doc/1?op_type=create
{
  "user" : "Mike",
    "post_date" : "2020-11-15T19:38:42",
    "message" : "trying out Elasticsearch"
}

2.1.2 Get一个文档

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

    image
//Get document by Id
GET users/_doc/1

2.1.3 Index文档

//Index,如果文档已经存在,就会删除旧文档,写入新文档,版本号会+1
PUT users/_doc/1
{
  "user" : "Mike"
}
  • IndexCreate不一样的地方:如果文档不存在,就索引新的文档。否则现有文档会被删除,新的文档被索引。版本信息+1
    image

    image

    image

    image

2.1.4 Update文档

  • Update方法不会删除原来的文档,而是实现真正的数据更新
  • Post方法 /Payload 需要包含再doc
    image

    image

    image
//Update,在原文档的基础上增加字段
POST users/_update/1/
{
  "doc":{
    "post_date" : "2020-11-15T19:59:42",
    "message" : "trying out Elasticsearch"
  }
}

2.2 批量操作

2.2.1 Bulk API

image
  • 在一次REST请求中,<font size = 3 color = red>重新建立网络连接是非常损耗性能的</font>
  • 支持在一次API调用中,对不同的索引进行操作
  • 支持四种类型操作
    • Index
    • Create
    • Update
    • Delete
  • 可以在URI中指定Index,也可以在请求的Payload中进行
  • <font size = 3 color = red>操作中单挑操作失败,并不会影响其他操作</font>
  • 返回结果包含了每一条操作执行的结果


    image
//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"}}

2.2.2 批量读取-mget

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


    image

    image
// mget 操作
GET /_mget
{
  "docs":[
      {
        "_index":"test",
        "_id":"1"
      },
      {
        "_index":"test",
        "_id":"2"
      }
    ]
}

2.2.3 批量查询-msearch

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

2.2.4 常见错误返回

问题 原因
无法连接 网络故障或集群挂了
连接无法关闭 网路故障或节点出错
429 集群过于繁忙
4xx 请求体格式有错
500 集群内部错误

3. 正排与倒排索引

3.1 正排

image

3.2 倒排索引

如果你想找某个词,在书中的具体页码,那正排就不能满足了,那我们可以建一个内容->文档Id的一种索引结构,就可以满足我们的需求了

image

3.2.1 倒排索引的核心组成

倒排索引包含两部分

  • 单词词典(Term Dictionary),记录所有文档的单词,记录单词到倒排列表的关联关系
    • 单词词典一般比较大,可以通过B+树哈希拉链法实现,以满足高性能的插入和查找
  • 倒排序列(Posting List)记录了单词对应的文档结合,由倒排索引项组成
    • 倒排索引项(Posting)
      • 文档Id
      • 词频TF-该单词在文档中出现的次数,用于相关性评分
      • 位置(Position)-单词在文档中分词的位置。用于语句搜索(phrase query)
      • 偏移(Offset)-记录单词的开始结束位置,实现高亮显示

3.2.2 Elasticsearch的一个例子

image

3.2.3 Elasticsearch的倒排索引

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

4. 通过Analyzer进行分词

4.1 AnalysisAnalyzer

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

4.2 Analyzer的组成

  • 分词器时专门处理分词的组件,Analyzer由三部分组成
    • Character Filters(针对原始文本处理,例如去除html)
    • Tokenizer(按照规则切分为单词)
    • Token Filter(将切分的单词进行加工,小写,删除stopword,增加同义词)
image

5. Elasticsearch的内置分词器

  • Standard Analyzer:默认分词器,按词切分,小写处理
  • Simple Analyzer:按照非字母切分(符号被过滤),小写处理
  • Stop Analyzer:小写处理,停用词过滤(the,a,is)
  • Whitespace Analyzer:按照空格切分,不转小写
  • Keyword Analyzer:不分词,直接将输入当作输出
  • Patter Analyzer:正则表达式,默认\w+(非字符分割)
  • Language:提供了30多种常用语言的分词器
  • Customer Analyzer:自定义分词器

5.1 使用_analyzer API

5.1.1 直接指定Analyzer进行测试

image
# 直接指定Analyzer进行测试
GET _analyze
{
  "analyzer": "standard",
  "text":"Mastering Elasticsearch,elasticsearch in Action"
}

5.2.2 指定索引的字段进行测试

image
# 指定索引的字段进行测试
POST users/_analyze
{
  "field":"message",
  "text":"Mastering Elasticsearch"
}

5.2.3 自定义分词器进行测试

image
# 自定义分词器进行测试
POST _analyze
{
  "tokenizer": "standard",
  "filter": ["lowercase"],
  "text": "Mastering Elasticsearch"
}

5.2 Standard Analyzer分词器(<font size = 3 color = red>Elasticsearch的默认分词器</font>)

  • 默认分词器
  • 按词切分
  • 小写处理
image

image

5.3 Simple Analyzer

  • 按照非字母切分,非字母的都被去除
  • 小写处理


    image

    image
# Simple Analyzer
GET _analyze
{
  "analyzer": "simple",
  "text":"2 runing Quick brown-foxes leap over lazy dogs in the summer evening"
}

5.3 Whitespace Analyzer

  • 按照空格切分


    image

5.4 Stop Analyzer

  • 相比Simple Analyzer
  • 多了stop filter
    • 会把the、a、is等修饰性词语去掉
      image

5.5 Keyword Analyzer

  • 不分词,直接将输入当一个term输出
    image

    image
# Keyword Analyzer
GET _analyze
{
  "analyzer": "keyword",
  "text":"2 runing Quick brown-foxes leap over lazy dogs in the summer evening"
}

5.5 Pattern Analyzer

  • 通过正则表达式进行分词
  • 默认是\w+,非字符的符号进行分割
    image

    image
# Pattern Analyzer
GET _analyze
{
  "analyzer": "pattern",
  "text":"2 runing Quick brown-foxes leap over lazy dogs in the summer evening"
}

5.6 Language Analyzer

  • 对不同国家的语言进行分词


    image
# Language Analyzer
POST _analyze
{
  "analyzer": "english",
  "text":"2 runing Quick brown-foxes leap over lazy dogs in the summer evening"
}

5.7 中文分词的难点

  • 中文句子,切分成一个一个词(不是一个个字)
  • 英文中,单词有自然的空格作为分隔
  • 一句中文,在不同的上下文,有不同的理解
    • 这个苹果,不大好吃/这个苹果,不大,好吃!
  • 例子
    • 他说的确实在理/这事的确定不下来

5.8 ICU Analyzer

  • 需要安装plugin
    • Elasticsearch-plugin install analysis-icu
  • 提供了Unicode的支持,更好的支持亚洲语言
image

image

image
POST _analyze
{
  "analyzer": "icu_analyzer",
  "text":"他说的确实在理"
}

GET /movies/_search

5. Search API概述

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

5.1 指定查询的索引

语法 范围
/_search 集群上所有的索引(用_search来标明这是一个搜索的请求)
/index1/_search 指定索引的名称为index1
/index1,inde-2/_search 可以指定多个索引,index1和index-2
/index*/_search 以index开头的索引

5.2 URI查询

  • 使用"q",指定查询字符串
  • "query string syntax",KV键值对
curl -XGET "http://elasticsearch:9200/kibana_sample_data_ecommerce/_search?q=customer_first_name:Eddie"
image

5.3 Request Body查询

image

5.4 搜索的返回结果(Response)

image

5.5 相关性

5.5.1 搜索的相关性

  • 搜索时用户和搜索引擎的对话
  • 用户关心的时搜索结果的相关性
    • 是否可以找到所有相关的内容
    • 有多少相关的内容被返回了
    • 文档的打分是否合理
    • 结合业务需求,平衡结果排名

5.5.2 衡量相关性

  • Information Retrieval(计算机领域的一门学课)
    • Precision(查准率): 尽可能返回较少的无关文档
    • Recall(查全率):尽可能返回较多的相关文档
    • Ranking:是否能够按照相关度进行排序

5.5.3 Precision and Recall

image

5.6 URI Search:通过URI query实现搜索

GET /movies/_search?q=2012&df=title&sort=year:desc&from=o&size=10&timeout=1s
{
    "profile":true
}
  • q:指定查询语句,使用Query String Syntax(<font color = red size = 3>Query String Syntax</font>)
  • df:默认字段,不指定时,会对所有字段进行查询
  • Sort:排序/fromsize 用于分页
  • Profile:可以查看查询时如何被执行的

5.6.1 指定字段查询 VS 范查询

  • q=title:2012 / q=2012
image

image
image

image

image
# 指定字段查询 VS 范查询
# 指定字段查询
GET /movies/_search?q=2012&df=title
{
    "profile":true
}
# 范查询
GET /movies/_search?q=2012
{
    "profile":true
}

5.6.2 Term VS Phrase

  • Beautiful Mind等效于Beautiful OR Mind,意思是只要有一个包含,就会返回
  • "Beautiful Mind",等效于Beautiful AND MindPhrase查询(<font size = 3 color =red>注意:要使用Phrase查询,需要将内容用引号引起来</font>),还要求前后顺序保持一致;意思是这两个词都要包含
  • 分组与引号
    • title:(Beautiful AND Mind)分组
    • title:"Beautiful Mind"
image

image
image

image

image

image

image

image
# Term VS Phrase
# Phrase 精确查找
GET /movies/_search?q=title:"Beautiful Mind"
{
  "profile": "true"  
}

GET /movies/_search?q=title:Beautiful Mind
{
  "profile": "true"
}

# TermQuery 分组,Bool查询
GET /movies/_search?q=title:(Mind Beautiful)
{
  "profile": "true"
}

TermQuery需要用()括号来把要查找的词括起来代表一个分组,不然就会变成上面的那种情况,两个Term在一起的时候默认是or的关系
PhraseQuery就是需要包含所有词,且保证顺序不变

5.6.3 布尔操作和分组操作

  • AND/OR/NOT 或者 &&/||/!
    • 必须大写
    • title:(matrix NOT reloaded)
  • 分组
    • +表示must
    • -表示must_not
    • title:(+matrix -reloaded)
      image
image

image

image

image

image
# TermQuery 分组,Bool查询
GET /movies/_search?q=title:(Mind Beautiful)
{
  "profile": "true"
}

# AND
GET /movies/_search?q=title:(Mind AND Beautiful)
{
  "profile": "true"
}
# NOT
GET /movies/_search?q=title:(Beautiful NOT Mind)
{
  "profile": "true"
}

# +
GET /movies/_search?q=title:(Beautiful %2BMind)
{
  "profile": "true"
}

5.6.4 范围查询和算数符号

  • 范围查询
    • 区间表示:[]闭区间,{}开区间
      • year:{2019 TO 2018}
      • year:[* TO 2018]
  • 算数符号
    • year:>2010
    • year:(>2010 && <=2018)
    • year:(+>2010 +<=2018)
image
# 所有的电影年份必须>=1980
GET /movies/_search?q=year:>=1980
{
  "profile": "true"
}

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

  • 通配符查询(通配符查询效率低,占用内存大,不建议使用。特别是放在最前面)
    • ?代表 1 个字符,*代表 0 或多个字符
      • title:mi?d
      • title:be*
  • 正则表达式
    • title:[bt]oy
  • 模糊匹配与近似查询
    • title:befutifl~1
    • title:“lord rings”~2
image
# 通配符查询
GET /movies/_search?q=title:b*
{
  "profile": "true"
}

# 模糊匹配&近似匹配
GET /movies/_search?q=title:beautifl~1
{
  "profile": "true"
}

GET /movies/_search?q=title:"lord Ring"~2
{
  "profile": "true"
}

5.7 Request BodyQuery DSL简介

5.7.1 Request Body Search

  • 将查询语句通过HTTP Request Body发送给Elasticcsearch
  • Query DSL
    image

5.7.2 分页

  • From从0开始,默认返回10个结果
  • 获取靠后的翻页成本较高


    image

5.7.3 排序

  • 最好在"数字型"与"日期型"字段上排序
  • 因为对于多值类型或分析过的字段排序,系统会选一个值,无法得知该值


    image

    image
//对日期排序
POST kibana_sample_data_ecommerce/_search
{
  "profile": "true",
  "sort": [{"order_date": "desc"}],
  "query": {
    "match_all": {} 
  }
}

5.7.4 _source filtering

  • 如果_source没有存储,那就只返回匹配的文档的元数据
  • _source支持使用通配符:_source["name*,"desc"]
    image

    image
//source filstering
POST kibana_sample_data_ecommerce/_search
{
  "_source": ["order_date"],
  "query": {
    "match_all": {}
  }
}

5.7.5 脚本字段

  • 用例:订单中有不同的汇率,需要结合汇率对订单价格进行排序


    image
//脚本字段
GET kibana_sample_data_ecommerce/_search
{
  "script_fields": {
    "new_field": {
      "script": {
        "lang": "painless",
        "source": "doc['order_date'].value+'_hello'"
      }
    }
  },
  "query": {
    "match_all": {}
  }
}

5.7.6 使用查询表达式:Match Query(我们之前学了Term Query,Phrase Query)

image

image
//matchQuery OR
POST movies/_search
{
  "query": {
    "match": {
      "title": "last Christmas"
    }
  }
}
//matchQuery AND
POST movies/_search
{
  "query": {
    "match": {
      "title": {
        "query": "last Christmas",
        "operator": "and"
      }
    }
  }
}

5.7.7 短语搜索:Match Phrase查询

image

image
//matchPhrase
POST movies/_search
{
  "query": {
    "match_phrase": {
      "title": "one love"
    }
  }
}
//matchPhrase slop:1
POST movies/_search
{
  "query": {
    "match_phrase": {
      "title": {
        "query": "one love",
        "slop": 1
      }
    }
  }
}

5.8 <font size = 3 color = red>几种查询方式的总结</font>

image

image

5.9 Query StringSimple Query String查询

5.8.1 Query String Query

  • 类似URI Query
    image

    image

    image

5.8.1 Simple Query String Query

  • 类似Query String,但是会忽略错误的语法,同时只支持部分查询语法
  • 不支持AND、OR、NOT,会当作字符串处理
  • Term之间默认的关系是OR,可以指定Operator
  • 支持部分逻辑
    • +代替AND
    • |代替OR
    • -代替NOT
image

image

image
PUT /users/_doc/1
{
  "name":"Ruan Yiming",
  "about":"java,golang,node,swift,elasticsearch"
}

PUT /users/_doc/2
{
  "name":"Li Yiming",
  "about":"Hadoop"
}

# 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 (Hadoop)"
    }
  }
}

# Simple Query String 默认operator是 OR
POST users/_search
{
  "query": {
    "simple_query_string": {
      "query": "Ruan AND Yiming",
      "fields": ["name"]
    }
  }
}

POST users/_search
{
  "query": {
    "simple_query_string": {
      "query": "Ruan Yiming",
      "fields": ["name"],
      "default_operator": "AND"
    }
  }
}

5.10 <font color = red>es match、match_phrase、query_string和term的区别</font>

https://www.cnblogs.com/chenmz1995/p/10199147.html

6. Dynamic Mapping和常见字段类型

6.1 什么是Mapping

  • Mapping类似数据库中的schema的定义,作用如下
    • 定义索引中的字段的名称
    • 定义字段的数据类型,例如字符串,数字,布尔......
    • 字段,倒排索引的相关配置,(Analyzed or Not Analyzed,Analyzer)
  • Mapping会把Json文档映射成Lucene所需要的扁平格式
  • 一个Mapping属于一个索引的Type
    • 每个文档都属于一个Type
    • 一个Type有一个Mapping定义
    • 7.0开始,不需要在Mapping定义中指定type信息

6.2 Elasticsearch字段的数据类型

  • 简单类型
    • Text/Keyword
    • Date
    • Integer/Floating
    • Boolean
    • IPv4 & IPv6
  • 复杂类型:对象和嵌套对象
    • 对象类型/嵌套类型
  • 特殊类型
    • geo_point & geo_shape/percolator

6.3 什么是Dynamic Mapping

  • 在写入文档时,如果索引不存在,会自动创建索引
  • Dynamic Mapping的机制,使得我们无需手动定义Mappings,Elasticsearch会自动根据文档信息,推算出字段的类型
  • 但是有时候推算的不对,例如地理位置信息
  • 当类型如果设置不对时,会导致一些功能无法正常运行,例如Range查询
    image

6.4 类型的自动识别

JSON类型 Elasticsearch类型
字符串 匹配日期格式,设置成Date
配置数字设置为float或者long,该选项默认关闭
设置为Text,并且增加keyword子字段
布尔值 boolean
浮点数 float
整数 long
对象 Object
数组 由第一个非空数值的类型所决定
空值 忽略
image

image
//写入文档,查看Mapping
PUT mapping_test/_doc/1
{
  "firstName":"Chan",
  "lastName":"Jackie",
  "loginDate":"2018-07-24T10:29:48.103Z"
}

//查看Mapping
GET mapping_test/_mapping

//Delete index 删除索引
DELETE mapping_test

//dynamic mapping,推断字段的类型
PUT mapping_test/_doc/1
{
  "uid":"123",
  "isVip":false,
  "isAdmin":"true",
  "age":19,
  "heigh":180
}

#查看Mapping
GET mapping_test/_mapping

6.5 能否更改Mapping的字段类型

  • 两种情况
    • 新增字段
      • Dynamic设为true时,一旦有新增字段的文档写入,Mapping也同时被更新
      • Dynamic设为false,Mapping不会被更新,新增字段的数据无法被索引,但是信息会出现在_source
      • Dynamic设置成Strict,文档写入失败
    • 对已有字段,一旦一句有数据写入,就不再支持修改字段定义
      • Lucene实现的倒排索引,一旦生成后,就不允许修改
    • 如果希望改变字段类型,必须Reindex API,重建索引
  • 原因
    • 如果修改了字段的数据类型,会导致已被索引的属于无法被搜索
    • 但是如果是增加新的字段,就不会有这样的影响

6.6 控制Dynamic Mappings

image
"true" "false" "strict"
文档可索引 YES YES NO
字段可索引 YES NO NO
Mapping被更新 YES NO NO
  • dynamic被设置成false时候,存在新增字段的数据写入,该数据可以被索引,但是新增字段被丢弃
  • 当设置成Strict模式时候,数据写入直接出错
image

image

image

image

image

image

image

image
#默认Mapping支持dynamic,写入的文档中加入新的字段
PUT dynamic_mapping_test/_doc/1
{
  "newField":"someValue"
}

POST dynamic_mapping_test/_search
{
  "query": {
    "match": {
      "newField": "someValue"
    }
  }
}

#修改dynamic的值为false
PUT dynamic_mapping_test/_mapping
{
  "dynamic":false
}

#新增 anotherField字段,字段依旧可以存入ES
PUT dynamic_mapping_test/_doc/10
{
  "anotherField":"someValue"
}

#但是,该字段不可以被搜索,因为dynamic的值被我们设置为了false
POST dynamic_mapping_test/_search
{
  "query": {
    "match": {
      "anotherField": "anotherField"
    }
  }
}

#查看索引的Mapping文件
GET dynamic_mapping_test/_mapping

#修改dynamic的值为strict
PUT dynamic_mapping_test/_mapping
{
  "dynamic":"strict"
}

#写入数据出错,HTTP Code 400
PUT dynamic_mapping_test/_doc/12
{
  "lastField":"value"
}

7 显示Mapping设置与常见参数

7.1 如何显示定义一个Mapping

image

7.2 自定义Mapping的一些建议

  • 可以参考API手册,纯手写
  • 为了减少输入的工作量,减少出错概率,可以依照以下步骤
    • 创建一个临时的index,写入一些样本数据
    • 通过访问Mapping API获得该临时文件的动态Mapping定义
    • 修改后用,使用该配置创建你的索引
    • 删除临时索引

7.3 控制当前字段是否被索引

  • Index:控制当前字段是否被索引。默认为true。如果设置成false,该字段不可被搜索
    image

    image

    image
DELETE dynamic_mapping_test
#设置 index 为 false
DELETE users
PUT users
{
  "mappings": {
    "properties": {
      "firstName":{
        "type": "text"
      },
      "lastName":{
        "type": "text"
      },
      "mobile":{
        "type": "text",
        "index": false
      }
    }
  }
}

PUT users/_doc/1
{
  "firstName":"Ruan",
  "lastName":"Yiming",
  "mobile":"123456789"
}

POST /users/_search
{
  "query": {
    "match": {
      "mobile": "123456789"
    }
  }
}

7.3 index Options

  • 对于倒排索引的建立,es提供了四种不同级别的index Options配置,可以控制倒排索引记录的内容
    • docs:记录doc id
    • freqs:记录doc idterm frequencies
    • positions:记录doc id/term frequencies/term position
    • offsets:记录doc id/term frequencies/term position/character offects
  • Text类型默认记录postions,其他默认为docs
  • 记录内容越多,占用存储空间越大


    image

7.4 null_value

  • 需要对null值实现搜索
  • 只有keyword类型支持设定Null_Value
    image

    image
#设定Null_value
DELETE users
PUT users
{
    "mappings": {
    "properties": {
      "firstName":{
        "type": "text"
      },
      "lastName":{
        "type": "text"
      },
      "mobile":{
        "type": "keyword",
        "null_value": "NULL"
      }
    }
  }
}

PUT users/_doc/1
{
  "firstName":"Ruan",
  "lastName":"Yiming",
  "mobile":null
}

GET users/_search
{
  "query": {
    "match": {
      "mobile": "NULL"
    }
  }
}

7.5 copy_to设置

  • _all7中被copy_to所替代
  • 满足一些特定的搜索需求
  • copy_to将字段的数值拷贝到目标字段,实现类似_all的作用
  • copy_to的目标字段不出现在_source
    image

    image
#设置 Copy to
DELETE users
PUT users
{
  "mappings": {
    "properties": {
      "firstName":{
        "type": "text",
        "copy_to": "fullName"
      },
      "lastName":{
        "type": "text",
        "copy_to": "fullName"
      }
    }
  }
}

PUT users/_doc/1
{
  "firstName":"Ruan",
  "lastName":"Yiming"
}

GET users/_search
{
  "query": {
    "match": {
      "fullName": {
        "query": "Ruan Yiming",
        "operator": "and"
      }
    }
  }
}

当你索引一个文档的时候,它如果包含了firstNamelastName,我们都会把这个值拷贝到fullName字段上去,当你要查询时,就可以用fullName来查询了

7.6 数组类型

  • Elasticsearch中不提供专门的数组类型。但是任何字段,都可以包含多个相同类型的数值
    image

    image

    image
#数组类型
PUT users/_doc/1
{
  "name":"onebird",
  "interests":"reading"
}

PUT users/_doc/1
{
  "name":"twobirds",
  "interests":["reading","music"]
}

POST users/_search
{
  "query": {
    "match_all": {}
  }
}

GET users/_mapping

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

8.1 多字段类型

image
  • 多字段特性
    • 厂商名字实现精确匹配
      • 增加一个keyword的<font size = 3 color = red>子字段</font>
    • 使用不同的analyzer
      • 不同语言
      • pingyin字段的搜索
      • 还支持为搜索和索引指定不同的analyzer

8.2 Exact Values(精确值) VS Full Text(全文本)

  • Exact values vs Full Text
    • Exact Value:包括数字/日期/具体一个字符串(例如:"Apple Store")
      • Elasticsearch中的keyword
    • 全文本,非结构化的文本数据
      • Elasticsearch中的text
image

8.2.1 Exact Values不需要被分词(Exact Values和Full Text最大的区别)

  • Elasticsearch为每一个字段创建一个倒排索引
    • Exact Value在索引时,不需要做特殊的分词处理
image

8.3 自定义分词

  • Elasticsearch自带的分词器无法满足时,可以自定义分词器。通过组合不同的<font size = 3 color = red>组件</font>实现(下面这三个组件是Analyzer的组成,可看上面4.2)
    • Character Filter
    • Tokenizer
    • Token Filter

8.3.1 Character Filters

  • Tokenizer之前对文本进行处理,例如增加删除及替换字符。可以配置多个Character Filters。会影响Tokenizerpositionoffset信息
  • 一些自带的Character Filter
    • HTML strip: 去除html标签
    • Mapping: 字符串替换
    • Pattern replace: 正则匹配替换
image

image

image

POST _analyze
{
  "tokenizer": "keyword",
  "char_filter": ["html_strip"],
  "text": "<b>hello world</b>"
}

//使用 char filter进行替换(将'-'替换为'_')
POST _analyze
{
  "tokenizer": "standard",
  "char_filter": [
    {
      "type":"mapping",
      "mappings":["- => _"]
    }
  ],
  "text": "123-456,I-test! test-990 650-555-1234"
}

//char filter替换表情符号
POST _analyze
{
  "tokenizer": "standard",
  "char_filter": [
    {
      "type":"mapping",
      "mappings": [":) => happy",":( => sad"]
    }
  ],
  "text": ["I am felling :)","Felling :( today"]
}

//正则表达式
GET _analyze
{
  "tokenizer": "standard",
  "char_filter": [
    {
      "type": "pattern_replace",
      "pattern": "http://(.*)",
      "replacement": "$1"
    }
  ],
  "text": ["http://www.elastic.co"]
}

8.3.2 Tokenizer

  • 将原始的文本按照一定的规则,切分为词(term or token)
  • Elasticsearch内置的Tokenizers
    • whitespace/standard/uax_url_email/pattern/keyword/path hierarchy
  • 可以用java开发插件,实现自己的Tokenizer
image
# Tokenizer
POST _analyze
{
  "tokenizer": "path_hierarchy",
  "text": "/user/ymruan/a/b/c/d/e"
}

8.3.3 Token Filters

  • Tokenizer输出的单词(term),进行增加,修改,删除
  • 自带的Token Filters
    • Lowercase/stop/synonym(添加近义词)
image

image

image

image
# Token Filters

#whitespace与stop
#按照空格切分,且将一些特定词过滤,比如 on in the ,这些词称之为stop,但是这里的第一个大写的The不会被去除
GET _analyze
{
  "tokenizer": "whitespace",
  "filter": ["stop"],
  "text": ["The rain in Spain falls mainly on the plain."]
}

#加入 lowercase后,The被当成 stopword 删除
#先做了小写处理
GET _analyze
{
  "tokenizer": "whitespace",
  "filter": ["lowercase","stop"],
  "text": ["The girls in China are playing this game!"]
}

# 如何自定义一个 analyzer 去满足自己特定的需求
DELETE my_index
PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "typpe":"custom",
          "char_filter": [
            "emoticons"
          ],
          "tokenizer": "punctuation",
          "filter": [
            "lowercase",
            "english_stop"
          ]
        }
      },
      "tokenizer": {
        "punctuation":{
          "type": "pattern",
          "pattern": "[.,!?]"
        }
      },
      "char_filter": {
        "emoticons": {
          "type":"mapping",
          "mappings": [
            ":) => _happy_",
            ":( => _sad_"
          ]
        }
      },
      "filter": {
        "english_stop": {
          "type":"stop",
          "stopwords": "_english_"
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": "I'm a :) person,and you?"
}

9. Index TemplateDynamic Template

9.1 什么是Index Template

  • 随着时间的推移,你的集群上会有越来越多的索引,那比如说你的集群是用来做日志管理的,你会每天为这些日志生成一个新的索引,因为这样的方式可以让你的数据管理更加合理,另外集群会有一个更好的性能;
  • Index Template:帮助你设定MappingsSettings,并按照一定的规则,自动匹配到新创建的索引之上
    • 模板仅在一个索引被创建时,才会产生作用。修改模板不会影响已创建的索引
    • 你可以设定多个索引模板,这些设置会被merge在一起
    • 你可以指定order的数值,控制merging的过程
      image

9.1.1 Index Template的工作方式

  • 当一个索引被创建时
    • 应用Elasticsearch默认的settingsmappings
    • 应用order数值低的Index Template中的设定
    • 应用order高的Index Template中的设定,之前的设定会被覆盖
    • 应用创建索引时,用户指定的SettingsMappings,并覆盖之前模板中的设定

9.1.2 Demo

  • 创建2个Index Template
  • 查看根据名字查看Template
  • 查看所有templates,_tmplate/*
  • 创建一个临时索引,查看replica和数据类型推断
  • 将所有名字设为能与Index Template匹配时,查看所生成的IndexMappingsSettings
image

image

image

image

image

image

image

image
# 创建一个模板
PUT _template/template_default
{
  "index_patterns": ["*"],
  "order" : 0,
  "version" : 1,
  "settings" : {
    "number_of_shards" : 1,
    "number_of_replicas" : 1
  }
}
# 创建第二个模板
PUT /_template/template_test
{
  "index_patterns": ["test*"],
  "order" : 1,
  "settings" : {
    "number_of_shards" : 1,
    "number_of_replicas" : 2
  },
  "mappings" : {
    "date_detection" : false,
    "numeric_detection" : true 
  }
}

# 查看template信息
GET /_template/template_default
GET /_template/temp*

# 写入新的数据,index以test开头
PUT testtemplate/_doc/1
{
  "someNumber" : "1",
  "someDate" : "2020/12/05"
}
GET testtemplate/_mapping
GET testtemplate/_settings

# 自己设定的settings的优先级高于template
PUT testmy
{
  "settings": {
    "number_of_replicas": 5
  }
}

PUT testmy/_doc/1
{
  "key" : "value"
}

GET testmy/_settings

9.2 什么是Dynamic Template

  • 根据Elasticseach识别的数据类型,结合字段名称,来动态设定字段类型
    • 所有的字符串类型都设定成Keyword,或者关闭keyword字段
    • is开头的字段都设置成boolean
    • long_开头的都设置成long类型

9.2.1 Dynamic Template

image
  • Dynamic Template是定义在某个索引的Mapping
  • Template有一个名称
  • 匹配规则是一个数组
  • 为匹配到字段设置Mapping
image

image
GET my_index/_mapping
DELETE my_index
PUT my_index
{
  "mappings": {
    "dynamic_templates": [
      {
        "string_as_boolean": {
          "match_mapping_type": "string",
          "match" : "is*",
          "mapping": {
            "type": "boolean"
          }
        } 
      },
      {
        "string_as_keywords": {
          "match_mapping_type" : "string",
          "mapping" : {
            "type" : "keyword"
          }
        }
      }
    ]
  }
}

PUT my_index/_doc/1
{
  "firstName" : "Ruan",
  "isVip" : "true"
}

GET my_index/_mapping

10. Elasticsearch聚合分析简介

10.1 什么是聚合?

  • Elasticsearch除了搜索之外,提供的针对ES数据进行统计分析的功能
    • 实时性高
    • Hadoop(T+1)
  • 通过聚合,我们会得到一个数据的概览,是分析和总结全套的数据,而不是寻找单个文档
    • 尖沙咀和香港岛的客房数量
    • 不同的价格区间,可预定的经济型酒店和五星级酒店的数量
  • 高性能,只需要一条语句,就可以从Elasticsearch得到分析结果
    • 无需再客户端自己去实现分析逻辑
  • Kibana中大量的可视化报表,都是聚合分析来的

10.2 聚合的分类

  • Bucket Aggregation:一些列满足特定条件的文档的集合(<font size = 3 color = red>类似Group BY</font>)
  • Metric Aggregation:一些数学运算,可以对文档字段进行统计分析(最大值、最小值、平均值)
  • Pipeline Aggregation:对其他的聚合结果进行二次聚合
  • Matrix Aggregation:支持多个字段的操作并提供一个结果矩阵

10.3 Bucket & Metric

  • Bucket: 可以理解为SQL中的Group
  • Metric: 可以理解为SQL中的Count,可以执行一系列的统计方法

10.3.1 Bucket

image
  • 一些例子
    • 杭州属于浙江/一个演员属于 男或女
    • 嵌套关系:杭州属于浙江属于中国属于亚洲
  • Elasticsearch提供了很多类型的Bucket,帮助你用多种方式划分文档
    • Term & Range(时间/年龄区间/地理位置)
image

10.3.2 Metric

  • Metric会基于数据集计算结果,除了支持在字段上进行计算,同样也支持在脚本(painless script)产生的结果之上进行计算
  • 大多数Metric是数学计算,仅输出一个值
    • min/max/sum/avg/cardinality
  • 部分metric支持输出多个数值
    • stats/percentiles/percentile_ranks
image

image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容