中铁建设集团有限公司网站,专做高中知识的网站,seo网站优化平台,黄骅港在哪若你之前从未了解过ES#xff0c;本文将由浅入深的一步步带你理解ES#xff0c;简单使用ES。作者本人就是此状态#xff0c;通过学习和梳理#xff0c;产出本文#xff0c;已对ES有个全面的了解和想法#xff0c;不仅将知识点梳理#xff0c;也涉及到自己的理解#xf… 若你之前从未了解过ES本文将由浅入深的一步步带你理解ES简单使用ES。作者本人就是此状态通过学习和梳理产出本文已对ES有个全面的了解和想法不仅将知识点梳理也涉及到自己的理解初次学习踩的坑都汇总如下。 1 了解ElasticSearch
对于第一次接触ES的读者该章节将直观的带你体验ES的魅力。
1.1 为何使用ES
使用前 案例需模糊查询带有 **华为** 的商品信息使用MySQL的查询功能select * from 表名 where name like “%华为%” 模糊查询会导致索引失效就会全表扫描效率低 案例需模糊查询带有 **华为手机** 的商品信息使用MySQL的查询功能select * from 表名 where name like “%华为手机%” 只能找到 华为手机 这样的结果 无法找到 华为荣耀手机、华为耳机、 手机这样的结果意思就是无法将华为手机分开查询。这也是MySQL查询功能弱的缺点 使用后 输入 ”华为手机“ 结果展示 华为荣耀手机、华为耳机、 手机、华为手机且查询效率高 上述案例旨在告诉读者面对更复杂的业务场景和搜索需求单纯的SQL查询远远不能满足MySQL是存储数据的解决方案ES则是面对海量数据执行搜索的解决方案。
现在简单了解一下ES是怎么做到的上述优点
1.1 倒排索引 在了解倒排索引概念之前先看看正向索引 案例 查找含有 明 这个字的诗句数据库信息是否匹配锄禾日当午x忽如一夜春风来x窗前明月光√
结果窗前明月光 缺点得从第每首诗的第一行的第一个字找这种正向操作的思想会导致查询比较慢 倒排索引 案例 查找含有 是 这个字的诗句内部操作 ES内部会自动的将 窗前明月光这个数据进行分词
拆分单词结果窗前窗前明月光床窗前明月光前窗前明月光明月窗前明月光明窗前明月光月窗前明月光光窗前明月光
找到关键字 明得到对应的结果效率很快的。我们习惯性将这种不直接查询的设计叫倒排索引
案例升级 此时需要在数据库中再存储一条数据”明月几时有“ES会如何操作 当然是自动拆分这句话
拆分单词结果窗前窗前明月光床窗前明月光前窗前明月光明月窗前明月光明月几时有明窗前明月光明月几时有月窗前明月光明月几时有光窗前明月光几时明月几时有有明月几时有
拆分的单词若已经有了直接存储在后面就行若拆分的单词是新的则续上。
优化倒排索引
考虑一下这个情况若拆分单词是 月 的结果有很多很多岂不是这个表就很大如何处理 可以这样设计
拆分单词结果ID窗前《静夜思》床《静夜思》前《静夜思》明月《静夜思》《水调歌头》明《静夜思》《水调歌头》月《静夜思》《水调歌头》光《静夜思》几时《水调歌头》有《水调歌头》
根据拆分单词找到诗词名称再根据诗词名称去查对应的内容。这样一个表就拆成两个表就不大了。此外这里的诗词名称就是唯一标识在ES引擎中用 ID 表示。
从这里我们才真正的进入ES引擎
我们的数据格式是Json存在文档中
{id:1,title:华为折叠手机,price:120.00
}
-----------------------------------------
{id:2,title:三星翻盖手机,price:40.00
}
-----------------------------------------
{id:3,title:华为移动翻盖手机,price:90.00
}自动拆分得到表
termvalue华为13折叠1手1,2,3手机1,2,3三星2翻盖2,3移动3
若term列数据很多那直接从上往下一个个匹配也是会很慢的因此ES引擎对词条term列做了优化。 在生成倒排索引此表后词条会排序形成一颗树形结构又称为字典树提升词条的查询速度。
ES的定位mysql的数据只要一更新就将索引同步给ES保证数据一致性
2 安装ES
2.1 环境
CentOS 7 elasticsearch-7.4.0-linux-x86_64.tar.gz
2.2 将安装包解压在opt目录下 2.3 解压
tar -zxvf elasticsearch-7.4.0-linux-x86_64.tar.gz -C /opt 2.3 修改elasticsearch.yml文件 cluster.name: my-application //默认名称是elasticserach
node.name: node-1
network.host: 0.0.0.0 //保证在windows上可以访问安装在centos上的ES引擎
http.port: 9200
cluster.initial_master_nodes: [node-1]
2.4 启动报错 这是因为ES不推荐以root身份启动而是推荐以用户身份启动 我们已经有用户zjh只需要给其赋予启动权限就好
2.5 修改用户配置文件
vim /etc/security/limits.conf
添加此信息
zjh soft nofile 65536
zjh hard nofile 65536vim /etc/security/limits.d/20-nproc.conf
添加此信息
zjh soft nofile 65536
zjh hard nofile 65536
* hard nproc 40963. vim /etc/sysctl.conf
添加此信息vm.max_map_count655360sysctl -p
2.6 切换用户重启ES
启动前先暂时关闭防火墙 再启动 输入自己的虚拟机IP9200
3 安装Kibana
Kibana版本必须和ES版本对应避免出现不兼容的问题。
链接: Kibana下载
解压 tar -xzf kibana-7.4.0-linux-x86_64.tar.gz -C /opt
2.修改配置文件vim /opt/kibana-7.4.0-linux-x86_64/config/kibana.yml
# 添加如下内容
server.port: 5601
server.hosts: 0.0.0.0
server.name: kibana-itcast
elasticsearch.hosts: [http://127.0.0.1:9200]
elasticsearch.requestTimeout: 999993.执行报错需切换身份 4.切换身份执行
4 ES核心概念
本章节讲述如下几个概念索引、映射、文档、倒排索引
这是一个mysql数据库处理数据的过程创建表将数据存储到对应字段创建Movice表Animal表结构 这里我们也是创建表不过在ES中不这样称呼而是称之为建立索引。创建Movice与Animal索引并给索引Movice索引Animla创建映射然后存储数据最后将相关字段进行分词。 5-8章节主要介绍在Kibana的可视化环境中使用脚本进行相关操作帮助熟悉ES 5 索引–基础操作
不能修改索引
5.1 创建索引 5.2 查询索引 5.3 添加映射 5.4 查询索引映射 5.5 删除索引 5.6 创建索引并添加映射 5.7 添加字段 6 文档–基础操作
6.1 添加文档指定id 6.2 添加文档不指定id 6.3 修改文档 6.4 查询所有文档 6.5 删除文档根据id 7 分词器analyze 但是其对中文很不友好使用ES的内置分词器中文只会被分成一个一个字中英文分别演示一下 中文彻底被拆分成了一个个字 英文是按照单词拆分的并不是按照字母拆分。 因此若想要更好的中文分词效果需要安装其他的分词器如IK分词器这里不介绍了。
8 文档查询
8.1 term
term查询的条件字符串和词条完全匹配 例查询与“美”相关的title 需要注意的是ES默认使用的standard分词器因此仅支持单独的汉字匹配例如这样
若想要更改分词器只能重新建立索引映射同时设置分词器
8.2 match
会先对查询的字符串进行分词再去查询得到并集 例将“美国”按照standard的分词器进行拆分得到“美” “国”分别查询求并集。
9 与springboot的整合 在springboot中我们一般只操作文档。在kibana使用脚本建立索引。这一章节介绍一下如何使用代码操作ES中的文档 9.1 简单获取cilent对象
ES将相关的操作都封装成在RestHighLevelClient 中因此我们需要获取其对象才能进行相关操作 创建一个springboot项目导入依赖 dependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-high-level-client/artifactIdversion7.9.0/version/dependencydependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-client/artifactIdversion7.9.0/version/dependencydependencygroupIdorg.elasticsearch/groupIdartifactIdelasticsearch/artifactIdversion7.9.0/version/dependency测试 获取ES客户端对象
SpringBootTest
class EsDemoApplicationTests {/*** HttpHost的三个参数* 1. 192.168.xx.xx:5601 地址是Kibana的地址和端口号* 2. 9002 是ES的端口* 3. schemehttp*/Testvoid test01() {RestHighLevelClient client new RestHighLevelClient(RestClient.builder(new HttpHost(ipxxxx:5601,9002,http)));System.out.println(client);}}成功获取client对象 获取了client就可以操作ES的文档
9.2 使用依赖注入方式优化获取Client
可以发现我们直接将HttpHost的三个参数写死了项目中不这样建议。
创建elasticsearch.yml文件
elasticsearch:host: 192.168.67.18:5601port: 9200创建配置类(获取Client)
Configuration
// 获取elasticsearch.yml文件信息自动将elasticsearch.yml文件中elasticsearch开头的字段和ESconfig 类中的字段匹配并赋值
ConfigurationProperties(prefix elasticsearch)
public class ESconfig {private String host;private int port;public String getHost() {return host;}public void setHost(String host) {this.host host;}public int getPort() {return port;}public void setPort(int port) {this.port port;}Beanpublic RestHighLevelClient client(){//1. 创建ES客户端对象RestHighLevelClient client new RestHighLevelClient(RestClient.builder(new HttpHost(host, port, http)));return client;}
}测试
SpringBootTest
class EsDemoApplicationTests {Autowiredprivate RestHighLevelClient client;Testvoid test01() {/* RestHighLevelClient client new RestHighLevelClient(RestClient.builder(new HttpHost(ipxxxx:5601,9002,http)));*/System.out.println(client);}}
9.3 索引相关了解
9.3.1 创建索引 /*** 创建索引*/Testvoid addIndex() throws IOException {//获取操作索引的对象IndicesClient indices client.indices();//创建索引获取返回值CreateIndexRequest createIndexRequest new CreateIndexRequest(movice);//设置映射mappingsString mapping {\n \properties\ : {\n \addres\ : {\n \type\ : \text\\n },\n \id\ : {\n \type\ : \integer\\n },\n \price\ : {\n \type\ : \integer\\n },\n \title\ : {\n \type\ : \text\\n }\n };createIndexRequest.mapping(mapping, XContentType.JSON);CreateIndexResponse response indices.create(createIndexRequest, RequestOptions.DEFAULT);//根据返回值判断结构成功了返回trueSystem.out.println(response.isAcknowledged());}
也就是这效果
9.3.2 查询索引
/*** 查询索引*/Testvoid queryIndex() throws IOException {//获取操作索引的对象IndicesClient indices client.indices();//根据索引名称查询GetIndexRequest getIndexRequest new GetIndexRequest(movice);GetIndexResponse response indices.get(getIndexRequest, RequestOptions.DEFAULT);//获取映射信息MapString, MappingMetadata mappings response.getMappings();for (String key: mappings.keySet()){System.out.println(key : mappings.get(key).getSourceAsMap());}}最后获得的结果是这一部分 解释代码 key索引名称 mappings.get(key)索引对象 mappings.get(key).getSourceAsMap()将数据转换为map集合
9.3.3 删除索引 /*** 删除索引*/Testvoid deleteIndex() throws IOException {//获取操作索引的对象IndicesClient indices client.indices();//根据索引名称删除DeleteIndexRequest request new DeleteIndexRequest(movice);AcknowledgedResponse response indices.delete(request, RequestOptions.DEFAULT);//成功返回trueboolean acknowledged response.isAcknowledged();System.out.println(acknowledged);}9.3.4 判断索引是否存在 /*** 判断索引是否存在*/Testvoid existsIndex() throws IOException {//获取操作索引的对象IndicesClient indices client.indices();//根据索引名称删除GetIndexRequest request new GetIndexRequest(movice);boolean exists indices.exists(request, RequestOptions.DEFAULT);System.out.println(exists);}9.4 文档相关重点
9.4.1 添加文档
按照这样的思路去撰写 但是一般我们不这样存入数据不会一个个put而是从数据库中拉取数据封装成对象存入文档
升级改造
创建索引的类movice类
public class movice {private Integer id;private String title;private Integer price;private String address;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getTitle() {return title;}public void setTitle(String title) {this.title title;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price price;}public String getAddress() {return address;}public void setAddress(String address) {this.address address;}Overridepublic String toString() {return movice{ id id , title title \ , price price , address address \ };}
}使用类传入数据 /*** 添加文档(升级改造):使用对象作为数据*/Testvoid addDoc2() throws IOException {movice movice new movice();movice.setId(1); //此为索引IDmovice.setTitle(国产动作电影我被修改了);movice.setPrice(40);movice.setAddress(香港);//将对象转换为jsonString data JSON.toJSONString(movice);// 获取操作文档的对象文档的ID设置为1IndexRequest request new IndexRequest(movice).id(1).source(data,XContentType.JSON);IndexResponse response client.index(request, RequestOptions.DEFAULT);//索引IDSystem.out.println(response.getId());}9.4.2 修改文档
还是添加相关的操作只不过若添加的时候ID已经存在了就会被修改。不存在就会创建新的
9.4.3 根据ID查询文档 /*** 查询文档根据ID查询*/Testvoid queryDoc2() throws IOException {//GetRequest getrequest new GetRequest(movice); //指定索引名称GetRequest getrequest new GetRequest(1); //指定索引IDGetResponse response client.get(getrequest, RequestOptions.DEFAULT);//将对象的source部分数据以字符串的形式处理前面是以map形式处理System.out.println(response.getSourceAsString());}response相应也就是这一部分数据。
9.4.4 删除文档 /*** 根据ID删除文档*/Testvoid deleteDoc2() throws IOException {DeleteRequest request new DeleteRequest(1);DeleteResponse response client.delete(request, RequestOptions.DEFAULT);//获取数据中的_id注意不是_source中的id哦System.out.println(response.getId());}我们可能会疑惑这个response到底是什么数据这就是response全部数据我们可以获取_id_source_index等等但是直接
总结其实可以发现使用代码进行索引文档的操作时候。一定要了解5-8章节的细节如何指定ID查询增删查操作返回的数据。然后再去看代码一一对照。 在代码中
先获得RestHighLevelClient对象 client熟记如何获取上述所操作的类梳理 非常清晰的看到如何使用代码操作ES。
在下一篇文章将会介绍更高级的操作熟悉企业开发。