elasticsearch

Elasticsearch是一个基于Lucene的搜索服务器,也是属于NoSQL阵营的数据库。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口提供给我们操作的。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。除了es以外, Sphinx 、迅搜、Zebra、Solr 、Whoosh。

官网:https://www.elastic.co/cn/elasticsearch/

中文文档:https://www.elastic.co/guide/cn/index.html

最新版本:8.0 版本。目前在市面上常用的版本是6.x和7.x,甚至是5.x。

安装elasticsearch

支持单点部署和集群部署。

# 从课件的素材中找到es的镜像压缩包,复制到ubuntu桌面下,执行以下命令
# sudo docker load -i ~/Desktop/elasticsearch.7.13.4.tar.gz
podman load -i ~/Desktop/elasticsearch.7.13.4.tar.gz
# 也可以不执行上面的操作,直接run可以让docker从官网拉取es镜像。

# 直接执行这句也成,即使本地没有该版本,他也会去远程拉取!
# sudo docker run --name elasticsearch --restart=always -d -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -e "discovery.type=single-node" elasticsearch:7.13.4

podman run --name elasticsearch -d -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" elasticsearch:7.13.4

参数说明

--name elasticsearch  
       设置当前容器的容器名称为elasticsearch
--restart=always
       设置容器开机自启,即便物理机关机重启了,docker在启动以后也会自动帮我们把当前容器启动起来。
-d     设置当前容器为守护式容器,在后台运行
-p 9200:9200
       设置端口影射,<物理机端口>:<容器端口>
       表示访问了当前物理机的9200,相当于访问了当前容器的9200端口
-p 9300:9300
       设置端口影射,<物理机端口>:<容器端口>
       表示访问了当前物理机的9300,相当于访问了当前容器的9300端口
       es提供的9200是restful api接口的端口,以http形式访问,9300端口是Api对服务器的管理端口。
-e ES_JAVA_OPTS="-Xms256m -Xmx256m"
       设置环境变量,变量名为ES_JAVA_OPTS,这个变量是启动elasticsearch的关键。
       表示设置java环境的最小和最大使用内存,内存不足,elasticsearch是无法启动的,所以此处设置为最小内存必须在256M以上
-e "discovery.type=single-node"
       设置环境变量,变量名discovery.type
       discovery.type 表示当前elasticsearch的运作模式为single-node,表示单机部署/单点部署
elasticsearch:7.13.4
       设置当前容器的镜像名和版本号

浏览器访问:http://127.0.0.1:9200

要基于es实现全文搜索,可以参考以下文档了解关于全文搜索的内容。

https://www.elastic.co/guide/cn/elasticsearch/guide/current/full-text-search.html

全文搜索的实现,必须依靠es内部调用分词器对语句进行词性分析,拆词,给每一个单词构建一个索引。

所以默认情况下,es只提供了标准分析器,和简单分析器,这几块分词器都是只能针对英文进行分词。

IK中文分词器

默认情况下,elasticsearch是外国开发的,所以本身对于中文分词构建分词索引的支持是不行的。所以我们需要在elasticsearch软件中新增一个支持中文索引和中文分词的插件,叫ik分词器。

注意:IK分词器插件的版本必须与elasticsearch的版本号同步。否则安装失败!

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

把IK分词器解压并复制到elasticsearch容器的/usr/share/elasticsearch/plugins目录下

unzip ~/Desktop/elasticsearch-analysis-ik-7.13.4.zip -d ~/Desktop/ik-7.13.4
# unzip /Users/mosson/Desktop/elasticsearch-analysis-ik-7.13.4.zip -d /Users/mosson/Desktop/ik-7.13.4
podman cp ~/Desktop/ik-7.13.4 elasticsearch:/usr/share/elasticsearch/plugins
docker cp /Users/mosson/Desktop/ik-7.13.4 elasticsearch:/usr/share/elasticsearch/plugins
podman stop elasticsearch
podman start elasticsearch

注意

