[ES] elasticsearch7.5.1 学习笔记

简介


ElasticSearch是一个基于Lucene的搜索服务器;

Elasticsearch最关键的就是提供强大的索引能力了, Elasticsearch索引的精髓

一切设计都是为了提高搜索的性能

 

安装ES


https://hub.docker.com/_/elasticsearch?tab=tags

拉取elasticsearch镜像;

docker pull elasticsearch:7.5.1

安装elasticsearch容器

docker run -d --name es7_server -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.5.1

查看是否安装成功

http://localhost:9200/

[ES] elasticsearch7.5.1 学习笔记_第1张图片

 

安装Kibana


Kibana 是为 Elasticsearch设计的开源分析和可视化平台;

拉取kibana镜像;

版本要跟es一致;

docker pull kibana:7.5.1

安装kibana容器

docker run -d --name kibana7.5.1 -p 5601:5601 --link b485e5c9bf22 kibana:7.5.1

b485e5c9bf22 为es 容器ID;

访问kibana

http://localhost:5601/app/kibana

[ES] elasticsearch7.5.1 学习笔记_第2张图片

Kibana server is not ready yet ? 报错

进入kibana容器, 修改kibana.yml配置文件

[root@localhost docker]# docker exec -it 187db87cb147 /bin/bash

[ES] elasticsearch7.5.1 学习笔记_第3张图片

bash-4.2$ vi config/kibana.yml

将配置文件kibana.yml中的elasticsearch.url改为正确的链接,默认为: http://elasticsearch:9200 改为http://自己的IP地址:9200

 

Elastic HD

ElasticHD 是一款 ElasticSearch的可视化应用。不依赖ES的插件安装,更便捷;导航栏直接填写对应的ES IP和端口就可以操作Es了

docker run -p 9800:9800 -d --link b485e5c9bf22 containerize/elastichd

b485e5c9bf22 为es 容器ID;

访问 http://localhost:9800/

[ES] elasticsearch7.5.1 学习笔记_第4张图片

 

elasticsearch-head

拉取镜像

docker pull mobz/elasticsearch-head:5

创建容器

docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5

启动容器

docker start elasticsearch-head

访问

浏览器打开: http://IP:9100

输入es地址点击连接

[ES] elasticsearch7.5.1 学习笔记_第5张图片

 

 

  • 无法连接问题

进入elassticsearch安装目录,修改配置文件elasticsearch.yml

vi config/elasticsearch.yml

添加跨域配置

http.cors.enabled: true

http.cors.allow-origin: "*"

重启es;

既可以连接成功了

 

 

概念


映射(Mapping)

Mapping 类似于数据库中的表结构定义, 定义文档及其包含的字段是如何存储和索引的过程;

  • 定义index下的字段名
  • 定义字段类型,比如数值型、浮点型、布尔型等
  • 定义倒排索引相关的设置,比如是否索引、记录position等

这里写图片描述

{
    "mappings": {
        "users": { 
            "properties": {
                "name":     { "type": "text"  }, 
                "age":      { "type": "integer" },  
                "created":  {
                    "type":   "date", 
                    "format": "strict_date_optional_time||epoch_millis"
                }
            }
        }
    }
}

 

映射类型 (Mapping Type)

每个索引都有一个映射类型,以决定文档将被如何索引;

映射类型包含两部分:

Meta-fields

  Meta-fields通常用于自定义文档的元数据。例如,meta-fields包括文档的 _index, _type, _id, _source等字段

Fields 或 properties

  一个映射类型包含一个字段列表或属性列表

 

字段数据类型 (Field datatypes)

每个字段有一个数据类型,它可以是下列之一:

  • 简单类型,比如 text, keyword, date, long, double, boolean , ip
  • 支持JSON层级结构的类型,比如 object 或者 nested
  • 特别的类型,比如 geo_point, geo_shape, completion

 

索引 / 类型 / 文档 / 字段

Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式

关系数据库     ⇒ 数据库 ⇒ 表    ⇒ 行    ⇒ 列(Columns)

