15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > ES从入门到实战

ES从入门到实战

时间:2023-05-30 12:12:01 | 来源:网站运营

时间:2023-05-30 12:12:01 来源:网站运营

ES从入门到实战:

简介

elasticsearch

我是@飓哥,经常会分享Java后台硬核知识,欢迎大家关注~

全文搜索属于最常见的需求,开源的 Elasticsearch 是目前全文搜索引擎的首选。它可以快速地存储、搜索和分析海量数据。 维基百科、Stack Overflow、Github 都采用它。 Elastic 的底层是开源库 Lucene。 但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。 Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。 REST API:天然的跨平台。





一、基本概念

  1. Index(索引)
    动词,相当于 MySQL 中的 insert; 名词,相当于 MySQL 中的 Database
  2. Type(类型)
    在 Index(索引)中,可以定义一个或多个类型; 类似于 MySQL 中的 Table;每一种类型的数据放在一起。
  3. Document(文档)
    保存在某个索引(Index)下,某种类型(Type)的一个数据(Document),文档是 JSON 格式的, Document 就像是 MySQL 中的某个 Table 里面的内容。
  4. 倒排索引机制
分词:将整句分拆为单词

保存的记录
检索: 1)、红海特工行动? 2)、红海行动?




二、Docker 安装




1、下载镜像文件

下载elasticsearch

docker pull elasticsearch:7.4.2 # 存储和检索数据

下载kibana

docker pull kibana:7.4.2 # 可视化检索数据
注意:elasticsearch 要和 kibana 的版本保持一致!



2、创建实例

1. ElasticSearch

mkdir -p /mydata/elasticsearch/config # 在mydata文件夹下创建es的config文件夹,将docker中es的配置挂载在外部,当我们在linux虚拟机中修改es的配置文件时,就会同时修改docker中的es的配置mkdir -p /mydata/elasticsearch/data #在mydata文件夹下创建es的data文件夹echo "http.host:0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml # [http.host:0.0.0.0]允许任何远程机器访问es,并将其写入es的配置文件中chmod -R 777 /mydata/elasticsearch/ # 保证权限问题docker run --name elasticsearch -p 9200:9200 -p 9300:9300 /-e "discovery.type=single-node" /-e ES_JAVA_OPTS="-Xms64m -Xmx128m" /-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# docker run --name elasticsearch 创建一个es容器并起一个名字;# -p 9200:9200 将linux的9200端口映射到docker容器的9200端口,用来给es发送http请求# -p 9300:9300 9300是es在分布式集群状态下节点之间的通信端口 / 换行符# -e 指定一个参数,当前es以单节点模式运行# *注意,ES_JAVA_OPTS非常重要,指定开发时es运行时的最小和最大内存占用为64M和128M,否则就会占用全部可用内存# -v 挂载命令,将虚拟机中的路径和docker中的路径进行关联# -d 后台启动服务安装完 elasticsearch 后我们来启动一下,会发现使用docker ps命令查看启动的容器时没有找到我们的 es,这是因为目前 es 的配置文件的权限导致的,因此我们还需要修改一下 es 的配置文件的权限:




修改完文件权限后,我们使用docker start elasticsearch再次启动 es,使用docker ps命令查看后发现容器还是没有启动,这是问什么呢? 我们使用docker logs elasticsearch看一下 es 的启动日志:




上述错误是由于我之前配置elasticsearch.yml文件的时候k-v键值对配置错误导致的,查看 yml 文件会发现我配置的内容是这样的:

http.host:0.0.0.0而实际上k-v键值对之间应该有空格,注意 yml 配置文件中key: value格式冒号后面要跟一个空格。否则就会导致上面的错误。 因此需要修改一下elasticsearch.yml文件,修改为:

http.host: 0.0.0.0修改并保存之后再次使用docker start elasticsearch启动 es,使用docker ps命令产看后可以看到我的 es 容器已经启动起来了:

在浏览器地址栏访问http://124.220.176.158:9200/,可以看到 es 启动成功后返回类似下面的数据:

注意124.220.176.158 是我的linux虚拟机的地址,读者需要根据自己的虚拟机地址来进行访问



2, Kibana

安装可视化界面

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://124.220.176.158:9200 -p 5601:5601 /-d kibana:7.4.2安装完成后在浏览器地址栏访问http://124.220.176.158:5601/,可以看到 kibana 已经启动成功:

选择yes或no都可以:

安装成功的界面:

三、初步检索

对 ES 的所有请求都被封装成了 REST API,因此我们可以使用 postman 来访问它。

使用 postman 或者在浏览器地址栏输入请求路径http://124.220.176.158:9200/_cat/xxx



1、_cat

green 表示健康