IK中文分词器安装方式:进入容器内部安装IK分词器
1.进入elasticsearch容器
docker 
2.进入到elasticsearch的bin目录
sh-4.4# cd /usr/share/elasticsearch/bin/
3.下载固定版本的ik分词器
sh-4.4# ./elasticsearch-plugin install  https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.13.4/elasticsearch-analysis-ik-7.13.4.zip
4. 查看分词器是否安装成功
sh-4.4# elasticsearch-plugin list
analysis-ik

注意:elasticsearch内部极其复杂,所以启动容器以后需要等待1分钟左右才对外提供搜索服务。

接下来,我们就可以通过postman测试。

注意:es提供的9200是restful api接口的端口,以http形式访问,9300端口是Api对服务器的管理端口。

post http://127.0.0.1:9200/_analyze?pretty

基于智能分词模式来查询分析词性,json数据

{
   "analyzer":"ik_smart",
   "text":"我是中国人"    
}

基于最大分词模式来查询分析词性,json数据

{
   "analyzer":"ik_max_word",
   "text":"我是中国人"  
}

elasticsearch-head

elasticsearch-head 是用于监控 Elasticsearch 状态的客户端插件,包括数据可视化、执行增删改查操作等。不过开发中,我们一般使用elasticsearch-head来查看elasticsearch的数据而已,真正对elasticsearch进行增删查改操作一般我们使用kibana或者postman或者编程语言实现的客户端来完成。

我们可以通过docker安装elasticsearch-head来对Elasticsearch 进行界面化管理。

# 拉取镜像
# sudo docker pull mobz/elasticsearch-head:5
podman pull mobz/elasticsearch-head:5

# 创建容器
# sudo docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5
podman create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5

# 启动容器
# sudo docker start elasticsearch-head
podman start elasticsearch-head

访问elasticsearch-head:http://127.0.0.1:9100/,会发现无法连接elasticsearch,原因是因为跨域问题导致。

解决方案就是修改容器elasticsearch中的elasticsearch.yml文件增加跨域支持即可。

# 将docker里面的内容复制到本地的桌面上
# sudo docker cp elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml /Users/mosson/Desktop/elasticsearch.yml
podman cp elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml ~/Desktop/elasticsearch.yml

修改elasticsearch.yml内容,增加跨域支持,如下:

cluster.name: "docker-cluster"
network.host: 0.0.0.0
http.cors.enabled: true 
http.cors.allow-origin: "*"

把elasticsearch.yml文件再次复制到容器elasticsearch中,并重启容器elasticsearch。

# sudo docker cp /Users/mosson/Desktop/elasticsearch.yml elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml
podman cp ~/Desktop/elasticsearch.yml elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml

修改容器elasticsearch-head的vendor.js让elasticsearch-head界面可以操作elasticsearch

# sudo docker cp elasticsearch-head:/usr/src/app/_site/vendor.js /Users/mosson/Desktop//vendor.js
podman cp elasticsearch-head:/usr/src/app/_site/vendor.js ~/Desktop/vendor.js

修改vendor.js内容,把6886行与7573行所在的"application/x-www-form-urlencoded"替换成"application/json;charset=UTF-8",并保存文件,复制回容器elasticsearch-head中。

# sudo docker cp /Users/mosson/Desktop//vendor.js  elasticsearch-head:/usr/src/app/_site/vendor.js
podman cp ~/Desktop/vendor.js elasticsearch-head:/usr/src/app/_site/vendor.js

重启elasticsearch和elasticsearch-head容器

# sudo docker stop elasticsearch
# sudo docker start elasticsearch
podman stop elasticsearch
podman start elasticsearch

# sudo docker stop elasticsearch-head
# sudo docker start elasticsearch-head
podman stop elasticsearch-head
podman start elasticsearch-head

kibana

Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。

kibana的版本必须与Elasticsearch一致,所以我们安装的kibana也是7.13.4版本。

