1 安装es
1.1 拉取镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/elasticsearch:7.17.3
1.2 运行容器
运行elasticsearch容器,挂载的目录给更高的权限,否则可能会因为目录权限问题导致启动失败:
docker run -d \
--name es \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v ./es-data:/usr/share/elasticsearch/data \
-v ./es-logs:/usr/share/elasticsearch/logs \
-v ./es-plugins:/usr/share/elasticsearch/plugins \
--privileged \
-p 9200:9200 \
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/elasticsearch:7.17.3
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
:内存大小-e "discovery.type=single-node"
:非集群模式-v es-data:/usr/share/elasticsearch/data
:挂载逻辑卷,绑定es的数据目录-v es-logs:/usr/share/elasticsearch/logs
:挂载逻辑卷,绑定es的日志目录-v es-plugins:/usr/share/elasticsearch/plugins
:挂载逻辑卷,绑定es的插件目录--privileged
:授予逻辑卷访问权-p 9200:9200
:端口映射配置
使用浏览器访问 服务器地址:9200,可看到elasticsearch的响应结果:
2 es基础操作
ES集群可以包含多个索引(indices)(数据库),每一个索引库中可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。
2.1 添加文档
post请求可以向es中添加文档,会自动生成文档id。
POST {index}/{type}
{
JSON,文档内容
}
2.2 指定id添加或更新文档
put请求可以更新指定id的文档内容,当没有对应的内容时则会创建文档。
PUT {index}/{type}/{id}
{
JSON,文档内容
}
2.3 删除文档
delete请求可以删除文档,可以指定id。
DELETE {index}/{type}/{id}
2.4 查询文档
get请求用于查询文档信息。
GET {index}/{info}/_search
3 mapping映射
get索引可以查看es索引信息。其中mapping类似于数据库中的表结构定义 schema
,它有以下几个作用:
- 定义索引中的字段的名称
- 定义字段的数据类型,比如字符串、数字、布尔
- 字段,倒排索引的相关配置,比如设置某个字段为不被索引、记录 position 等
GET {index}
3.1 字段数据类型
3.1.1 核心类型
核心类型可以划分为字符串类型、数字类型、日期类型、布尔类型、基于 BASE64 的二进制类型、范围类型。
3.1.1.1 字符串类型
在 ES 7.x 有两种字符串类型:text
和 keyword。
text
类型适用于需要被全文检索的字段,例如新闻正文、邮件内容等比较长的文字,text
类型会被 Lucene 分词器(Analyzer)处理为一个个词项,并使用 Lucene 倒排索引存储,text 字段不能被用于排序,如果需要使用该类型的字段只需要在定义映射时指定 JSON 中对应字段的type
为text
。keyword
适合简短、结构化字符串,例如主机名、姓名、商品名称等,可以用于过滤、排序、聚合检索,也可以用于精确查询。
3.1.1.2 数字类型
数字类型分为 long、integer、short、byte、double、float、half_float、scaled_float
。数字类型的字段在满足需求的前提下应当尽量选择范围较小的数据类型,字段长度越短,搜索效率越高,对于浮点数,可以优先考虑使用 scaled_float
类型,该类型可以通过缩放因子来精确浮点数,例如 12.34 可以转换为 1234 来存储。
3.1.1.3 日期类型
在 ES 中日期可以为以下形式:
- 格式化的日期字符串,例如 2020-03-17 00:00、2020/03/17
- 时间戳(和 1970-01-01 00:00:00 UTC 的差值),单位毫秒或者秒
即使是格式化的日期字符串,ES 底层依然采用的是时间戳的形式存储。
3.1.1.4 布尔类型
JSON 文档中同样存在布尔类型,不过 JSON 字符串类型也可以被 ES 转换为布尔类型存储,前提是字符串的取值为 true
或者 false
,布尔类型常用于检索中的过滤条件。
3.1.1.5 二进制类型
二进制类型 binary
接受 BASE64 编码的字符串,默认 store
属性为 false
,并且不可以被搜索。
3.1.1.6 范围类型
范围类型可以用来表达一个数据的区间,可以分为5种:integer_range、float_range、long_range、double_range
以及 date_range
。
3.1.2 复杂类型
复杂类型主要有对象类型(object)和嵌套类型(nested)。
3.1.2.1 对象类型
JSON 字符串允许嵌套对象,一个文档可以嵌套多个、多层对象。可以通过对象类型来存储二级文档,不过由于 Lucene 并没有内部对象的概念,ES 会将原 JSON 文档扁平化,例如文档:
{
"name": {
"first": "wu",
"last": "px"
}
}
实际上 ES 会将其转换为以下格式,并通过 Lucene 存储,即使 name
是 object
类型:
{
"name.first": "wu",
"name.last": "px"
}
3.1.2.2 嵌套类型
嵌套类型可以看成是一个特殊的对象类型,可以让对象数组独立检索,例如文档:
{
"group": "users",
"username": [
{ "first": "wu", "last": "px"},
{ "first": "hu", "last": "xy"},
{ "first": "wu", "last": "mx"}
]
}
username字段是一个 JSON 数组,并且每个数组对象都是一个 JSON 对象。如果将username设置为对象类型,那么 ES 会将其转换为:
{
"group": "users",
"username.first": ["wu", "hu", "wu"],
"username.last": ["px", "xy", "mx"]
}
可以看出转换后的 JSON 文档中 first
和 last
的关联丢失了,如果尝试搜索 first
为 wu
,last
为 xy
的文档,那么成功会检索出上述文档,但是 wu
和 xy
在原 JSON 文档中并不属于同一个 JSON 对象,应当是不匹配的,即检索不出任何结果。
嵌套类型就是为了解决这种问题的,嵌套类型将数组中的每个 JSON 对象作为独立的隐藏文档来存储,每个嵌套的对象都能够独立地被搜索,所以上述案例中虽然表面上只有 1 个文档,但实际上是存储了 4 个文档。
3.1.3 地理类型
地理类型字段分为两种:经纬度类型和地理区域类型。
3.1.3.1 经纬度类型
经纬度类型字段(geo_point)可以存储经纬度相关信息,通过地理类型的字段,可以用来实现诸如查找在指定地理区域内相关的文档、根据距离排序、根据地理位置修改评分规则等需求。
3.1.3.2 地理区域类型
经纬度类型可以表达一个点,而 geo_shape
类型可以表达一块地理区域,区域的形状可以是任意多边形,也可以是点、线、面、多点、多线、多面等几何类型。
3.1.4 特殊类型
特殊类型包括 IP 类型、过滤器类型、Join 类型、别名类型等,在这里简单介绍下 IP 类型和 Join 类型,其他特殊类型可以查看官方文档。
3.1.4.1 IP 类型
IP 类型的字段可以用来存储 IPv4 或者 IPv6 地址,如果需要存储 IP 类型的字段,需要手动定义映射:
{
"mappings": {
"properties": {
"my_ip": {
"type": "ip"
}
}
}
}
3.1.4.2 Join 类型
Join 类型是 ES 6.x 引入的类型,以取代淘汰的 _parent
元字段,用来实现文档的一对一、一对多的关系,主要用来做父子查询。Join 类型的 Mapping 如下:
PUT my_index
{
"mappings": {
"properties": {
"my_join_field": {
"type": "join",
"relations": {
"question": "answer"
}
}
}
}
}
其中,my_join_field
为 Join 类型字段的名称;relations
指定关系:question
是 answer
的父类。例如定义一个 ID 为 1 的父文档:
PUT my_join_index/1?refresh
{
"text": "This is a question",
"my_join_field": "question"
}
接下来定义一个子文档,该文档指定了父文档 ID 为 1:
PUT my_join_index/_doc/2?routing=1&refresh
{
"text": "This is an answer",
"my_join_field": {
"name": "answer",
"parent": "1"
}
}
3.2 类型自动识别
ES 类型的自动识别是基于 JSON 的格式,如果输入的是 JSON 是字符串且格式为日期格式,ES 会自动设置成 Date
类型;当输入的字符串是数字的时候,ES 默认会当成字符串来处理,可以通过设置来转换成合适的类型;如果输入的是 Text
字段的时候,ES 会自动增加 keyword
子字段,还有一些自动识别如下图所示:
3.3 Mapping 设置
在创建一个索引的时候,可以对 dynamic
进行设置,默认为true,可以设成 false
、true
或者 strict
。
PUT users
{
"mappings": {
"_doc": {
"dynamic": false
}
}
}
比如一个新的文档,这个文档包含一个字段,当 Dynamic 设置为 true
时,这个文档可以被索引进 ES,这个字段也可以被索引,也就是这个字段可以被搜索,Mapping 也同时被更新;当 dynamic 被设置为 false
时候,存在新增字段的数据写入,该数据可以被索引,但是新增字段被丢弃;当设置成 strict
模式时候,数据写入直接出错。
3.4 修改 Mapping 字段类型
如果是新增加的字段,根据 Dynamic 的设置分为以下三种状况:
- 当 Dynamic 设置为
true
时,一旦有新增字段的文档写入,Mapping 也同时被更新。 - 当 Dynamic 设置为
false
时,索引的 Mapping 是不会被更新的,新增字段的数据无法被索引,也就是无法被搜索,但是信息会出现在_source
中。 - 当 Dynamic 设置为
strict
时,文档写入会失败。
另外一种是字段已经存在,这种情况下,ES 是不允许修改字段的类型的,因为 ES 是根据 Lucene 实现的倒排索引,一旦生成后就不允许修改,如果希望改变字段类型,必须使用 Reindex API 重建索引。不能修改的原因是如果修改了字段的数据类型,会导致已被索引的无法被搜索,但是如果是增加新的字段,就不会有这样的影响。