(一)、ElasticSearch简介

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: (一)、ElasticSearch简介

Elasticsearch简介

Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

*特点:*

  • 分布式的实时文件存储,每个字段都被索引并可被搜索
  • 分布式的实时分析搜索引擎--做不规则查询
  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据

Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

ES能做什么?

全文检索(全部字段)、模糊查询(搜索)、数据分析(提供分析语法,例如聚合)

Elasticsearch使用案例

(1)2013年初,GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch搜索20TB的数据,包括13亿文件和1300亿行代码”

(2)维基百科:启动以elasticsearch为基础的核心搜索架构SoundCloud:“SoundCloud使用ElasticSearch为1.8亿用户提供即时而精准的音乐搜索服务”

(3)百度:百度目前广泛使用ElasticSearch作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据

(4)新浪使用ES 分析处理32亿条实时日志

(5)阿里使用ES 构建挖财自己的日志采集和分析体系

基本概念

Index(索引)

Elastic 会索引所有字段,经过处理后写入一个反向索引(Inverted Index)。查找数据的时候,直接查找该索引

所以,Elastic 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词。每个 Index (即数据库)的名字必须是小写。

  • 动词,相当于mysql的insert
  • 名词,相当于mysql的database

es某个索引的某个类型下,就相当于mysql哪个数据库的哪个表下

Document(文档)

保存在某个 Index(索引)下,某种 Type(类型)的一个数据,Document(文档)是JSON格式的,Document 就像是 MySQL 中某个 Table 里面每一行的数据,字段就是Document里的属性。

在mysql中存的一条条叫数据,es中存的数据叫文档

Type(类型)

在 Index(索引)中,可以定义一个或多个类型。

类似于 MySQL 的 Table,每一种类 型的数据存放在一起。

在Elasticsearch6.0之后,Type 类型被移除。


对比关系

索引(index)----------------------Databases 数据库
  类型(type)--------------------------Table 数据表
     文档(Document)----------------------Row 行
      字段(Field)-------------------------Columns 列

倒排索引


Docker安装Elasticsearch、Kibana

Docker镜像网站:Docker Hub Container Image Library | App Containerization

1. 下载镜像文件

# 存储和检索数据
docker pull elasticsearch:7.4.2
# 可视化检索数据
docker pull kibana:7.4.2


2.配置挂载数据文件夹

# 创建配置文件目录
mkdir -p /mydata/elasticsearch/config
# 创建数据目录
mkdir -p /mydata/elasticsearch/data
# 将/mydata/elasticsearch/文件夹中文件都可读可写
chmod -R 777 /mydata/elasticsearch/
# 配置任意机器可以访问 elasticsearch
echo "http.host: 0.0.0.0" >/mydata/elasticsearch/config/elasticsearch.yml

3. 启动Elasticsearch

docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e  "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v  /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2


  • -p 9200:9200 -p 9300:9300:向外暴露两个端口,9200用于HTTP REST API请求,9300 ES 在分布式集群状态下 ES 之间的通信端口;
  • -e  "discovery.type=single-node":es 以单节点运行
  • -e ES_JAVA_OPTS="-Xms64m -Xmx512m":设置启动占用内存,不设置可能会占用当前系统所有内存
  • -v:挂载容器中的配置文件、数据文件、插件数据到本机的文件夹;
  • -d elasticsearch:7.6.2:指定要启动的镜像

4.安装成功

访问http://192.168.195.100:9200/ 显示以下内容则安装成功


如果没有反应查看日志是否有error报错信息

docker logs elasticsearch

如果日志没有报错检查是否开启了虚拟机的防火墙,并开放相关9200端口才能显示成功

如果没有权限开启相关文件夹的读写操作权限

chmod -R 777 /mydata/elasticsearch/

5.启动可视化Kibana

-e ELASTICSEARCH_HOSTS=http://192.168.195.100:9200这里改成自己的虚拟机地址

docker run --name kibana \
-e ELASTICSEARCH_HOSTS=http://192.168.195.100:9200 \
-p 5601:5601 \
-d kibana:7.4.2

这里记得要添加防火墙端口