# sudo docker pull kibana:7.13.4
# sudo docker run -d --name kibana -e ELASTICSEARCH_URL=http://127.0.0.1:9200 -p 5601:5601 --restart=always kibana:7.13.4

podman pull kibana:7.13.4
podman run -d --name kibana -p 5601:5601 kibana:7.13.4

修改让kibana能访问到Elasticsearch并完成汉化操作

# sudo docker exec -it kibana bash
podman  exec -it kibana bash
vi config/kibana.yml

kibana.yml中的内容需改如下:

#
# ** THIS IS AN AUTO-GENERATED FILE **
#

# Default Kibana configuration for docker target
server.host: "0.0.0.0"
# 注意:此处的IP地址替换为网卡地址,不能使用127.0.0.1或localhost,否则无法访问,可以通过ip a来查看
elasticsearch.hosts: [ "http://IP地址:9200" ]
monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: "zh-CN"

修改完成以后,退出当前kibana容器,并重启kibana容器即可。

# sudo docker stop kibana
# sudo docker start kibana
podman stop kibana
podman start kibana

等待1分钟左右,打开浏览器直接访问http://127.0.0.1:5601,即可。

快速入门

核心概念

Elasticsearch是面向文档的,以json格式存储数据的NoSQL数据库,也是一个全文搜索引擎。

Elasticsearch 关系型数据库(如Mysql)
索引(Index) 数据库(Database)
类型(Type) 表(Table)
文档(Document) 行,记录(Row,Record)
字段(Field) 列,字段(Column,Field)
映射(Mapping) 约束(Schema)

注意:es中的类型在es7.x版本中已经没有,在后面的8.x版本中被彻底删除掉。

在 7.x 及之后的版本中,数据存储结构从传统的 索引/类型/文档 三层模型简化为了 索引/文档 两层模型。

为什么移除类型(Type)?

在底层,同一个索引中的不同类型的数据最终会存储在同一个倒排索引中,不同类型中同名字段的数据结构必须一致,这在实际使用中带来了很多混淆和限制。移除类型简化了数据模型,并使其更符合 Lucene 的底层实现。

倒排索引

倒排索引(Inverted Index),是Elasticsearch中的索引工作机制。倒排索引是区别于正排索引的概念:

  • 正排索引:是以文档对象的唯一ID作为索引,以文档内容作为记录。
  • 倒排索引:指的是将文档内容中的单词作为索引,将包含该词的文档ID作为记录。

在这里插入图片描述

Elasticsearch的工作流程如下,因为使用倒排索引产生的文档记录要比mysql数据行少多了,所以会比较快。

在这里插入图片描述

基本使用

es提供了retfulAPI风格操作接口给开发者对索引、类型、文档、字段、映射等进行增删查改操作。

索引操作
创建索引

请求格式:

PUT /索引名称
类型映射[了解]

相当于在mysql中创建数据表时的字段类型

# 索引名称必须已经存在!
POST /索引名称/类型名称
{
    "类型名称": { // 映射的类型名称
        "properties": {  // 索引中文档的属性
            "字段名": {           // 属性名或字段名
                "type": "text"   // 属性值类型或字段类型,text表示文本,如商品标题
                "index": "analyzed",    // 索引类型
                "analyzer": "ik_smart"  // 设置使用的分词器[标准分词]
            },
            "字段名": {           // 属性名或字段名
                "type": "text"   // 属性值类型或字段类型,text表示文本,如商品标题
                "index": "analyzed",    // 索引类型
                "analyzer": "standard"  // 设置使用的分词器
            },
            "字段名": {           // 属性名或字段名
                "type": "text"   // 属性值类型或字段类型,text表示文本,如商品标题
                "index": "analyzed",    // 索引类型
                "analyzer": "standard"  // 设置使用的分词器
            }
        }
    }
}

kinana操作:

