ElasticSearch学习笔记

一、常用术语

索引(Index)、类型(Type)、文档(Document)

  • 索引Index是含有相同属性的文档集合。索引在ES中是通过一个名字来识别的,且必须是英文字母小写,且不含中划线(-);可类比于 MySQL 中的 database ;在 7.0中,由于类型(Type)的移除,我们可以理解为,一个索引就是一张 table。
  • 一个索引中可以定义一个或多个类型Type,文档必须属于一个类型;可类比于 MySQL 中的 table;
  • 文档Document是可以被索引的基本数据单位。文档是Elasticsearch中最小的数据存储单位。可类比于 MySQL 中 一个table 中的一行记录

注意事项:
从ES6.0开始,官方便不建议一个索引中创建多个类型;在ES7.0中,更是移除了类型(Type)这个概念。为什么呢?
在Elasticsearch索引中,不同类型(Type)中具有相同名称的字段在内部由相同的Lucene字段支持。一个index中多个Type在Lucene中会有许多问题。具体的可以参考官方说明:Removal of mapping types

节点Node、集群Cluster

  • 节点:一个ES运行实例,是集群的的构成单元
  • 集群:由1个(只有1个节点也是1个集群)或多个节点组成,对外提供服务

分片Shard(集群—提高吞吐与计算性能)、副本Replica(主从—提高可用性)

  • 在ES中,每个索引都有多个分片,每个分片都是一个Lucene索引。假设一个索引的数据量很大,就会造成硬盘压力很大,同时,搜索速度也会出现瓶颈。我们可以将一个索引分为多个分片,从而分摊压力;分片同时还允许用户进行水平地扩展和拆分,以及分布式的操作,可以提高搜索以及其他操作的效率。
  • 拷贝一份分片,就完成了分片的备份。备份的好处是,当一个主分片出现问题时,备份的分片就能代替工作,从而提高了ES的可用性。同时,备份的分片还可以执行搜索操作,以分摊搜索的压力。ES禁止同一个分片的主分片和副本分片在同一个节点上。

RESTful API

Elasticsearch 集群对外提供 RESTful API

  • REST - REpresentational State Transfer
  • URI 指定资源,如Index、Document等
  • Http Method 指明资源操作类型,如GET、POST、PUT、DELETE等

倒排索引

  • 正排索引


     
    ElasticSearch学习笔记_第1张图片
    正排索引
 
ElasticSearch学习笔记_第2张图片
倒排索引
 
ElasticSearch学习笔记_第3张图片
全文检索查询流程

倒排索引组成

倒排索引是搜索引擎的核心,主要包含两部分:

  • 单词词典(Term Dictionary)
    • 记录所有文档的单词,一般都比较大
    • 记录单词到倒排列表的关联信息
    • 单词字典的实现一般是用B+Tree,能兼顾内存与磁盘性能,保障增删改查高效
  • 倒排列表(Posting List)
    • 倒排列表(Posting List)记录了单词对应的文档集合,由倒排索引项(Posting)组成
    • 倒排索引项(Posting)主要包含如下信息:
      • 文档ld,用于获取原始信息
      • 单词频率(TF,Term Frequency),记录该单词在该文档中的出现次数,用于后续相关性算分
      • 位置(Position),记录单词在文档中的分词位置(多个),用于做词语搜索(Phrase Query)
      • 偏移(Offset),记录单词在文档的开始和结束位置,用于做高亮显示
 
ElasticSearch学习笔记_第4张图片
倒排列表例子

 

 
ElasticSearch学习笔记_第5张图片
单词字典指向倒排列表例子

ES中的倒排索引

es存储的是一个json格式的文档,其中包含多个字段,每个字段会有自己的倒排索引。

 

 
ElasticSearch学习笔记_第6张图片
ES中倒排索引

相关性算分

相关性算分是指文档与查询语句间的相关度,英文为 relevance

  • 通过倒排索引可以获取与查询语句相匹配的文档列表,那么如何将最符合用户查询需求的文档放到前列呢?
  • 本质是一个排序问题,排序的依据是相关性算分
 
ElasticSearch学习笔记_第7张图片

相关性算分的几个重要概念

  • Term Frequency(TF)词频,即单词在该文档中出现的次数。词频越高,相关度越高
  • Document Frequency(DF)文档频率,即单词出现的文档数
  • Inverse Document Frequency(IDF)逆向文档频率,与文档频率相反,简单理解为1/DF。即单词出现的文档数越少,相关度越高
  • Field-length Norm 文档越短,相关性越高

使用 explain 参数查看具体的计算方法

  • es的算分是按照shard进行的,即shard的分数计算是相互独立的,所以在使用explain的时候注意分片数
  • 可以通过设置索引的分片数为1来避免这个问题


     
    ElasticSearch学习笔记_第8张图片