firewall-cmd --zone=public --add-port=5601/tcp --permanent

查看开放的端口

sudo firewall-cmd --zone=public --list-ports

更新防火墙

sudo firewall-cmd --reload


访问:Kibana


6.配置启动方式

# 当前 Docker 开机自启,所以 kibana 现在也是开机自启
docker update kibana --restart=always
# 当前 Docker 开机自启,所以 ES 现在也是开机自启
docker update elasticsearch --restart=always

初步检索

_Cat

Elasticsearch 都是通过 REST API 接口来操作数据的,那么下面接通过几个接口的请求来演示它的使用

1.查看所有节点信息

http://192.168.195.100:9200/_cat/nodes

2.查看节点健康状况

http://192.168.195.100:9200/_cat/health

3.查看主节点信息

http://192.168.195.100:9200/_cat/master

4.查看所有索引

http://192.168.195.100:9200/_cat/indices

索引文档

即保存一条数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识

PUT 请求

http://192.168.195.100:9200/customer/external/1


version:多次操作会更新版本

result:第一次是新增、第二次是更新

POST 请求

POST: http://192.168.195.100:9200/customer/external


PUT和POST都可以

  • POST新增,如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号;
  • PUT可以新增也可以修改。PUT必须指定id;由于PUT需要指定id,我们一般用来做修改操作,不指定id会报错。

查看文档

GET:http://192.168.195.100:9200/customer/external/1


{
    "_index": "customer",  # 在哪个索引(库)
    "_type": "external",   # 在哪个类型(表)
    "_id": "1",            # 文档id(记录)
    "_version": 5,         # 版本号
    "_seq_no": 4,          # 并发控制字段,每次更新都会+1,用来做乐观锁
    "_primary_term": 1,    # 同上,主分片重新分配,如重启,就会变化
    "found": true,
    "_source": {           # 数据
        "name": "zhangsan"
    }
}
# 乐观锁更新时携带 ?_seq_no=0&_primary_term=1  当携带数据与实际值不匹配时更新失败

更新文档

POST:http://192.168.195.100:9200/customer/external/1/_update


result:noop表示更新数据跟原数据相同,没有做任何操作

更新文档的区别

POST、PUT请求带id都会直接更新数据,只有Post带(_update)才会检查更新

PUT请求带id更新和POST请求带id更新,会直接覆盖原来的数据,不会在原来的属性里面新增属性

删除索引

Delete:http://192.168.195.100:9200/customer/external/1


查询不到数据了


删除文档

Delete http://192.168.195.100:9200/custome/

bulk-批量操作数据

{action:{metadata}}\n   // 例如index保存记录,update更新
{request body  }\n
{action:{metadata}}\n
{request body  }\n

指定索引和类型的批量操作

接口:POST /customer/external/_bulk

参数:

{"index":{"_id":"1"}}
{"name":"John Doe"}
{"index":{"_id":"2"}}
{"name":"John Doe"}

在Kibana中使用dev-tools测试批量:


对所有索引执行批量操作

接口:POST /_bulk

{"delete":{"_index":"website","_type":"blog","_id":"123"}}
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"my first blog post"}
{"index":{"_index":"website","_type":"blog"}}
{"title":"my second blog post"}
{"update":{"_index":"website","_type":"blog","_id":"123"}}
{"doc":{"title":"my updated blog post"}}


  • 这里的批量操作,当发生某一条执行发生失败时,其他的数据仍然能够接着执行,也就是说彼此之间是独立的。
  • bulk api以此按顺序执行所有的action(动作)。如果一个单个的动作因任何原因失败,它将继续处理它后面剩余的动作。
  • 当bulk api返回时,它将提供每个动作的状态(与发送的顺序相同),所以您可以检查是否一个指定的动作是否失败了。

批量导入测试数据

POST bank/account/_bulk

es测试数据.json · 坐看云起时/common_content - Gitee.com



进阶检索

GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": "asc"
    }
  ]
}
# query 查询条件
# sort 排序条件
Get bank/_search?q=*&sort=account_number:asc


Elasticsearch 默认会分页返回10条数据,不会一下返回所有数据。