Elasticsearch  ⇒ 索引(Index)   ⇒ 类型(type)  ⇒ 文档(Docments)  ⇒ 字段(Fields)  

索引

索引是具有相同结构的文档集合;

每个索引都有一个映射类型,以决定文档将被如何索引;

 

文档 (document)

 

 

分析器(analyzer)

接受文本,处理输出token流;

由三种构件块组成的:

  • character filters (字符过滤器)
  • tokenizer(分词器)
  • token filters(token过滤器)

 

[ES] elasticsearch7.5.1 学习笔记_第6张图片

一个analyzer可以有0个或多个character filters

一个analyzer有且只能有一个tokenizer

一个analyzer可以有0个或多个token filters

 

字符过滤器 (Character filters)

字符过滤器以字符流的形式接收原始文本,并可以通过添加、删除或更改字符来转换该流。

character filter 是做字符转换的,它接收的是文本字符流,输出也是字符流;

一个分析器可以有0个或多个字符过滤器,它们按顺序应用,类似Servlet中的过滤器,或者拦截器链;

 

分词器 (Tokenizer)

接受一个字符串作为输入,将这个字符串拆分成独立的词或 语汇单元(token) (可能会丢弃一些标点符号等字符),然后输出一个 语汇单元流(token stream) ---- 接收字符流,输出token流

Tokenizer 负责将文本拆分成单个token ,这里token就指的就是一个一个的单词。就是一段文本被分割成好几部分,相当于Java中的字符串的 split

 

ES内置分词器
分词器 类型type 规则
标准分词器 Standard Tokenizer standard ES默认分词器,  实现Unicode文本分割算法,该分割算法在Unicode Standard Annex #29中指定
连词分词器 NGram Tokenizer nGram  
边际连词分词器 Edge NGram Tokenizer edgeNGram  
关键字分词器 Keyword Tokenizer keyword 不分词
字符分词器 Letter Tokenizer letter 将文本按非字符(non-lentter)进行分词
小写分词器 Lowercase Tokenizer lowercase 将词全部转换成小写,其他的同letter Tokenizer
空格分词器Whitespace Tokenizer whitespace 按空格分词
模式分词器/正则分词器 Pattern Tokenizer pattern 根据正则表达式的匹配规则来分词
标准Email URL分词器 UAX Email URL Tokenizer uax_url_email 和标准分词器一样,但是把email和url当作一个词
路径层次分词器 Path Hierarchy Tokenizer path_hierarchy 按 / 分词
典型的编译器 Classic Tokenizer classic 基于语法的分词器,这对英语文档是一个很好的分词器
Simple Analyzer simple 按照非字母切分(符号被过滤), 小写处理
Stop Analyzer stop 小写处理,停用词过滤(the,a,is)

 

 

第三方分词器比较
分词器 优势 劣势
Smart Chinese Analysis 官方插件 中文分词效果惨不忍睹
IKAnalyzer 简单易用,支持自定义词典和远程词典 词库需要自行维护,不支持词性识别
结巴分词 新词识别功能 不支持词性识别
Ansj中文分词 分词精准度不错,支持词性识别 对标hanlp词库略少,学习成本高
Hanlp 目前词库最完善,支持的特性非常多 需要更优的分词效果,学习成本高

截止到目前为止,他们的分词准确性从高到低依次是:

Hanlp > Ansj > 结巴 > IK > Smart Chinese Analysis

 

token filter 是做token过滤的,它接收token流,输出也是token流

 

token过滤器(token filters)

Token filters accept a stream of tokens from a tokenizer and can modify tokens (eg lowercasing), delete tokens (eg remove stopwords) or add tokens (eg synonyms).

对token流进行过滤;

 

停用词(stopwords)

信息检索中,停用词是为节省存储空间和提高搜索效率,处理文本时自动过滤掉某些字或词,这些字或词即被称为Stop Words(停用词);

用词大致分为两类:

  • 一类是语言中的功能词

这些词极其普遍而无实际含义,比如“the”、“is“、“which“、“on”等

  • 一类是词汇词