2、索引一个文档(对应成Mysql就是保存一条记录)

保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识PUT customer/external/1; 在 customer 索引下的 external 类型下保存 1 号数据为




PUT customer/external/1



{

"name":"lohn Doe"

}

PUTPOST都可以;

POST新增。如果不指定id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号;

PUT可以新增也可以修改。PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改

可以看到创建记录成功:

再一次发送请求后得到如下结果:

所以 put 方法既可以用来新增,也可以用来更新。
在 postman 中使用 post 方法发送 http://192.168.56.10:9200/customer/external/ 请求,注意没有带 id,使用的还是上面 put 方法中的参数, 可以看到创建记录成功,es 帮我们生成了一个id:



当我们使用这个 id 再一次发送 post 请求时,就会变成更新操作:

所以 post 方法不带 id 时是新增,带 id 不存在时也是新增,带 id 且数据存在时是更新操作。




那么问题来了,put 和 post 方法有啥区别呢?如果使用 put 方法不带 id 发送请求行不行?

可以看到使用 put 方法不带 id 请求会报错,也就是说 put 是不允许不带 id 请求的,而 post 是允许的。




3、查询文档




3.1、get查询数据

GET customer/external/1

3.2、乐观锁修改

要使用乐观锁修改,我们就需要在 put 或 post 请求的路径中加上?if_seq_no=0&if_primary_term=1字段; 我们在 postman 中使用 put 方法发送 http://192.168.56.10:9200/customer/external/1?if_seq_no=0&if_primary_term=1 请求,参数传



如果我们使用最新的序列号去更新,就会返回状态 更新成功的结果:

4、更新文档

使用带_update的 post 请求更新数据,在 postman 中使用 post 方法发送http://192.168.56.10:9200/customer/external/1/_update请求,参数传:

发送请求可以得到下面的结果,可以看到更新成功:

再次发送请求,可以看到如果数据相同,对比原来数据,与原来一样就什么都不做,_version_seq_no也不会变:




5、删除文档&索引




5.1、删除文档

在 postman 中使用 delete 方法发送 http://192.168.56.10:9200/customer/external/1 请求,可以看到以下结果,可以看到删除文档成功:

再发送一次请求,会返回一个 404 状态的not_found结果:

5.2、删除索引

在 kibanda中使用 delete 方法发送http://192.168.56.10:9200/customer请求,可以看到以下结果,可以看到删除索引成功:

查询一下刚才删除的索引,会返回一个no such index [customer]的 404 状态的结果:

6、bulk 批量 API

要使用 bulk 批量 API,就需要在 kibana 中来执行我们的操作,如果在 postman 中请求会报错: 首先我们的请求体中的数据已经不是 json 格式了,我们是用 text 格式,会报下面的错误:

进行一个复杂的批量操作

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,没有指定具体的索引,表示在 ES 全局执行。执行结果如下:

bulk API 以此按顺序执行所有的 action (动作) 。 如果一个单个的动作因任何原因而失败,它将继续处理它后面剩余的动作。 当 bulk API 返回时,它将提供每个动作的状态(与发送的顺序相同) ,所以你可以检查是否一个指定的动作是不是失败了。

7、样本测试数据

我准备了一份顾客银行账户信息的虚构的 JSON 文档样本。每个文档都有下列的 schema(模式) :

上面的数据是从 github 的 ES 官方文档中截取的,可以访问下面的地址:

accounts.json 导入测试数据

在 ES 中执行测试数据 POST bank/account/_bulk:




四、进阶检索

1、SearchAPl


ES 支持两种基本方式检索:


1)、检索信息
一切检索从_search开始 uri+检索参数:



uri+请求体 进行检索:

GET /example/_search

{ "query": { "match_all": {} }

}

HTTP 客户端工具(POSTMAN),get 请求不能携带请求体,我们变为 post 也是一样的我们 POST 一个 JSON 风格的查询请求体到_search APl。
需要了解,一旦搜索的结果被返回, Elasticsearch 就完成了这次请求,并且不会维护任何服务端的资源或者结果的 cursor (游标)

2、Query DSL

GET /example/_search{ "query": { "match_all": {} }, "sort": [ { "id": "asc" } ]}1)、基本语法格式
Elastisearch 提供了一个可以执行查询的 Json 风格的 DSl (domain-specific language 领域特定语言) 。这个被称为Query DSL。 该查询语言非常全面,并且刚开始的时候感觉有点复杂,真正学好它的方法是从一些基础的示例开始的。


{ QUERY_NAME:{ ARGUMENT: VALUE, ARGUMENT: VALUE, ... }}例如:

如果是针对某个字段,那么它的结构如下:

{ QUERY_NAME:{ FIELD_NAME:{ ARGUMENT: VALUE, ARGUMENT: VALUE, ... } }}例如:

GET /bank/_search{ "query": { "match_all": {} }, "sort": [ { "balance": { "order": "desc" } } ], "from": 0, "size": 5}- query 定义如何查询;
- match_all 查询类型【代表查询所有的所有】, es 中可以在 query 中组合非常多的查询类型完成复杂查询
- 除了 query 参数之外,我们也可以传递其它的参数以改变查询结果。如 sort,size;
- from+size 限定,完成分页功能;
- sort 排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准



2)、返回部分字段

GET /example/_search{ "query": { "match_all": {} }, "sort": [ { "id": "asc" } ], "from": 0, "size": 5,"_source": ["name","counter"] }只返回_source中指定的字段,类似于 MySQL 中的select field_1,field_2,... from table




3)、match【匹配查询】

match 返回 id=1的数据:

GET /example/_search{ "query": { "match": { "id": 1 } }}最终查询出 name中包含 张的所有记录,当搜索字符串类型的时候,会进行全文检索,并且每条记录有相关性得分。

GET /example/_search{ "query": { "match": { "name": "张" } }}

4)、match_phrase 【短语匹配】

将需要匹配的值当成一个整体单词(不分词)进行检索

举个栗子:查出 name中包含张的所有记录,并给出相关性得分

GET /example/_search{ "query": { "match_phrase": { "name": "张 三" } }}

5)、multi_match 【多字段匹配】

举例:id或 counter包含 1




GET /example/_search{ "query": { "multi_match": { "query": "1", "fields": ["id","counter"] } }}

6)、bool 【复合查询】

bool 用来做复合查询:

复合语句可以合并任何其它查询语句,包括复合语句,了解这一点是很重要的。 这就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

GET /example/_search{ "query": { "bool": { "must": [ { "match": { "id": 2 } }, { "match": { "name": "张三" } } ] } }}must_not:子句(查询)不得出现在匹配的文档中




should:子句(查询)应出现在匹配的文档中。(should表示有最好,没有也可以)

布尔查询

与文档匹配的查询,这些文档与其他查询的布尔组合匹配。布尔查询映射到LuceneBooleanQuery。它是使用一个或多个布尔子句构建的,每个子句都具有类型的出现。发生类型为:

7)、filter 【结果过滤】
并不是所有的查询都需要产生分数,特别是那些仅用于 "fitering" (过滤)的文档。为了不计算分数 Elasticsearch 会自动检查场景并且优化查询的执行。 在 filter 元素下指定的查询对得分没有影响-得分以 0 形式返回。分数仅受指定查询的影响。 以 must 查询为例:



使用filter来替代must查询,需要注意的是,使用filter查询出的结果和must查询出的结果是一致的,差异仅是没有相关性得分:

所以我们在should之后还可以加上filter条件进行过滤:




8)、term

和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term

非文本值使用 term 检索:

GET /example/_search{ "query": { "term": { "id":1 } }}注意:如果对于文本值使用 term 检索时,并不会进行分词,而是精确检索,所以可能会匹配不到数据:




9) 、aggregations (执行聚合)
聚合提供了从数据中分组和提取数据的能力。 最简单的聚合方法大致等于 SQL GROUP BYSQL 聚合函数。 在 Elasticsearch 中,您有执行搜索返回 hits (命中结果),并且同时返回聚合结果, 把一个响应中的所有hits(命中结果)分隔开的能力。这是非常强大且有效的,您可以执行查询和多个聚合, 并且在一次使用中得到各自的(任何一个的)返回结果,使用一次简洁和简化的 API 来避免网络往返。
aggregations 查询语法:



"aggregations" : { "<aggregation_name>" : { "<aggregation_type>" : { <aggregation_body> } [,"meta" : { [<meta_data_body>] } ]? [,"aggregations" : { [<sub_aggregation>]+ } ]? } [,"<aggregation_name_2>" : { ... } ]*}


3、Mapping


1)、字段类型


地理类型(Geo)



特定类型



2)、映射
Mapping (映射) Mapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。比如,使用mapping来定义:






PUT /my-index{ "mappings": {//映射规则 "properties": { "age": { "type": "integer" }, "email": { "type": "keyword" },//keyword不会进行全文检索 "name": { "type": "text" }//text保存的时候进行分词,搜索的时候进行全文检索 } }}3)、新版本改变
ES7 及以上移除了 type 的概念。


Elasticsearch 7.x:


Elasticsearch 8.x:


解决: 1)、将索引从多类型迁移到单类型,每种类型文档一个独立索引 2)、将已存在的索引下的类型数据,全部迁移到指定位置即可。详见数据迁移

关键词:实战,入门

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