took—Elasticsearch运行查询所花费的时间,以毫秒为单位
timed_out-是否搜索请求超时
_shards -有多少碎片被搜索,有多少碎片成功,失败,或被跳过。
Max_score -找到的最相关文档的分数
Hits.total.value—找到了多少匹配的文档
hits.Sort—文档的排序位置(当不按相关性分数排序时)
hits._score -文档的相关分数(在使用match_all时不适用)

检索的两种方式

ES支持两种基本方式检索;

  • 通过REST request uri 发送搜索参数 (uri +检索参数);
  • 通过REST request body 来发送它们(uri+请求体);

还可以用GET请求参数的方式检索:

GET bank/_search?q=*&sort=account_number:asc
# q=* 查询所有
# sort=account_number:asc 按照account_number进行升序排列

Query DSL

Elasticsearch提供了一个可以执行查询的Json风格的DSL。这个被称为Query DSL,该查询语言非常全面

基本语法格式

一个查询语句的典型结构:

QUERY_NAME:{
   ARGUMENT:VALUE,
   ARGUMENT:VALUE,...
}

如果针对于某个字段,那么它的结构如下

{
  QUERY_NAME:{
     FIELD_NAME:{
       ARGUMENT:VALUE,
       ARGUMENT:VALUE,...
      }   
   }
}

请求示例:

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": {
        "order": "desc"
      },
      "balance": {
        "order": "asc"
      }
    }
  ],
  "from": 0,
  "size": 5,
  "_source": ["balance","firstname"]
}
# match_all 查询类型【代表查询所有的所有】,es中可以在query中组合非常多的查询类型完成复杂查询;
# from+size 限定,完成分页功能;从第几条数据开始,每页有多少数据
# sort 排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准;
#_source 表示只显示哪一些字段,就像数据库的select xxx from


match全文检索

精确查询-基本数据类型(非文本)

相当于sql语句的where=条件,查找account_number=20的数据

GET bank/_search
{
  "query": {
    "match": {
      "account_number": 20
    }
  }
}

模糊查询-文本字符串

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill lane"
    }
  }
}
# 查找匹配 address 包含 mill 或 lane 的数据

match即全文检索,对检索字段进行分词匹配,会按照响应的评分 _score 排序,原理是倒排索引。

match_phrase 短语匹配

要想精确查找整个字符串,不使用分词,就需要用到match_phrase

GET bank/_search
{
  "query": {
    "match": {
      "address.keyword": "288 Mill Street"
    }
  }
}


multi_math-多字段匹配

相当于sql多条件查询,检查多个字段中有包含xxx的数据,用到了分词

GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": [
        "city",
        "address"
      ]
    }
  }
}
# 检索 city 或 address 匹配包含 mill 的数据,会对查询条件分词

bool-复合查询

复合语句可以合并,任何其他查询语句,包括符合语句

  • must:必须达到must所列举的所有条件
  • must_not,必须不匹配must_not所列举的所有条件。
  • should,应该满足should所列举的条件。
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "gender": "M"
          }
        },
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "address": "111"
          }
        }
      ],
      "should": [
        {
          "match": {
            "address": "Lane"
          }
        }
      ]
    }
  }
}
# 查询 gender 为 M 且 address 包含 mill 的数据 
# 并且 address不等于111的数据
# 或者 address等于 Lane的数据

filter-结果过滤

并不是所有的查询都需要产生分数,特别是哪些仅用于filtering过滤的文档。为了不计算分数,elasticsearch会自动检查场景并且优化查询的执行。

filter 对结果进行过滤,且不计算相关性得分。

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "filter": {
        "range": {
          "balance": {
            "gte": "10000",
            "lte": "20000"
          }
        }
      }
    }
  }
}
# 这里先是查询所有匹配 address 包含 mill 的文档,
# 然后再根据 10000<=balance<=20000 进行过滤查询结果 匹配到也不会增加分数,单纯查找作用

term-精确检索

对于非文本字段,使用 term来精确检索是一个推荐的选择,如果要查询文本字段值,请使用 match 查询代替。