比如‘want‘等,这些词应用广泛,但搜索引擎无法保证能够给出真正相关的搜索结果,难以缩小搜索范围,还会降低搜索效率。

 

实践中,通常把这些词从问题中过滤,从而节省索引的存储空间、提高搜索性能。

 

分片(Shards)

ES中所有数据的文件块,也是数据的最小单元块;

整个ES集群的核心就是对所有分片的分布、索引、负载、路由等达到惊人的速度;

 

分片个数是越多越好,还是越少越好? 建议:(仅参考)

1、每一个分片数据文件小于30GB

2、每一个索引中的一个分片对应一个节点

3、节点数大于等于分片数

 

实列场景:

如果 IndexA 所有数据文件大小是300G,改怎么定制方案?(可以通过Head插件来查看)

根据建议,至少需要 10 个分片。

结果: 建10个节点 (Node),Mapping 指定分片数为 10,满足每一个节点一个分片,每一个分片数据带下在30G左右。

SN(分片数) = IS(索引大小) / 30

NN(节点数) = SN(分片数) + MNN(主节点数[无数据]) + NNN(负载节点数)

 

别名

索引别名;

Elasticsearch可以对一个或者多个索引指定别名, 通过别名可以查询到一个或者多个索引的内容。

在内部,Elasticsearch会自动把别名映射到相应的索引上。

可以对别名编写过滤器或者路由,在系统中别名不能重复,也不能和索引名重复。

Elasticsearch的别名机制有点像数据库中的视图

 

一个别名可以对应多个索引;

一个索引可以有多个别名;

 

常用操作


操作方式

浏览器, postman,jmeter,idea restfull client,kibana;

 

添加索引

添加索引users, 请求方式PUT

PUT /users
{
   "settings" : {
      "number_of_shards" : 1,
      "number_of_replicas" : 1
   }
}

返回

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "users"
}

 

删除索引

删除索引 users, 请求方式DELETE

DELETE /users

返回结果

{
  "acknowledged" : true
}
 

获取索引映射

通过 _mapping内置映射, 请求方式GET

GET /users/_mappings

返回

{
  "users" : {
    "mappings" : { }
  }
}

 

GET http://127.0.0.1:9200/secisland/_mapping/             指定索引
GET http://127.0.0.1:9200/_all/_mapping/                  所有索引
GET http://127.0.0.1:9200/_mapping/                       与上一个一样
GET http://127.0.0.1:9200/secisland,secisland2/_mapping/  多个索引

 

修改索引映射

通过_mapping内置映射, 请求方式POST;

不能修改,删除 properties属性字段,只能添加;

POST /users/_mappings
{
  "properties": {
    "name": {
      "properties": {
        "last": {
          "type": "keyword"
        }
      }
    },
    "user_id": {
      "type": "keyword",
      "index": "false",
      "ignore_above": 100
    }
  }
}

返回

{
  "acknowledged" : true
}
 

索引添加别名

POST/ PUT方式;

给users这个索引,起个别名为us;

POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "users",
        "alias": "us"
      }
    }
  ]
}

查看别名

查看users索引的别名

GET /users/_alias

返回

{
  "users" : {
    "aliases" : {
      "us" : { }
    }
  }
}

 

查看所有索引的别名

GET /_alias

 

删除别名

POST方式;

注意这里是_aliases不是_alias

POST /_aliases
{
 "actions": [
    {
      "remove": {
        "index": "users",
        "alias": "us2"
      }
    }
  ] 
}

别名没有修改的语法,当需要修改别名的时候,可以先删除别名,然后再增加别名

 

为索引设置分词器

为forum索引定义standard分词器

PUT /forum
{
  "settings": {
    "number_of_shards" : 1,
    "number_of_replicas" : 1,
    "analysis": {
      "analyzer": {
        "es_std":{
          "type":"standard",
          "stopwords":"_english_"
        }
      }
    }
  }
}
 

停用词(stopwords)使用 _english_

 

默认分词器standard

按空格分成多个token

