内容概述
本文内容主要集中在应用层,通过下面几个部分介绍当前最流行的搜索工具: Elasticsearch
,了解这些内容后,可以快速开始使用它。
Elasticsearch index RESTful Api
什幺是 Elasticsearch
,为什幺要使用它?
Elasticsearch
是一个分布式、RESTful 风格的搜索和数据分析引擎。
它基于 Lunece
实现,使用 java
语言编写。 Lunece
是一个优秀的搜索引擎库,但它使用起来非常复杂。
Elasticsearch
通过对 Lunece
的封装,隐藏了复杂性,提供了使用简单的RESTful Api。
同时也实现了分布式集群特性,具有存储数据大,查询性能好,扩展方便等特点。
为什幺要使用它
在业务开发中,基于ES的特性,通常有下面这些场景需要使用它:
存储大量数据。通过在使用mysql存储的时候,数据的单位是 G
。使用ES的时候,数据的单位是 T
。由此可以看出ES使用于大数据量的存储场景,基于分布式特性,它也支持备份和容灾,并且可以很容易水平扩展容量。
分词搜索引擎。ES具有强大的分词能力,可以支持高性能的实时搜索。
高效数据分析。ES提供的聚合分析功能,可实现对保存的大量数据的近实时统计分析。
基础概念简介
要使用ES,需要了解几个最基本的概念,节点( node
),索引( index
),类型映射( mapping
)和文档( doc
)。
节点( node
)
节点是组成ES集群的基本单位,每个节点是一个运行的ES实例。每个物理机器上可以有多个节点,使用不同的端口和节点名称。
节点按主要功能可以分为三种:主节点(Master Node),协调节点(Coordianting Node)和数据节点(Data Node)。下面简单介绍下:
主节点:处理创建,删除索引等请求,维护集群状态信息。可以设置一个节点不承担主节点角色
协调节点:负责处理请求。默认情况下,每个节点都可以是协调节点。
数据节点:用来保存数据。可以设置一个节点不承担数据节点角色
索引( index
)
索引是ES中的逻辑概念,是文档的容器。对ES的操作,基本都是对索引操作,一个ES集群中,可以创建多个索引。
索引定义了一组文档的数据模型和处理方法。每个索引可以有多个主分片和副本分片,分别保存在不同的节点。
主分片的作用是对索引的扩容,使一个索引的容量可以突破单机的限制。
副本分片是对数据的保护,每个主分片对应一个或多个副本分片,当主分片所在节点宕机时,副本分片会被提升为对应的主分片使用。
一个主分片和它的副本分片,不会分配到同一个节点上。
一个索引的分片数在创建时指定,如果要修改需要重建索引,代价很高。
类型映射( mapping
)
mapping
定义了一个索引中,文档保存的每个字段的数据类型。根据数据类型的不同,在添加文档时对每个字段的处理也不同。
例如,对text类型的字段,会先使用分词器分词,生成倒排索引,用于之后的搜索。对keyword类型的字段,不会分词,搜索时只能精确查找。
一个简单的mapping示例如下:
{ "javalogs": { //索引名称 "mappings": { "properties": { "log_content": { //text类型,分词,用于之后的分词索引 "type": "text" }, "date": {//时间类型 "type": "date" }, "log_level": { //keyword类型,不分词 "type": "keyword" }, "ip": { "type": "keyword" } } } } }
在6.x版本中,每个索引中还可以有多个type,区分不同的mapping。在7.x中,type被取消,每个索引只有一个type:_doc
文档( doc
)
Elasticsearch mapping
下面通过一张图来描述,节点( node
),索引( index
)和文档( doc
)之间的关系。
本地环境搭建,创建第一个 index
一切知识都要通过实践掌握,所以在了解基本的概念和逻辑后,下面就进入实践环节。
这里推荐使用docker来搭建本地开发环境,docker对应windows和mac系统都有桌面版本,使用非常方便。因为网络限制,直接使用docker官方仓库拉取镜像会很慢,所以在安装完成后,需要在设置中将仓库的地址替换为国内源,这里推荐 https://docker.mirrors.ustc.edu.cn
,速度很快,设置如下:
{ "registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn" ] }
下面我们使用docker安装 Elasticsearch
和 kibana
镜像, kibana
是es官方配套的可视化分析工具,使用它的页面dev tools可以很方便的通过api操作es。
因为要同时部署两个docker镜像,这里推荐使用 docker-composer
,桌面版安装完成后就带有该命令,需要的配置如下:
services: kibana: image: kibana:7.2.0 container_name: kibana-simple environment: - TIMELION_ENABLED=true ports: - "5601:5601" networks: - mynetwork elasticsearch: image: elasticsearch:7.2.0 container_name: es-simple environment: - cluster.name=mytestes #这里就是ES集群的名称 - node.name=es-simple #节点名称 - bootstrap.memory_lock=true - network.publish_host=elasticsearch #节点发布的网络名称 - discovery.seed_hosts=es-simple #设置集群中的主机地址 - cluster.initial_master_nodes=es-simple #手动设置可以成为master的节点集合 ulimits: memlock: soft: -1 hard: -1 volumes: - esdata1:/usr/local/elasticsearch/simpledata ports: - 9200:9200 networks: - mynetwork volumes: esdata1: driver: local networks: mynetwork: driver: bridge
创建一个名称为 docker-compose.yaml
文件,复制下面的配置到文件中,然后再文件所在目录执行 docker-compose up
,之后会启动两个docker实例,分别是 elasticsearch
和 kibana
。
在本地浏览器中,访问 http://127.0.0.1:5601/
,可以看到 kibana
的界面如下:
创建好的 kibana
已经默认添加了 Elasticsearch
的配置,通过管理工具可以很方便的查看ES集群的状态,索引情况,删除索引等。
下面通过 dev tools
创建索引, dev tools
提供的命令提示很方便,并且可以把已写好的请求保存在浏览器缓存中,非常适合用来学习 Elasticsearch
。
这里通过ES提供的 RESTful Api
创建了第一个索引, 并且设置了该索引中的 mapping
,ES的地址已经设置过,这里可以不写完整的域名,对应的curl完整请求如下:
curl --location --request PUT 'http://127.0.0.1:9200/javalogs' \ --header 'Content-Type: application/json' \ --data-raw '{ "mappings": { "properties": { "log_content": { "type": "text" }, "date": { "type": "date" }, "log_level": { "type": "keyword" }, "ip": { "type": "keyword" } } } }'
常用 RESTful Api
示例
下面介绍下 Elasticsearch
中常用的api,这些例子都是直接在 kibana
的 dev tools
中运行的,如果想用curl访问,可参考前一节中的转换例子。
新增文档
//自动生成_id POST javalogs/_doc { "log_content" : "get user_id 123456", "date" : "2020-04-15T11:09:08", "log_level": "info", "ip": "10.223.32.67" }
//指定_id POST javalogs/_doc/111 { "log_content" : "api response in 55ms", "date" : "2020-04-15T11:09:07", "log_level": "info", "ip": "10.223.32.67" }
查询文档-不分词类型
ES在文档查询时,对于不分词的查询,直接按值查询即可,例如下面这样:
//不分词类型查询 POST javalogs/_search { "query": { "match": { "ip": "10.223.32.67" } } }
查询文档-分词类型
这里主要说下分词类型的查询,对于分析类型的 field
在查询时,也会默认把查询的语句分词。假设有两个文档如下:
//文档1 { "log_content" : "call aaa service error", "date" : "2020-04-15T11:09:07", "log_level": "error", "ip": "10.223.32.67" } //文档2 { "log_content" : "call bbb service error", "date" : "2020-04-15T11:09:08", "log_level": "error", "ip": "10.223.32.67" }
当搜索条件为 call aaa service
时,实际上会把两个文档都搜索出来。
这是因为在搜索时,条件 call aaa service
会被分词为 call
, aaa
和 service
,所有包含这三个词的文档都会被搜索出来,例如下面:
//普通搜索,两个文档都会返回 POST javalogs/_search { "query": { "match": { "log_content": "call aaa service" } } }
那如果想要只搜索包含 call aaa service
的文档,应该如何做呢?
按照上面的分析,需要同时包含这三个词,并且按照给定的顺序,才返回对应的文档,那幺这个可以使用 match_phrase
实现,示例如下:
//文档必须同时包含三个词,并且顺序与搜索条件一致才会返回。这里只会返回-文档1 POST javalogs/_search { "profile": "true", "query": { "match_phrase": { "log_content": "call aaa service" } } }
那如果条件是包含 call
, aaa
和 service
,但是不一定是连着的,该如何搜索呢?可以使用 operator
操作符实现。
例如有第三个文档如下:
//文档3 { "log_content" : "call inner aaa service error", "date" : "2020-04-15T11:09:08", "log_level": "error", "ip": "10.223.32.67" }
要想把 文档1
和 文档2
都搜索出来,查询的示例如下:
//文档中同时包含call,aaa和service就会返回,不按顺序。会返回-文档1和文档2 POST javalogs/_search { "query": { "match": { "log_content": { "query": "call aaa service", "operator": "and" } } } }
上面就是对 Elasticsearch
的简单介绍和实战操作示例,希望能帮助大家快速入门使用ES。
Be First to Comment