GET bank/_search
{
  "query": {
    "term": {
      "age": "28"
    }
  }
}
# 查找 age 为 28 的数据

Aggregation-执行聚合

https://www.elastic.co/guide/en/elasticsearch/reference/7.11/search-aggregations.html

聚合语法

GET /my-index-000001/_search
{
  "aggs":{
    "aggs_name":{ # 这次聚合的名字,方便展示在结果集中
        "AGG_TYPE":{ # 聚合的类型(avg,term,terms)
        } 
     }
  }
}

搜索address中包含mill的所有人的年龄分布以及平均年龄

聚合字段为 age,聚合后前十个数据,求聚合字段为 age的平均值,求聚合字段为 balance的平均值

对address=mill的年龄进行分组,然后求这些组里面age和balance的平均值

GET bank/_search
{
  "query": {
    "match": {
      "address": "Mill"
    }
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 10
      }
    },
    "ageAvg": {
      "avg": {
        "field": "age"
      }
    },
    "balanceAvg": {
      "avg": {
        "field": "balance"
      }
    }
  },
  "size": 0
}
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "ageAgg" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 38,
          "doc_count" : 2
        },
        {
          "key" : 28,
          "doc_count" : 1
        },
        {
          "key" : 32,
          "doc_count" : 1
        }
      ]
    },
    "ageAvg" : {
      "value" : 34.0
    },
    "balanceAvg" : {
      "value" : 25208.0
    }
  }
}

按照年龄聚合,并且求这些年龄段的这些人的平均薪资

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "ageAvg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}


查出所有年龄分布,并且这些年龄段中M的平均薪资和F的平均薪资以及这个年龄段的总体平均薪资

根据年龄分组,再根据男女性别分组,再根据性别分别求平均薪资。求分组年龄的平均薪资

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "genderAgg": {
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "balanceAvg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "ageBalanceAvg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}
# "field": "gender.keyword" gender是txt没法聚合 必须加.keyword精确替代

Mapping-映射

默认添加数据就会找到相应的字段类型

Maping是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。

比如:使用maping来定义:

  • 哪些字符串属性应该被看做全文本属性(full text fields);
  • 哪些属性包含数字,日期或地理位置;
  • 文档中的所有属性是否都嫩被索引(all 配置);
  • 日期的格式;
  • 自定义映射规则来执行动态添加属性;

查看mapping信息

GET bank/_mapping
{
  "bank" : {
    "mappings" : {
      "properties" : {
        "account_number" : {
          "type" : "long"
        },
        "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "age" : {
          "type" : "long"
        },
        "balance" : {
          "type" : "long"
        },
        "city" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "email" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "employer" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "firstname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "gender" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "lastname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "state" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

新版本type移除

ElasticSearch7-去掉type概念

  1. 关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用,但ES中不是这样的。elasticsearch是基于Lucene开发的搜索引擎,而ES中不同type下名称相同的filed最终在Lucene中的处理方式是一样的。
  • 两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed,你必须在两个不同的type中定义相同的filed映射。否则,不同type中的相同字段名称就会在处理中出现冲突的情况,导致Lucene处理效率下降。
  • 去掉type就是为了提高ES处理数据的效率。
  1. Elasticsearch 7.x URL中的type参数为可选。比如,索引一个文档不再要求提供文档类型。
  2. Elasticsearch 8.x 不再支持URL中的type参数。
  3. 解决:
    将索引从多类型迁移到单类型,每种类型文档一个独立索引
    将已存在的索引下的类型数据,全部迁移到指定位置即可。详见数据迁移

属性类型

参考:官方属性类型

映射操作

参考:创建映射操作

创建索引映射

PUT /my_index
{
  "mappings": {
    "properties": {
      "age": {
        "type": "integer"
      },
      "email": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      }
    }
  }
}

结果

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

给已有映射增加字段

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.htmladd-field-mapping

PUT /my_index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
  }
}
# 这里的 "index": false,表明新增的字段不能被检索。默认是true
# https://www.elastic.co/guide/en/elasticsearch/reference/7.x/mapping-index.html

