(一)、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概念
- 关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用,但ES中不是这样的。elasticsearch是基于Lucene开发的搜索引擎,而ES中不同type下名称相同的filed最终在Lucene中的处理方式是一样的。
-
- 两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed,你必须在两个不同的type中定义相同的filed映射。否则,不同type中的相同字段名称就会在处理中出现冲突的情况,导致Lucene处理效率下降。
- 去掉type就是为了提高ES处理数据的效率。
-
Elasticsearch 7.x URL中的type参数为可选。比如,索引一个文档不再要求提供文档类型。
-
Elasticsearch 8.x 不再支持URL中的type参数。
-
解决:
将索引从多类型迁移到单类型,每种类型文档一个独立索引
将已存在的索引下的类型数据,全部迁移到指定位置即可。详见数据迁移
属性类型
参考:官方属性类型
映射操作
参考:创建映射操作
创建索引映射
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.html#add-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.html#update-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
- 拷贝出 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
- 删除临时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
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":"我是湖南岳阳人"
}