ES中的相关性算分模型

  • TF/IDF 模型
  • BM25 模型5.x之后的默认模型

TF/IDF 模型

 
ElasticSearch学习笔记_第9张图片

BM25 模型

 
ElasticSearch学习笔记_第10张图片
 
ElasticSearch学习笔记_第11张图片
BM25 模型对比TF/IDF 模型

二、Document API

1. 文档是一个Json Object,由字段(Field)组成,常见数据类型如下:

  • 字符串:text,keyword(不分词)
  • 数值型:long,integer,short byte,double,float,half float,scaled_float
  • 布尔:boolean
  • 日期:date
  • 二进制:binary
  • 范围类型:integer_range,float_range,long_range,double_range,date_range

2. 文档元数据,用于标注文档的相关信息

  • _index:文档所在的索引名
  • _type:文档所在的类型名(7.0后默认_doc)
  • _id:文档唯一id
  • _uid:组合id,由_type和_id组成(6.x_type不再起作用,因此同_id值一样),默认禁用
  • _source:文档的原始Json数据,可以从这里获取每个字段的内容
  • _all:整合所有字段内容到该字段,默认禁用

3. 每个文档有唯一的_Id标识

  • 自行指定
  • es自动生成

4. 文档API

  • es有专门的Document API,创建文档,查询文档,更新文档,删除文档

创建文档(创建文档时,如果索引不存在,es会自动创建对应的index和type)

  • 指定id创建文档
PUT /test_index/_doc/1
{
  "username":"zhangsan",
  "age":1
}
 
ElasticSearch学习笔记_第12张图片
指定ID创建文档
  • 不指定id创建文档
POST /test_index/_doc
{
  "username":"lisi",
  "sex":2
}
 
ElasticSearch学习笔记_第13张图片
不指定ID创建文档

查询文档

  • 指定要查询的文档id
GET /test_index/_doc/1
 
ElasticSearch学习笔记_第14张图片
指定要查询的文档id
  • 搜索所有文档,用到_search
GET /test_index/_search # GET /test_index/_doc/_search在高版本提示类型已过期,因此不用指定type了
 
ElasticSearch学习笔记_第15张图片
搜索所有文档

批量增删改查文档

  • ES允许一次创建多个文档,从而减少网络传输开销,提升写入速率,endpoint为_bulk
  • index 用于创建文档,文档已存在则更细文档
  • create 同样可以创建文档,文档已存在则返回错误
  • delete 用于删除文档
  • update 用于更新文档,文档不存在则返回错误
  • 在es6.0之后的版本可以省略_type,官方已舍弃_type这个概念
POST _bulk
{"index":{"_index":"test_index","_id":"3"}}
{"username":"alfred","age":10}
{"create":{"_index":"test_index","_id":"3"}}
{"username":"alfred2","age":110}
{"delete":{"_index":"test_index","_id":"1"}}
{"update":{"_id":"2","_index":"test_index"}}
{"doc":{"age":"20"}}

返回:

{
  "took" : 18, "errors" : true, "items" : [ { "index" : { "_index" : "test_index", "_type" : "_doc", "_id" : "3", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 4, "_primary_term" : 1, "status" : 200 } }, { "create" : { "_index" : "test_index", "_type" : "_doc", "_id" : "3", "status" : 409, "error" : { "type" : "version_conflict_engine_exception", "reason" : "[3]: version conflict, document already exists (current version [2])", "index_uuid" : "jjJIqT7QSeaYcOeWxxY-og", "shard" : "0", "index" : "test_index" } } }, { "delete" : { "_index" : "test_index", "_type" : "_doc", "_id" : "1", "_version" : 3, "result" : "not_found", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 5, "_primary_term" : 1, "status" : 404 } }, { "update" : { "_index" : "test_index", "_type" : "_doc", "_id" : "2", "status" : 404, "error" : { "type" : "document_missing_exception", "reason" : "[_doc][2]: document missing", "index_uuid" : "jjJIqT7QSeaYcOeWxxY-og", "shard" : "0", "index" : "test_index" } } } ] } 

批量查询文档[跨索引]

  • es允许一次查询多个索引的文档,endpoint为_mget
GET /_mget
{
  "docs": [
    {
      "_index": "test_index",
      "_id": 1
    },
    {
      "_index": "test_index2",
      "_id": 1
    }
  ]
}

返回

{
  "docs" : [
    { "_index" : "test_index", "_type" : "_doc", "_id" : "1", "found" : false }, { "_index" : "test_index2", "_type" : null, "_id" : "1", "error" : { "root_cause" : [ { "type" : "index_not_found_exception", "reason" : "no such index [test_index2]", "resource.type" : "index_expression", "resource.id" : "test_index2", "index_uuid" : "_na_", "index" : "test_index2" } ], "type" : "index_not_found_exception", "reason" : "no such index [test_index2]", "resource.type" : "index_expression", "resource.id" : "test_index2", "index_uuid" : "_na_", "index" : "test_index2" } } ] } 