更新映射

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.htmlupdate-mapping

对于已经存在的字段映射,我们不能更新。更新必须创建新的索引,进行数据迁移

迁移方式分为两种,一种是7和7之后去掉type的情况,一种是包含type 迁移的情况

无type数据迁移

POST reindex [固定写法]
{
  "source":{
      "index":"twitter"
   },
  "dest":{
      "index":"new_twitters"
   }
}

有type数据迁移

POST reindex [固定写法]
{
  "source":{
      "index":"twitter",
      "twitter":"twitter"
   },
  "dest":{
      "index":"new_twitters"
   }
}

数据迁移实例

对于我们的测试数据,是包含 type 的索引 bank。

现在我们创建新的索引 newbank 并修改一些字段的类型来演示当需要更新映射时的数据迁移操作。

当前数据类型

GET /bank/_mapping

创建新索引,修改字段类型

PUT /newbank
{
  "mappings": {
    "properties": {
      "account_number": {
        "type": "long"
      },
      "address": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "balance": {
        "type": "long"
      },
      "city": {
        "type": "keyword"
      },
      "email": {
        "type": "keyword"
      },
      "employer": {
        "type": "keyword"
      },
      "firstname": {
        "type": "text"
      },
      "gender": {
        "type": "keyword"
      },
      "lastname": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "state": {
        "type": "keyword"
      }
    }
  }
}

数据迁移

POST _reindex
{
  "source": {
    "index": "bank",
    "type": "account"
  },
  "dest": {
    "index": "newbank"
  }
}

迁移后 type 统一为 _doc 移除 type


ElasticSearch分词

一个tokenizer(分词器)接收一个字符流,将之分割为独立的tokens(词元,通常是独立的单词),然后输出tokens流。

例如:whitespace tokenizer遇到空白字符时分割文本。它会将文本“Quick brown fox!”分割为[Quick,brown,fox!]。

该tokenizer(分词器)还负责记录各个terms(词条)的顺序或position位置(用于phrase短语和word proximity词近邻查询),以及term(词条)所代表的原始word(单词)的start(起始)和end(结束)的character offsets(字符串偏移量)(用于高亮显示搜索的内容)。

elasticsearch提供了很多内置的分词器,可以用来构建custom analyzers(自定义分词器)。