POST /indexes1/goods
{
  "mapping": {
    "properties": {
      "id": {
        "type": "long"
      },
      "name": {
        "type": "text",
        "index": "analyzed",
        "analyzer": "ik_max_word"
      },
      "price":{
        "type": "float"
      },
      "created_time":{
          "type": "date",
          "format":"yyyy-MM-dd HH:mm:ss"
      }
    }
  }
}

新版es操作

PUT /indexes1
{
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "name": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "price": {
        "type": "float"
      },
      "created_time": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      }
    }
  }
}
数据类型[了解]

elasticsearch中支持的常见字段数据类型:

类型 描述
text 字符串类型,可以模糊查询, 可以分词查询,不能聚合、排序
keyword 字符串类型,只能精准查询, 不能分词查询,可以聚合、排序
long 有符号的64位整数, 范围:[−263 ~ 263-1]
Integer 有符号的32位整数, 范围: [−231 ~ 231-1]
short 有符号的16位整数, 范围: [-32768 ~ 32767]
byte 有符号的8位整数, 范围: [-128 ~ 127]
float 32位单精度浮点数
double 64位双精度浮点数
boolean 布尔类型,支持使用字符串,数字等零值表示true/false
date 日期类型,
date_nanos 日期纳秒类型,
binary 二进制类型,Base64编码字符串的二进制值
Range 范围类型,有integer_range, float_range, long_range, double_range, date_range等
array 数组类型,ES中没有专门的数组类型, 直接使用[ ]定义即可,所有的成员的值必须是同一种数据类型
object 对象类型,以json对象为结构

这里写个小例子,如果指定文档id,当再次写入数据时就是更新,如果没有指定文档id,那么在写入数据时会生成一个随机id,只要id不重复,相同的数据可以一直写入

// 这里指定文档id为01
PUT /users/_doc/01
{
  "name": "chens",
  "age": 12,
  "sex": "male"
}

// 在下面指定id是没用的,它会生成随机id
POST /users/_doc
{
  "id": "02",
  "name": "cs02",
  "age": 13,
  "sex": "male"
}

// 查询索引的所有文档
GET /users/_search

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "3KFMTJkB3S2Stzq3SYGo",
        "_score" : 1.0,
        "_source" : {
          "id" : "02",
          "name" : "cs02",
          "age" : 13,
          "sex" : "male"
        }
      },
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "3aFMTJkB3S2Stzq3rIHc",
        "_score" : 1.0,
        "_source" : {
          "id" : "02",
          "name" : "cs02",
          "age" : 13,
          "sex" : "male"
        }
      },
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "01",
        "_score" : 1.0,
        "_source" : {
          "name" : "chens",
          "age" : 12,
          "sex" : "male"
        }
      }
    ]
  }
}

使用默认类型_doc代替映射的创建,es会内部自动推断字段类型。

PUT /indexes2/_doc/文档ID
{
    "name": "商品的标题",
    "price": 18,
    "created_time": "2022-01-10 22:00:31"
}

_doc 就是默认类型(default type),type在8.x版本会被彻底删除,以后使用默认类型_doc替代即可。

查看索引
GET /_cat/indices      // 查看所有的索引信息
GET /索引名称           // 查看指定名称的索引结构信息
删除索引
DELETE /索引名称
文档操作
请求方法/method uri地址 描述
PUT(创建,修改) /索引名称/_doc/文档id 创建文档(指定文档id)
POST(创建) /索引名称/_doc/文档id 创建文档,如果uri地址只是以_doc结尾,文档id是随机生成的)
POST(修改) /索引名称/_doc/文档id/_update 修改文档
DELETE(删除) /索引名称/_doc/文档id 删除文档
GET(查询) /索引名称/_doc/文档id 查询文档通过文档ID
POST(查询) /索引名称/_doc/文档id/_search 查询所有数据
添加文档
PUT /users/_doc/01
{
  "name": "chens",
  "age": 12,
  "sex": "male"
}
修改文档
PUT /users/_doc/01
{
  "name": "chens-1",
  "age": 13,
  "sex": "male"
}
删除文档
DELETE /索引名称
查询文档