# 测试默认分词器
GET /forum/_analyze
{
  "analyzer": "standard",
  "text": ["a dog is in the house", "中华人民共和国the house蜂巢互联"]
}

 

常用分词器

PUT /forum1 
{
    "settings": {
        "analysis": {
          "filter": {
                "my_stopwords": {
                    "type": "stop",
                    "stopwords": ["的"]
                }
            },
            "analyzer": {
                "my_analyzer": {
                  "char_filter" : [],
                    "tokenizer": "standard",
                    "filter":[]
                },
                "my_nGram": {
                    "tokenizer": "nGram"
                },
                "my_edgeNGram": {
                    "tokenizer": "edgeNGram"
                },
                "my_keyword": {
                    "tokenizer": "keyword",
                    "buffer_size":"2"
                },
                "my_letter": {
                    "tokenizer": "letter"
                },
                "my_lowercase": {
                    "tokenizer": "lowercase"
                },
                "my_whitespace": {
                    "tokenizer": "whitespace"
                },
                "my_pattern": {
                    "tokenizer": "pattern"
                },
                "my_uax_url_email": {
                    "tokenizer": "uax_url_email"
                },
                "my_path_hierarchy": {
                    "tokenizer": "path_hierarchy"
                },
                "my_classic": {
                    "tokenizer": "classic"
                },
                "my_ik_smart": {
                    "tokenizer": "ik_smart",
                    "filter":["my_stopwords"]
                }
            }
        }
    }
}

 

停用词的分词器

过滤掉 a is in the 没有意义的单词

PUT /forum
{
  "settings": {
    "number_of_shards" : 1,
    "number_of_replicas" : 1,
    "analysis": {
      "analyzer": {
        "es_std":{
          "type":"standard",
          "stopwords":"_english_"
        }
      }
    }
  }
}

 

# 测试es_std分词器
GET /forum/_analyze
{
  "analyzer": "es_std",
  "text": ["a dog is in the house"]
}

 

filter处理token

限制单词长度, 大小写转换

GET _analyze
{
  "tokenizer" : "standard",
  "filter": [{"type": "length", "min":2, "max":3 }, "uppercase"],  
  "text" : "A Bb Ccc Dddd Eeeee"
}

过滤出【2,3】区间长度, 转成大写;

 

 

自定义分词器

定义一个名称是my_analyzer的分词器

PUT /forum 
{
    "settings": {
        "analysis": {
            "char_filter": {
                "&_to_and": {
                    "type": "mapping",
                    "mappings": ["&=>and","es=>Elasticsearch"]
                }
            },
            "filter": {
                "my_stopwords": {
                    "type": "stop",
                    "stopwords": ["的"]
                }
            },
            "analyzer": {
                "my_analyzer": {
                    "type": "custom",
                    "char_filter": ["html_strip", "&_to_and"],
                    "tokenizer": "standard",
                    "filter": ["lowercase", "my_stopwords"]
                }
            }
        }
    }
}

测试效果

GET /forum/_analyze
{
  "analyzer": "my_analyzer",
  "text": ["

solr & es
的比较"]
}

进行了以下处理:

  1. html_strip把html标签元素去掉;
  2. &_to_and 把 &改成and
  3. lowercase 把token转成大写

 

 

IK分词器


查看IK分词库ES插件, 版本要跟ES一致

https://github.com/medcl/elasticsearch-analysis-ik/releases

安装

[root@b485e5c9bf22 bin]# ./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.1/elasticsearch-analysis-ik-7.5.1.zip

安装完插件后需重启Es,才能生效;

 

测试

POST _analyze
{
  "analyzer": "ik_smart",
  "text": "ik_smart会做最粗粒度的拆分, ik_max_word会将文本做最细粒度的拆分"
}

 

#使用自定义分词器,过滤掉 ”的“

POST /forum1/_analyze
{
  "analyzer": "my_ik_smart",
  "text": "ik_smart会做最粗粒度的拆分, ik_max_word会将文本做最细粒度的拆分"
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Elasticsearch)