POST _analyze
{
  "analyzer": "standard",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

默认的分词器一般都是针对于英文,对于中文我们需要安装额外的分词器来进行分词。

安装IK分词器

IK属于Elasticsearch 的插件,所以 IK 分词器的安装目录是 Elasticsearch 的 plugins 目录

  • 在我们使用Docker启动 Elasticsearch 时,已经将该目录挂载到主机的 /mydata/elasticsearch/plugins 目录。
  • IK 分词器的版本需要跟 Elasticsearch 的版本对应,当前选择的版本为 7.4.2,下载地址为:Github Release 或访问:镜像地址
# 进入挂载的插件目录 /mydata/elasticsearch/plugins
cd /mydata/elasticsearch/plugins
# 安装 wget 下载工具
 yum install -y wget
# 下载对应版本的 IK 分词器(这里是7.4.2)
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip

所以我们之后只需要在挂载的目录/mydata/elasticsearch/plugins下进行操作即可。

解压

# 进入到 es 的插件目录
cd /mydata/elasticsearch/plugins
# 解压到 plugins 目录下的 ik 目录
unzip elasticsearch-analysis-ik-7.4.2.zip -d ik
# 删除下载的压缩包
 rm -f elasticsearch-analysis-ik-7.4.2.zip 
# 修改文件夹访问权限
chmod -R 777 ik/

查看安装的ik插件

# 进入 es 容器内部
docker exec -it elasticsearch /bin/bash
# 进入 es bin 目录
cd /usr/share/elasticsearch/bin
# 执行查看命令  显示 ik
elasticsearch-plugin list
# 退出容器
exit
# 重启 Elasticsearch
docker restart elasticsearch

测试 ik 分词器

GET my_index/_analyze
{
   "analyzer": "ik_max_word", 
   "text":"我是湖南岳阳人"
}


这里对于默认词库中没有的词,不会有词语的组合,所以我们可以通过配置自定义词库或远程词库来实现对词库的扩展

自定义分词库

我们在 nginx 中自定义分词文件,通过配置 es 的 ik 配置文件来远程调用 nginx 中的分词文件来实现自定义扩展词库

docker安装nginx

1.创建要挂载的配置目录

mkdir -p /mydata/nginx/conf

2.启动临时nginx容器

docker run -p 80:80 --name nginx -d nginx:1.10
  1. 拷贝出 Nginx 容器的配置
# 将nginx容器中的nginx目录复制到本机的/mydata/nginx/conf目录
docker container cp nginx:/etc/nginx /mydata/nginx/conf
# 复制的是nginx目录,将该目录的所有文件移动到 conf 目录
mv /mydata/nginx/conf/nginx/* /mydata/nginx/conf/
# 删除多余的 /mydata/nginx/conf/nginx目录
rm -rf /mydata/nginx/conf/nginx
  1. 删除临时nginx容器
# 停止运行 nginx 容器
docker stop nginx
# 删除 nginx 容器
docker rm nginx

5.启动 nginx 容器

docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf/:/etc/nginx \
-d nginx:1.10

6.nginx 随 Docker 启动

docker update nginx --restart=always

7.测试 nginx

echo '<h1>谷粒商城源码</h1>' \
>/mydata/nginx/html/index.html

访问:192.168.195.100

nginx 中自定义分词文件

vim /mydata/nginx/html/fenci.txt


给 es 配置自定义词库

# 1. 打开并编辑 ik 插件配置文件
vim /mydata/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml

修改内容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 -->
        <entry key="ext_dict"></entry>
         <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords"></entry>
        <!--用户可以在这里配置远程扩展字典 -->
        <entry key="remote_ext_dict">http://192.168.195.100/fenci.txt</entry>
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

重启 elasticsearch 容器

docker restart elasticsearch

测试自定义词库

GET my_index/_analyze
{
   "analyzer": "ik_max_word", 
   "text":"我是湖南岳阳人"
}
相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
Web App开发 自然语言处理 Java
Elasticsearch简介及安装
Elasticsearch简介及安装
290 0
|
存储 数据可视化 搜索推荐
分布式系列教程(26) -分布式日志搜集工具Elasticsearch简介
分布式系列教程(26) -分布式日志搜集工具Elasticsearch简介
111 0
|
自然语言处理 Rust 搜索推荐
elasticsearch简介
elasticsearch简介
78 0
|
6月前
|
存储 自然语言处理 Java
Elasticsearch全文搜索技术之二kibana的简介和使用
Elasticsearch全文搜索技术之二kibana的简介和使用
87 2
|
存储 消息中间件 监控
【ElasticSearch】ELK简介
【ElasticSearch】ELK简介
172 2
【ElasticSearch】ELK简介
|
6月前
|
存储 自然语言处理 数据挖掘
01_Elasticsearch简介与环境搭建
01_Elasticsearch简介与环境搭建
88 0
|
关系型数据库 MySQL Docker
ElasticSearch简介
ElasticSearch简介
|
存储 机器学习/深度学习 SQL
阿里云 Elasticsearch简介和购买流程
开源Elasticsearch是一个基于Lucene的实时分布式的搜索与分析引擎,是遵从Apache开源条款的一款开源产品,是当前主流的企业级搜索引擎。作为一款基于RESTful API的分布式服务,Elasticsearch可以快速地、近乎于准实时地存储、查询和分析超大数据集,通常被用来作为构建复杂查询特性和需求强大应用的基础引擎或技术。
|
存储 自然语言处理 前端开发
Elasticsearch倒排索引(一)简介
Elasticsearch倒排索引(一)简介
132 0
|
存储 缓存 JSON
elasticsearch简介安装使用事例大全
Elasticsearch是面向文档(document oriented)的,可以存储整个对象或文档(document)、索引(index)每个文档的内容,可以快速搜索。Elasticsearch中,可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。
186 0
elasticsearch简介安装使用事例大全
下一篇
无影云桌面