查询文档有三种方式:

  • 主键查询:根据文档id查询
  • 精确查询:根据关键词查询,也叫term查询 浪潮之巅 -> 浪潮之巅
  • 匹配查询:根据输入的内容先对内容进行分词,再进行分词匹配查询 浪潮 -> 浪潮之巅
准备数据
POST /indexes4/_doc/1
{
  "created_time":"2022-04-01",
  "title":"浪潮之巅",
  "content":"一部IT人非读不可,而非IT人也应该阅读的作品,讲故事的经典作品",
  "author_id": 119
}

POST /indexes4/_doc/2
{
  "post_date":"2022-03-12",
  "title":"人月神话",
  "content":"一部IT人非读不可,而非IT人也应该阅读的作品,讲人与团队关系作品",
  "author_id": 120
}

POST /indexes4/_doc/3
{
  "post_date":"2021-12-16",
  "title":"代码之髓",
  "content":"小日子过得不错的人写的作品,对代码中各种语言结构的实现进行揭秘",
  "author_id": 110
}
主键查询
# GET /索引名称/_doc/1
GET /indexes4/_doc/3
# 查询多个指定 ID 的文档
GET /your_index/_search
{
  "query": {
    "ids": {
      "values": ["id1", "id2", "id3"]
    }
  }
}
精确查询
# 查询 title.keyword 字段精确等于 "代码之髓" 的文档
GET /your_index/_search
{
  "query": {
    "term": {
      "title.keyword": {
        "value": "代码之髓"
      }
    }
  }
}

多值精确匹配

# 查询 status 字段值为 "active" 或 "pending" 的文档
GET /your_index/_search
{
  "query": {
    "terms": {
      "status.keyword": ["active", "pending"]
    }
  }
}

数值范围查询

# 查询价格在 100 到 500 之间的商品
GET /your_index/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 500
      }
    }
  }
}
匹配查询,模糊查询

查询所有

POST /索引名称/_search
{
    "query": {
        "match_all": {}
     },
     "sort": [  // 排序,注意:text无法使用排序,keyword才支持
          // {"字段名":"排序规则,asc正序, desc倒序"}
          {"title": "asc" }
     ],
      "from": 0,                       // 分页,查询起始下标
      "size": 2,                       // 指定返回结果数量
      "_source": ["title", "content"]  // 指定只返回部分字段
}

kibana操作:

POST /indexes4/_search
{
  "query": {
    "match_all": {}
  },
  "sort": {
    "author_id": "desc"
  },
  "from": 0,
  "size": 4,
  "_source": ["title"]
}

条件查询

格式:

POST /索引名称/_search
{
    "query": {
        "match": {
          "字段名": "查询条件值"
        }
    }
}
POST /indexes4/_search
{
    "query": {
        "match": {
          "content": "非读不可"
        }
    }
}

多字段模糊查询

# 在 title 和 description 字段中搜索包含 "智能手机" 的文档
GET /your_index/_search
{
  "query": {
    "multi_match": {
      "query": "智能手机",
      "fields": ["title", "description"]
    }
  }
}

模糊匹配(容错查询),这个不好用

# 使用模糊查询,允许有一定拼写错误或差异
GET /your_index/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "智能手机",
        "fuzziness": "AUTO"  // 自动根据词长确定允许的编辑距离
      }
    }
  }
}

通配符查询

# 使用通配符查询
GET /your_index/_search
{
  "query": {
    "wildcard": {
      "name.keyword": {
        "value": "智能*"  // 匹配以"智能"开头的任何词
      }
    }
  }
}

查询优化技巧

指定返回字段

# 只返回特定字段,减少网络传输
GET /your_index/_search
{
  "_source": ["name", "price", "category"],
  "query": {
    "match": {
      "name": "手机"
    }
  }
}

分页和排序

# 分页查询并按价格降序排序
GET /your_index/_search
{
  "query": {
    "match": {
      "name": "手机"
    }
  },
  "from": 0,
  "size": 10,
  "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