三、Indices APIs

1. 索引中一般存储具有相同结构的文档(Document)

  • 每个索引都有自己的mapping定义,用于定义字段名和类型
  • 创建索引不定义mapping,es将自动根据插入的数据定义mapping,但是通常不建议这样做,mapping相当于数据库建表时的表结构定义
  • 1个索引中可以存储不同结构的文档,但在6.0后type的舍弃,官方建议1个index存储1中结构的文档

2. 一个集群(只有1个节点也是1个集群)可以有多个索引,比如:nginx 日志存储的时候可以按照日期每天生成一个索引来存储

  • nginx-log-2017-01-01
  • nginx-log-2017-01-02
  • nginx-log-2017-01-03

3. 索引API

  • es有专门的IndexAPI,用于查询、创建、更新、删除索引配置等

创建索引

PUT /test_index
 
创建索引成功

查看所有索引

GET /_cat/indices
 
ElasticSearch学习笔记_第16张图片
全部索引

删除索引

DELETE /test_index
 
删除成功

4. 索引模板

索引模板,英文为Index Template,主要用于在新建索引时自动应用预先设定的配置,简化索引创建的操作步骤

  • 可以设定索引的配置和mapping
  • 可以有多个模板,当创建的索引匹配到多个模板时,根据order设置,order大的覆盖小的配置
 
ElasticSearch学习笔记_第17张图片
创建索引模板(语法可能过期)
  • 查看所有索引模板
    • GET /_template
  • 查看指定名称的索引模板
    • GET /_template/test_template
  • 删除指定名称的索引模板
    • DELETE /_template/test_template

四、Analysis

分词是指将文本转换成一系列单词(term or token)的过程,也可以叫做文本分析,在es 里面称为Analysis,如下图所示:

 

 
ElasticSearch学习笔记_第18张图片
分词

在es中,分词会在如下两个时机使用:

  • 创建或更新文档时,也称索引时(Index Time),会对相应的文档进行分词处理


     
    ElasticSearch学习笔记_第19张图片
    索引时分词
  • 查询时(Search Time),会对查询语句进行分词


     
    ElasticSearch学习笔记_第20张图片
    查询时分词

一般不需要特别指定查询时分词器,直接使用索引时分词器即可(此时查询也会默认使用索引时分词器)

分词的使用建议:

  • 明确字段是否需要分词,不需要分词的字段就将type设置为keyword,可以节省空间和提高写性能
  • 善用_analyze API,查看文档的具体分词结果
  • 动手测试

1. 分词器组成

分词器是es中专门处理分词的组件,英文为Analyzer,它的组成如下:

  • Character Filters
    • 针对原始文本进行处理,比如去除html特殊标记符
  • Tokenizer
    • 将原始文本按照一定规则切分为单词
  • Token Filters
    • 针对tokenizer处理的单词就行再加工,比如转小写、删除或新增等处理
 
ElasticSearch学习笔记_第21张图片
分词器中的调用顺序

2. es内置的分词器

es 自带如下的分词器:

  • Standard
  • Simple
  • Whitespace
  • Stop
  • Keyword
  • Pattern
  • Language

Standard Analyzer

 
ElasticSearch学习笔记_第22张图片
POST _analyze
{
  "analyzer":"standard",
  "text":"The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:

{
  "tokens" : [
    { "token" : "the", "start_offset" : 0, "end_offset" : 3, "type" : "", "position" : 0 }, { "token" : "2", "start_offset" : 4, "end_offset" : 5, "type" : "", "position" : 1 }, { "token" : "quick", "start_offset" : 6, "end_offset" : 11, "type" : "", "position" : 2 }, { "token" : "brown", "start_offset" : 12, "end_offset" : 17, "type" : "", "position" : 3 }, { "token" : "foxes", "start_offset" : 18, "end_offset" : 23, "type" : "", "position" : 4 }, { "token" : "jumped", "start_offset" : 24, "end_offset" : 30, "type" : "", "position" : 5 }, { "token" : "over", "start_offset" : 31, "end_offset" : 35, "type" : "", "position" : 6 }, { "token" : "the", "start_offset" : 36, "end_offset" : 39, "type" : "", "position" : 7 }, { "token" : "lazy", "start_offset" : 40, "end_offset" : 44, "type" : "", "position" : 8 }, { "token" : "dog's", "start_offset" : 45, "end_offset" : 50, "type" : "", "position" : 9 }, { "token" : "bone", "start_offset" : 51, "end_offset" : 55, "type" : "", "position" : 10 

转载于:https://www.cnblogs.com/mjhblog/p/11589130.html

你可能感兴趣的:(ElasticSearch学习笔记)