一、概述
Elasticsearch(以下简称es)是建立在全文搜索引擎库 Apache Lucene™ 基础上的实时分布式搜索分析引擎。它通过隐藏 Lucene 的复杂性,提供一套简单的 RESTful API。它不仅有Lucene的能力,还是一个分布式的实时文档存储,每个字段可以被索引和搜索、还是一个分布式实时分析搜索引擎、能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。es常被用作全文检索、结构化搜索、分析以及这三个功能的组合。帮助文档请参考:
es官网:https://www.elastic.co/cn/
es中文官网:https://www.elastic.co/cn/
es中文文档:https://www.elastic.co/guide/cn/index.html
es参考手册:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
es Github源码:https://github.com/elastic/elasticsearch
es是面向文档的,对文档而不是像对结构化数据那样的行列数据进行索引、检索、排序和过滤。它在存储整个对象或文档的同时会索引每个文档的内容,使之可以被检索。正因为es是面向文档的,其文档内部的结构关系并没有破坏,才使es能支持复杂的全文检索。es中很重要的一个数据结构是倒排索引(反向索引),它把要搜索的词作为key,把包含该词的文档作为value,由于包含该词的文档不止一个,所以这个value是文档的数组。
一个es集群可以包含多个节点,每个节点可以包含多个索引。相应的每个索引可以包含多个类型(高版本已逐渐取消多类型) 。 每个类型存储着多个文档 ,每个文档又有多个字段(在es中称为“域”),每个域都有自己的类型。需要注意的是同一索引的不同类型下文档的域必须相同。
每个索引都有一个映射mappings,该映射确定如何对文档建立索引。一个映射mappings中主要包含两部分:
1、元字段:主要包括每个文档的:_index、_type、_id和_source;
2、properties属性列表:其中定义了文档中的属性(可以理解为字段,又叫域),每个属性都有自己的类型。常用类型有:
映射类型 | 说明 |
---|---|
string | 字符串,es5后被移除,被拆成keyword和text |
keyword | 精确匹配的字符串,不会做分词处理 |
text | 全文检索的字符串,分析器会做分词处理 |
byte、short、integer、long | 整型 |
float、double | 浮点数 |
boolean | 布尔型 |
date | 日期 |
integer_range、float_range、long_range、double_range、date_range | 表示对应类型的范围 |
多层级对象 | 通过properties将若干简单域组成上级域的属性 |
nested | 数组 |
completion | 用于支持Completion Suggester |
1>多层级对象示例:
//在mappings中定义为:
{
"properties": {
"name": {
"properties": {
"first_name": {
"type": "keyword"
},
"middle_name": {
"type": "keyword"
},
"last_name": {
"type": "text"
}
}
}
}
}
//实际存储的数据示例为:
{
"_source": {
"name": {
"last_name": "Clinton",
"middle_name": "Jefferson",
"first_name": "William"
}
}
}
2>nested示例:
//在mappings中定义为:
{
"properties": {
"scores": {
"type": "nested",
"properties": {
"chinese": {
"type": "long"
},
"math": {
"type": "long"
}
}
}
}
}
//实际存储的数据示例为:
{
"_source": {
"scores": [
{
"chinese": 100,
"math": 99
},
{
"chinese": 99,
"math": 98
},
{
"chinese": 100,
"math": 100
}
]
}
}
更多字段类型请参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/mapping.html
二、集群和节点
集群(cluster)由一个或多个拥有相同cluster.name配置的节点(实例)组成, 它们共同承担数据和负载的压力。当有新节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。节点有主节点和非主节点之分,主节点负责管理集群范围内所有的变更。
分片(_shards)是数据的容器,被分配到集群内的各个节点里。分片其实就是Lucene实例,所以一个分片就是一个完整的搜索引擎。分片有主分片和副本分片之分,索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。实际上最大数据量还跟硬件、文档的大小和复杂程度、索引和查询文档的方式以及期望的响应时长等有关。主分片的数量在创建时被确定并且不能改变,因为每个文档存储在哪个主分片上是根据公式:shard = hash(routing) % number_of_primary_shards确定的,如果number_of_primary_shards发生了变化,原本保存的文档在主分片的位置就错误了。副本分片只是主分片的拷贝, 作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。
elasticsearch.yml配置说明如下:
配置项 | 说明 |
---|---|
cluster.name | 集群名称 |
node.name | 节点名称 |
node.master | 是否是主节点。es默认集群中的第一台机器为主节点,如果这台机挂了就会重新选主节点 |
node.data | 该节点是否存储索引数据,默认为true |
index.number_of_shards | 索引的主分片个数,默认为5 |
index.number_of_replicas | 索引的副本分片个数,默认为1 |
path.conf | 配置文件的存储路径,默认是es根目录下的config文件夹 |
path.data | 索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开 |
path.work | 临时文件的存储路径,默认是es根目录下的work文件夹 |
path.logs | 日志文件的存储路径,默认是es根目录下的logs文件夹 |
path.plugins | 插件的存放路径,默认是es根目录下的plugins文件夹 |
bootstrap.mlockall | 是否锁住内存,因为当jvm开始swapping时es的效率 会降低,所以要保证它不swap |
network.bind_host | 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0 |
network.publish_host | 设置其它节点和该节点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址 |
network.host | 同时设置bind_host和publish_host |
transport.tcp.port | 节点间交互的tcp端口,默认是9300 |
transport.tcp.compress | 是否压缩tcp传输时的数据,默认为false |
http.port | 对外服务的http端口,默认为9200 |
http.max_content_length | 内容的最大容量,默认100mb |
http.enabled | 是否使用http协议对外提供服务,默认为true |
gateway.type | gateway的类型,默认为local即为本地文件系统。可以设置为本地文件系统,分布式文件系统,hadoop的HDFS、amazon的s3服务器以及其它文件系统 |
gateway.recover_after_nodes | 集群中N个节点启动后进行数据恢复,默认为1 |
gateway.recover_after_time | 初始化数据恢复进程的超时时间,默认是5分钟 |
gateway.expected_nodes | 集群中节点的数量,默认为2,一旦这N个节点启动,就会立即进行数据恢复 |
cluster.routing.allocation.node_initial_primaries_recoveries | 初始化数据恢复时,并发恢复线程的个数,默认为4 |
cluster.routing.allocation.node_concurrent_recoveries | 添加删除节点或负载均衡时并发恢复线程的个数,默认为4 |
indices.recovery.max_size_per_sec | 数据恢复时限制的带宽,单位mb,默认为0,即无限制 |
indices.recovery.concurrent_streams | 限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5 |
discovery.zen.minimum_master_nodes | 有主节点资格的节点个数,默认为1 |
discovery.zen.ping.timeout | 自动发现其它节点时ping连接超时时间,默认为3秒 |
discovery.zen.ping.multicast.enabled | 是否打开多播发现节点,默认是true |
discovery.zen.ping.unicast.hosts | 设置主节点的初始列表,可以通过这些节点来自动发现新加入集群的节点 |
action.auto_create_index | 是否自动创建索引 |
action.destructive_requires_name | 是否禁止使用_all和通配符删除索引 |
script.groovy.sandbox.enabled | 是否启用脚本 |
修改配置有两种方式:
1、持久性修改,使用关键字:persistent,集群重启后不失效;
2、临时性修改,使用关键字:transient,集群重启后就会失效;
PUT http://$user:$passwd@$host:$port/_cluster/settings
{
"persistent" : {
配置名 : 值
},
"transient" : {
配置名 : 值
}
}
常用API:
1、查看集群信息:
GET http://$user:$passwd@$host:$port/
2、查看集群健康信息:
GET http://$user:$passwd@$host:$port/_cluster/health
3、查看集群状态:
GET http://$user:$passwd@$host:$port/_cluster/state
4、查看集群下所有索引:
GET http://$user:$passwd@$host:$port/_cat/indices
5、查看集群下已安装的插件:
GET http://$user:$passwd@$host:$port/_cat/plugins
6、给指定集群下的索引增加别名:
POST http://$user:$passwd@$host:$port/_aliases
{
"actions": [
{
"add": {
"alias": 索引别名,
"index": $index
}
}
]
}
7、给指定集群下指定索引重新指向:
POST http://$user:$passwd@$host:$port/_aliases
{
"actions": [
{
"add": {
"alias": 索引别名, //别名必须和$index1一样,这样如果查询都是用的这个别名,那么可以平滑地切到新的索引
"index": $index2
}
},
{
"remove": {
"alias": 索引别名,
"index": $index1
}
},
]
}
更多API请参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/cluster.html
8、从一个索引复制数据到另一个索引:
POST http://$user:$passwd@$host:$port/_reindex
{
"source": {
"index": $index1
},
"dest": {
"index": $index2
}
}
更多API请参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/docs-reindex.html
三、分析器
文档的每个域都有多个属性,更多属性参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/mapping-params.html,介绍两个属性:
1、analyzer:它指定在索引文档或搜索文档时使用的分析器。默认使用标准分析器(standard)分析器。分析器对文档内容的分析包含以下过程:
1>将文本分成适合倒排索引的独立的词条;
2>将这些词条统一为标准格式以提高它们的“可搜索性”,比如:
①大小写转换;
②词根提取;
③同义词转换;
分析器实际上是将三个功能封装到了一个包里:
1>字符过滤器
字符串按顺序通过每个字符过滤器,过滤器的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将&转化成 `and`;
2>分词器
字符串被分词器分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条;
3>token过滤器
词条按顺序通过每个token过滤器。这个过程可能会改变词条(比如转换大小写),删除词条(比如像`a`,`and`,`the`等无用词),或者增加词条(比如增加同义词)。
es常见的内置分析器有:
1>标准分析器(standard):根据Unicode联盟定义的单词边界划分文本,删除绝大部分标点,最后将词条小写;
2>简单分析器(simple):在任何不是字母的地方分隔文本,将词条小写;
3>空格分析器(whitespace):在空格的地方划分文本;
4>语言分析器:根据指定语言的特点,对文本进行划分;
2、fields:由于不同的用处,对同一字段建立不同的索引。比如同一个字段需要使用不同的类型和分析器:
{
"title": {
"type": "text",
"analyzer": "ik_smart",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 64
},
"completion": {
"type": "completion",
"analyzer": "ik_smart"
}
}
}
}
常用API:
1、查看文本放入字段后的拆词结果:
GET http://$user:$passwd@$host:$port/$index/_analyze
{
"field": 字段名,
"text": 文本内容
}
2、查看文本经过分析器处理后的结果:
GET http://$user:$passwd@$host:$port/$index/_analyze
{
"analyzer": 分析器名,
"text": 文本内容
}
3、创建自定义分析器:
PUT http://$user:$passwd@$host:$port/$index
{
"settings": {
"analysis": {
"analyzer": {
"dash_remove_analyzer": { //创建名为dash_remove_analyzer的分析器,用于去“-”
"tokenizer": "standard",
"stopwords": "_spanish_", //停用词使用预定义的西班牙语停用词列表
"char_filter": [
"dash_remove_char_filter"
]
}
},
"char_filter": {
"dash_remove_char_filter": {
"type": "pattern_replace",
"pattern": "(\\S*)-(\\S*)|(\\S*)",
"replacement": "$1$2"
}
}
}
}
}
详情参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/analysis-custom-analyzer.html
四、用户
集群安全参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/secure-cluster.html
常用API(仅限百度云):
1、查看集群有哪些用户:
GET http://$user:$passwd@$host:$port/_user/show
2、创建针对某个索引的用户权限:
POST http://$user:$passwd@$host:$port/_user/create
{
"username" : "test",
"password" : "test123",
"get_path" : ["/index1"],
"put_path" : ["/index2"],
"post_path" : ["/index3"],
"del_path" : ["/index4"],
"read_index": ["index5"],
"write_index": ["index6"]
}
五、索引
常用API:
1、查看指定索引信息:
GET http://$user:$passwd@$host:$port/$index
2:创建索引:
PUT http://$user:$passwd@$host:$port/$index
{
"settings": {
"index": {
"number_of_shards": 1, //索引的主分片个数,默认值是5,这个配置在索引创建后不能修改
"number_of_replicas" : 0 //每个主分片的副本分片个数,默认值是1,对于活动的索引库,这个配置可以随时修改
}
},
"aliases": {
索引别名: {} //务必要设置索引别名,方便以后数据平滑迁移
},
"mappings": {
"$type": {
"properties": {
字段名1: {
"type": "text",
"analyzer": "ik_smart", //默认使用ik_smart分词
"fields": {
"keyword": { //定义分析器:字段名1.keyword
"type": "keyword",
"ignore_above": 64
},
"completion": {
"type": "completion", //用于completion suggester
"analyzer": "ik_smart"
}
}
},
字段名2: {
"type": "boolean"
},
字段名3: {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
字段名4: {
"type": "long"
}
}
}
}
}
3、查看指定索引类型下的映射信息:
GET http://$user:$passwd@$host:$port/$index/_mappings/$type
4:修改指定索引配置:
PUT http://$user:$passwd@$host:$port/$index/_settings
{
"refresh_interval": "2s"
}
5:新增属性:
PUT http://$user:$passwd@$host:$port/$index/_mappings/$type
{
"properties": {
新增的属性名: {
"type": "keyword"
}
}
}
6:新增字段:
PUT http://$user:$passwd@$host:$port/$index/_mappings/$type
{
"properties": {
原有的属性名: {
"type": "keyword", //原有的type
"fields": {
新增的字段名: {
"type": "completion",
"analyzer": "ik_smart"
}
}
}
}
}
7:一般情况下是无法修改已有映射中的属性,因为数据入ES时已根据这些属性的特点进行了处理,如果允许轻易改这些属性,那已有的数据将可能无法兼容新的属性。但有一些特殊情况是可以修改的。
①给指定字段下增加子properties,组成多层级对象:
PUT http://$user:$passwd@$host:$port/$index/_mappings/$type
{
"properties": {
原已有的属性名: {
"type": "keyword", //原已有的type
"properties": {
新增的子属性的字段名: {
"type": "long"
}
}
}
}
}
②
③④
7:删除索引,可以有多种方式:
DELETE http://$user:$passwd@$host:$port/$index
DELETE http://$user:$passwd@$host:$port/$index0,$index1
DELETE http://$user:$passwd@$host:$port/$index*
DELETE http://$user:$passwd@$host:$port/_all
DELETE http://$user:$passwd@$host:$port/*