深圳鸿天顺网站建设,建网站市场,电脑软件开发培训机构,免费ppt模板下载红色初识elasticsearch
什么是elasticsearch
elasticsearch是一款非常强大的开源搜索引擎#xff0c;可以帮助我们从海量数据中快速找到需要的内容。
elasticsearch结合kibana、Logstash、Beats#xff0c;也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域…初识elasticsearch
什么是elasticsearch
elasticsearch是一款非常强大的开源搜索引擎可以帮助我们从海量数据中快速找到需要的内容。
elasticsearch结合kibana、Logstash、Beats也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域。
elasticsearch是elastic stack的核心负责存储、搜索、分析数据。 elasticsearch的发展
Lucene是一个Java语言的搜索引擎类库是Apache公司的顶级项目由DougCutting于1999年研发。官网地址: https://lucene.apache.orgl。
Lucene的优势:
易扩展高性能(基于倒排索引)
Lucene的缺点:
只限于Java语言开发学习曲线陡峭不支持水平扩展
2004年Shay Banon基于Lucene开发了Compass
2010年Shay Banon重写了Compass取名为Elasticsearch。
官网地址: https://www.elastic.co/cn/目前最新的版本是:8.7.0
相比与luceneelasticsearch具备下列优势:
支持分布式可水平扩展提供Restful接口可被任何语言调用
为什么学习elasticsearch?
搜索引擎技术排名:
Elasticsearch:开源的分布式搜索引擎Splunk:商业项目Solr: Apache的开源搜索引擎
什么是elasticsearch?
一个开源的分布式搜索引擎可以用来实现搜索、日志统计、分析、 系统监控等功能
什么是elastic stack (ELK)?
是以elasticsearch为核心的技术栈包括beats、Logstash、kibana、elasticsearch
什么是Lucene?
是Apache的开源搜索引擎类库提供了搜索引擎的核心API
正向索引和倒排索引
传统数据库如MySQL采用正向索引例如给下表(tb_goods中的id创建索引: elasticsearch采用倒排索引:
文档 document) :每条数据就是一个文档词条term) :文档按照语义分成的词语 什么是文档和词条?
每一条数据就是一个文档对文档中的内容分词得到的词语就是词条
什么是正向索引?
基于文档id创建索引。查询词条时必须先找到文档而后判断是否包 含词条
什么是倒排索引?
对文档内容分词对词条创建索引并记录词条所在文档的信息。查询时先根据词条查询到文档id而后获取到文档
文档
elasticsearch是面向文档存储的可以是数据库中的一条商品数据一个订单信息。
文档数据会被序列化为json格式后存储在elasticsearch中。
索引(lndex)
索引(index) :相同类型的文档的集合映射mapping) :索引中文档的字段约束信息类似表的结构约束 概念对比 架构
Mysql:擅长事务类型操作可以确保数据的安全和一致性
Elasticsearch:擅长海量数据的搜索、分析、计算 文档:一条数据就是一个文档es中是Json格式字段:Json文档中的字段索引:同类型文档的集合映射:索引中文档的约束比如字段名称、类型
elasticsearch与数据库的关系:
数据库负责事务类型操作elasticsearch负责海量数据的搜索、分析、计算
安装elasticsearch、kibana
1.部署单点es
1.1.创建网络
因为我们还需要部署kibana容器因此需要让es和kibana容器互联。这里先创建一个网络
docker network create es-net1.2.加载镜像
这里我们采用elasticsearch的7.12.1版本的镜像这个镜像体积非常大接近1G。不建议大家自己pull。将镜像上传到虚拟机中然后运行命令加载即可
# 导入数据
docker load -i es.tar同理还有kibana的tar包也需要这样做。
1.3.运行
运行docker命令部署单点es
docker run -d \--name es \-e ES_JAVA_OPTS-Xms512m -Xmx512m \-e discovery.typesingle-node \-v es-data:/usr/share/elasticsearch/data \-v es-plugins:/usr/share/elasticsearch/plugins \--privileged \--network es-net \-p 9200:9200 \-p 9300:9300 \
elasticsearch:7.12.1命令解释
-e cluster.namees-docker-cluster设置集群名称-e http.host0.0.0.0监听的地址可以外网访问-e ES_JAVA_OPTS-Xms512m -Xmx512m内存大小-e discovery.typesingle-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授予逻辑卷访问权--network es-net 加入一个名为es-net的网络中-p 9200:9200端口映射配置
在浏览器中输入http://ip地址:9200 即可看到elasticsearch的响应结果 2.部署kibana
kibana可以给我们提供一个elasticsearch的可视化界面便于我们学习。
2.1.部署
运行docker命令部署kibana
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTShttp://es:9200 \
--networkes-net \
-p 5601:5601 \
kibana:7.12.1--network es-net 加入一个名为es-net的网络中与elasticsearch在同一个网络中-e ELASTICSEARCH_HOSTShttp://es:9200设置elasticsearch的地址因为kibana已经与elasticsearch在一个网络因此可以用容器名直接访问elasticsearch-p 5601:5601端口映射配置
kibana启动一般比较慢需要多等待一会可以通过命令
docker logs -f kibana查看运行日志当查看到下面的日志说明成功 此时在浏览器输入地址访问http://ip地址:5601即可看到结果
2.2.DevTools
kibana中提供了一个DevTools界面 这个界面中可以编写DSL来操作elasticsearch。并且对DSL语句有自动补全功能。
分词器
es在创建倒排索引时需要对文档分词;在搜索时需要对用户输入内容分词。但默认的分词规则对中文处理并不友好。我们在kibana的DevTools中测试:
# 测试分词器
POST /_analyze
{text: 霁华学Java,analyzer: standard
}语法说明:
POST:请求方式/_analyze:请求路径这里省略了http://192.168.150.101:9200有kibana帮我们补充请求参数json风格: analyzer:分词器类型这里是默认的standard分词器text:要分词的内容 处理中文分词一般会使用IK分词器。https://github.com/medcl/elasticsearch-analysis-ik
安装IK分词器
1.在线安装ik插件较慢
# 进入容器内部
docker exec -it elasticsearch /bin/bash# 在线下载并安装
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip#退出
exit
#重启容器
docker restart elasticsearch2.离线安装ik插件推荐
1查看数据卷目录
安装插件需要知道elasticsearch的plugins目录位置而我们用了数据卷挂载因此需要查看elasticsearch的数据卷目录通过下面命令查看:
docker volume inspect es-plugins显示结果
[{CreatedAt: 2023-04-29T04:11:4908:00,Driver: local,Labels: null,Mountpoint: /var/lib/docker/volumes/es-plugins/_data,Name: es-plugins,Options: null,Scope: local}
]说明plugins目录被挂载到了/var/lib/docker/volumes/es-plugins/_data 这个目录中。
2解压缩分词器安装包
下面我们需要把ik分词器解压缩重命名为ik
3上传到es容器的插件数据卷中
也就是/var/lib/docker/volumes/es-plugins/_data
4重启容器
# 4、重启容器
docker restart es# 查看es日志
docker logs -f es5测试
IK分词器包含两种模式 ik_smart最少切分 ik_max_word最细切分 ik分词器-拓展词库
要拓展ik分词器的词库只需要修改一个ik分词器目录中的config目录中的IKAnalyzer.cfg.xml文件:
?xml version1.0 encodingUTF-8?
!DOCTYPE properties SYSTEM http://java.sun.com/dtd/properties.dtd
propertiescommentIK Analyzer 扩展配置/comment!--用户可以在这里配置自己的扩展字典 --entry keyext_dictext.dic/entry
/properties然后在名为ext.dic的文件中添加想要拓展的词语即可:
白嫖
鸡你太美
奥力给ik分词器-停用词库
要禁用某些敏感词条只需要修改一个ik分词器目录中的config目录中的IKAnalyzer.cfg.xml文件:
?xml version1.0 encodingUTF-8?
!DOCTYPE properties SYSTEM http://java.sun.com/dtd/properties.dtd
propertiescommentIK Analyzer 扩展配置/comment!--用户可以在这里配置自己的扩展字典 --entry keyext_dictext.dic/entry!--用户可以在这里配置自己的扩展停止词字典--entry keyext_stopwordsstopword./entry
/properties然后在名为stopword.dic的文件中添加想要拓展的词语即可:
的
了
哦
嗯
啊索引库操作
mapping属性
mapping是对索引库中文档的约束常见的mapping属性包括:
type:字段数据类型常见的简单类型有: 字符串: text (可分词的文本)、keyword精确值例如:品牌、国家、ip地址)数值:long、integer、short、byte、double、float布尔: boolean日期:date对象:object index:是否创建索引默认为trueanalyzer:使用哪种分词器properties:该字段的子字段
创建索引库
ES中通过Restful请求操作索引库、文档。请求内容用DSL语句来表示。创建索引库和mapping的DSL语法如下:
{mappings: {properties: {字段名: {type: text,analyzer : ik_smart},字段名2: {type: keyword,index: false},字段名3: {properties: {子字段: {type : keyword}}},// ...略}}
}例如
# 创建索引库
PUT /jihua
{mappings: {properties: {info: {type: text,analyzer: ik_smart},email: {type: keyword,index: false},name: {type: object,properties: {firstName: {type: keyword},lastName: {type: keyword}}}}}
}查看、删除索引库
查看索引库语法:
GET /索引库名删除索引库的语法:
DELETE /索引库名修改索引库
索引库和mapping一旦创建无法修改但是可以添加新的字段语法如下:
PUT/索引库名/ _mapping
{properties : {新字段名:{type : integer}}
}例如
# 修改索引库
PUT /jihua/_mapping
{properties: {age: {type: integer}}
}文档操作
新增文档
新增文档的DSL语法如下:
POST /索引库名/_doc/文档id
{字段1:值1,字段2:值2,字段3: {子属性1:值3,子属性2:值4},//...
}例如
# 插入文档
POST /jihua/_doc/1
{info: 这里是介绍信息,email: ,name: {firstName: ji,lastName: hua},age: 21
}查询文档
查看文档语法:
GET /索引库名/_doc/文档id删除文档
DELETE /索引库名/_doc/文档id修改文档
方式一:全量修改会删除旧文档添加新文档
# 修改文档
PUT /jihua/_doc/1
{字段1:值1,字段2:值2,// ...略
}方式二:增量修改修改指定字段值
# 修改文档
POST /_update/_doc/1
{doc:{字段名:新的值}
}RestClient操作索引库
什么是RestClient
ES官方提供了各种不同语言的客户端用来操作ES。这些客户端的本质就是组装DSL语句通过http请求发送给ES。
官方文档地址: https://www.elastic.co/guide/en/elasticsearch/client/index.html 案例
利用JavaRestClient实现创建、删除索引库判断索引库是否存在
根据课前资料提供的酒店数据创建索引库索引库名为hotelmapping属性根据数据库结构定义。
基本步骤如下: 导入课前资料Demo 分析数据结构定义mapping属性 mapping要考虑的问题: 字段名、数据类型、是否参与搜索、是否分词、如果分词分词器是什么? ES中支持两种地理坐标数据类型: geo_point:由纬度latitude和经度( longitude确定的一个点。例如:“32.8752345,120.2981576”geo_shape:有多个geo_point组成的复杂几何图形。例如一条直线 “LINESTRING (-77.03653 38.897676,-77.009051 38.889939)” 字段拷贝可以使用copy_to属性将当前字段拷贝到指定字段。示例: all: {type : text,analyzer : ik_max_word
},
brand: {type : keyword,copy_to: all
}最终的mapping # 酒店的mapping
PUT /hotel
{mappings: {properties: {id: {type: keyword},name: {type: text,analyzer: ik_max_word,copy_to: all},address: {type: keyword,index: false},price: {type: integer},score: {type: integer},brand: {type: keyword,copy_to: all},city: {type: keyword},starName: {type: keyword},business: {type: keyword,copy_to: all},location: {type: geo_point},pic: {type: keyword,index: false},all: {type: text,analyzer: ik_max_word}}}
}初始化JavaRestClient 引入es的RestHighLevelclient依赖: !--elasticsearch--
dependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-high-level-client/artifactIdversion7.12.1/version
/dependency因为SpringBoot默认的ES版本是7.6.2所以我们需要覆盖默认的ES版本: propertiesjava.version1.8/java.versionelasticsearch.version7.12.1/elasticsearch.version
/properties初始化RestHighLevelClient: package cn.itcast.hotel;import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;import java.io.IOException;public class HotelIndexTest {private RestHighLevelClient client;Testvoid testInit() {System.out.println(client);}BeforeEachvoid setUp() {this.client new RestHighLevelClient(RestClient.builder(HttpHost.create(http://192.168.5.131:9200)));}AfterEachvoid tearDown() throws IOException {this.client.close();}
}利用JavaRestClient创建索引库 package cn.itcast.hotel.constants;public class HotelConstants {public static final String MAPPING_TEMPLATE {\n \mappings\: {\n \properties\: {\n \id\: {\n \type\: \keyword\\n },\n \name\: {\n \type\: \text\,\n \analyzer\: \ik_max_word\,\n \copy_to\: \all\\n },\n \address\: {\n \type\: \keyword\,\n \index\: false\n },\n \price\: {\n \type\: \integer\\n },\n \score\: {\n \type\: \integer\\n },\n \brand\: {\n \type\: \keyword\,\n \copy_to\: \all\\n },\n \city\: {\n \type\: \keyword\\n },\n \starName\: {\n \type\: \keyword\\n },\n \business\: {\n \type\: \keyword\,\n \copy_to\: \all\\n },\n \location\: {\n \type\: \geo_point\\n },\n \pic\: {\n \type\: \keyword\,\n \index\: false\n },\n \all\: {\n \type\: \text\,\n \analyzer\: \ik_max_word\\n }\n }\n }\n };
}Test
void createHotelIndex() throws IOException {//1.创建Request对象CreateIndexRequest request new CreateIndexRequest(hotel);//2.准备请求的参数:DSL语句request.source(MAPPING_TEMPLATE, XContentType.JSON);//3.发送请求client.indices().create(request, RequestOptions.DEFAULT);
}利用JavaRestClient删除索引库 Test
void testDeleteHotelIndex() throws IOException {//1.创建Request对象DeleteIndexRequest request new DeleteIndexRequest(hotel);//2.发送请求client.indices().delete(request, RequestOptions.DEFAULT);
}利用JavaRestClient判断索引库是否存在 Test
void testExistsHotelIndex() throws IOException {//1.创建Request对象GetIndexRequest request new GetIndexRequest(hotel);//2.发送请求boolean exists client.indices().exists(request, RequestOptions.DEFAULT);//3.输出System.err.println(exists?索引库已经存在 : 索引库不存在);
}RestClient操作文档
案例1
利用JavaRestClient实现文档的CRUD
去数据库查询酒店数据导入到hotel索引库实现酒店数据的CRUD。基本步骤如下: 初始化JavaRestClient 新建一个测试类实现文档相关操作并且完成JavaRestClient的初始化 public class ElasticsearchDocumentTest {//客户端private RestHighLevelClient client;BeforeEachvoid setUp() {this.client new RestHighLevelClient(RestClient.builder(HttpHost.create(http://192.168.5.131:9200)));}AfterEachvoid tearDown() throws IOException {this.client.close();}
}利用JavaRestClient新增酒店数据 先查询酒店数据然后给这条数据创建倒排索引即可完成添加: Test
void testAddDocument() throws IOException {//根据id查询酒店数据Hotel hotel hotelService.getById(61083L);//转换为文档类型HotelDoc hotelDoc new HotelDoc(hotel);//1.准备Request对象IndexRequest request new IndexRequest(hotel).id(hotel.getId().toString());//2.准备Json文档request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);//3.发送请求client.index(request, RequestOptions.DEFAULT);
}利用JavaRestClient根据id查询酒店数据 根据id查询到的文档数据是json需要反序列化为java对象: Test
void testGetDocumentById() throws IOException {//1.创建request对象GetRequest request new GetRequest(hotel, 61083);//2.发送请求得到结果GetResponse response client.get(request, RequestOptions.DEFAULT);//3.解析结果String json response.getSourceAsString();HotelDoc hotelDoc JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc);
}利用JavaRestClient删除酒店数据 修改文档数据有两种方式: 方式一:全量更新。再次写入id一样的文档就会删除旧文档添加新文档(同新增) 方式二:局部更新。只更新部分字段 Test
void testUpdateDocument() throws IOException {// 1.准备RequestUpdateRequest request new UpdateRequest(hotel, 61083);// 2.准备请求参数request.doc(price, 952,starName, 四钻);// 3.发送请求client.update(request, RequestOptions.DEFAULT);
}利用lavaRestClient修改酒店数据 Test
void testDeleteDocument() throws IOException {// 1.准备RequestDeleteRequest request new DeleteRequest(hotel, 61083);// 2.发送请求client.delete(request, RequestOptions.DEFAULT);
}案例2
利用JavaRestClient批量导入酒店数据到ES
需求:批量查询酒店数据然后批量导入索引库中 思路:
利用mybatis-plus查询酒店数据将查询到的酒店数据(Hotel)转换为文档类型数据HotelDoc)利用JavaRestClient中的Bulk批处理实现批量新增文档
Test
void testBulkRequest() throws IOException {//批量查询数据库ListHotel hotels hotelService.list();// 1.创建RequestBulkRequest request new BulkRequest();// 2.准备参数添加多个新增的Requestfor (Hotel hotel : hotels) {//转换为文档类型HotelDocHotelDoc hotelDoc new HotelDoc(hotel);//创建新增文档的Request对象request.add(new IndexRequest(hotel).id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));}// 3.发送请求client.bulk(request, RequestOptions.DEFAULT);
}t DeleteRequest request new DeleteRequest(“hotel”, “61083”); // 2.发送请求 client.delete(request, RequestOptions.DEFAULT); } ## 案例2利用JavaRestClient**批量导入**酒店数据到ES需求:批量查询酒店数据然后批量导入索引库中
思路:1. 利用mybatis-plus查询酒店数据
2. 将查询到的酒店数据(Hotel)转换为文档类型数据HotelDoc)
3. 利用JavaRestClient中的Bulk批处理实现批量新增文档java
Test
void testBulkRequest() throws IOException {//批量查询数据库ListHotel hotels hotelService.list();// 1.创建RequestBulkRequest request new BulkRequest();// 2.准备参数添加多个新增的Requestfor (Hotel hotel : hotels) {//转换为文档类型HotelDocHotelDoc hotelDoc new HotelDoc(hotel);//创建新增文档的Request对象request.add(new IndexRequest(hotel).id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));}// 3.发送请求client.bulk(request, RequestOptions.DEFAULT);
}