原文链接:https://gaoyubo.cn/blogs/52ef5bf7.html

一、Elasticsearch 架构设计

Elasticsearch 架构层:

Elasticsearch 五层架构设计图:

说明:

  • Elasticsearch是基于Lucene架构实现的,所以其核心层为Lucene
  • Elasticsearch 目前支持HTTPThriftMemcache三种协议,默认是HTTP
  • JMX指在Elasticsearch中对 Java 的管理架构,用来管理Elasticsearch应用

二、Docker部署

2.1加载es镜像

因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:

docker network create es-net
# 导入数据
docker load -i es.tar

同理还有kibana的tar包也需要这样做。

# 导入数据
docker load -i kibana.tar

2.2运行镜像

docker run -d \
--name es \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-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.name=es-docker-cluster":设置集群名称
  • -e "http.host=0.0.0.0":监听的地址,可以外网访问
  • -e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小
  • -e "discovery.type=single-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:端口映射配置

此时访问9200端口,可以访问到已经部署成功

2.3部署kibana

kibana可以提供一个elasticsearch的可视化界面

docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601 \
kibana:7.12.1
  • --network es-net :加入一个名为es-net的网络中,与elasticsearch在同一个网络中
  • -e ELASTICSEARCH_HOSTS=http://es:9200":设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch
  • -p 5601:5601:端口映射配置

部署成功

2.4离线安装ik插件

查看数据卷目录

安装插件需要知道elasticsearch的plugins目录位置,而我们用了数据卷挂载,因此需要查看elasticsearch的数据卷目录,通过下面命令查看:

docker volume inspect es-plugins

说明plugins目录被挂载到了:/var/lib/docker/volumes/es-plugins/_data 这个目录中。

上传插件


# 重启容器
docker restart es
# 查看es日志
docker logs -f es

扩展词词典

词汇需要不断的更新,IK分词器提供了扩展词汇的功能。

1)打开IK分词器config目录:

2)在IKAnalyzer.cfg.xml配置文件内容添加:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典-->
<entry key="ext_dict">ext.dic</entry>
</properties>

3)新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改

奥力给

4)重启elasticsearch

docker restart es

日志中已经成功加载ext.dic配置文件

注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑

三、索引库操作

3.1创建索引库

索引库就类似数据库表,mapping映射就类似表的结构。

基本语法:

  • 请求方式:PUT
  • 请求路径:/索引库名,可以自定义
  • 请求参数:mapping映射
PUT /index1
{
"mappings": {
"properties": {
"info": {
"type": "text",
"analyzer": "ik_smart"
},
"email": {
"type": "keyword",
"index": false
},
"name": {
"type": "object",
"properties": {
"firstName": {
"type": "keyword"
},
"lastName": {
"type": "keyword"
}
}
}
}
}
}

3.2查询索引库

基本语法

  • 请求方式:GET

  • 请求路径:/索引库名

  • 请求参数:无

3.3修改索引库

倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引。因此索引库一旦创建,无法修改mapping

虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。

语法说明

PUT /索引库名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}

四、文档操作

4.1添加文档

POST /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    "字段3": {
        "子属性1": "值3",
        "子属性2": "值4"
    },
// ...
}

4.2查询文档

语法:

GET /{索引库名称}/_doc/{id}

4.3.删除文档

删除使用DELETE请求,同样,需要根据id进行删除:

语法:

DELETE /{索引库名}/_doc/id值

4.4修改文档

修改有两种方式:

  • 全量修改:直接覆盖原来的文档
  • 增量修改:修改文档中的部分字段

全量修改

全量修改是覆盖原来的文档,其本质是:

  • 根据指定的id删除文档
  • 新增一个相同id的文档

类似于Java中的HashMap的put操作

PUT /{索引库名}/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
// ... 略
}

增量修改

增量修改是只修改指定id匹配的文档中的部分字段。

语法:

POST /{索引库名}/_update/文档id
{
    "doc": {
"字段名": "新的值",
}
}

五、RestAPI操作索引库

官方地址

其中的Java Rest Client又包括两种:

  • Java Low Level Rest Client
  • Java High Level Rest Client

译文:

Java底层REST客户端:Elasticsearch的官方底层客户端。它允许通过http与Elasticsearch集群通信。将请求编组和响应反编组留给用户。它与所有Elasticsearch版本兼容。

Java高级REST客户端:Elasticsearch的官方高级客户端。基于底层客户端,它公开了特定于API的方法,并负责请求编组和响应反编组。

我们学习的是Java HighLevel Rest Client客户端API

mapping映射分析

创建索引库,最关键的是mapping映射,而mapping映射要考虑的信息包括:

  • 字段名
  • 字段数据类型
  • 是否参与搜索
  • 是否需要分词
  • 如果分词,分词器是什么?

其中:

  • 字段名、字段数据类型,可以参考数据表结构的名称和类型
  • 是否参与搜索要分析业务来判断,例如图片地址,就无需参与搜索
  • 是否分词呢要看内容,内容如果是一个整体就无需分词,反之则要分词
  • 分词器,我们可以统一使用ik_max_word
  • id主键特殊,不实用long,而是使用keyword

MySQL数据结构如下:

CREATE TABLE `tb_hotel` (
  `id` bigint(20) NOT NULL COMMENT '酒店id',
  `name` varchar(255) NOT NULL COMMENT '酒店名称;例:7天酒店',
  `address` varchar(255) NOT NULL COMMENT '酒店地址;例:航头路',
  `price` int(10) NOT NULL COMMENT '酒店价格;例:329',
  `score` int(2) NOT NULL COMMENT '酒店评分;例:45,就是4.5分',
  `brand` varchar(32) NOT NULL COMMENT '酒店品牌;例:如家',
  `city` varchar(32) NOT NULL COMMENT '所在城市;例:上海',
  `star_name` varchar(16) DEFAULT NULL COMMENT '酒店星级,从低到高分别是:1星到5星,1钻到5钻',
  `business` varchar(255) DEFAULT NULL COMMENT '商圈;例:虹桥',
  `latitude` varchar(32) NOT NULL COMMENT '纬度;例:31.2497',
  `longitude` varchar(32) NOT NULL COMMENT '经度;例:120.3925',
  `pic` varchar(255) DEFAULT NULL COMMENT '酒店图片;例:/img/1.jpg',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

根据MySQL表结构构造了如下的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",
"copy_to": "all"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}

此时会发现多出一个all字段:因为如果很多字段都需要倒排索引,那么性能就会下降,ES可以使用cpoy_to属性将当前字段拷贝到指定字段,在指定字段里,统一构造倒排索引。

location:地理坐标,里面包含精度、纬度

初始化RestClient

  1. 引入es的RestHighLevelClient依赖:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>

因为SpringBoot进行了自动依赖管理,默认的ES版本是7.6.2,所以需要额外指定固定版本。

  1. 初始化RestHighLevelClient:

初始化的代码如下:

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://xxx:9200")
));

创建索引库

 @Test
void hotelIndexCreate() throws IOException {
//获取create请求
CreateIndexRequest createIndexRequest = new CreateIndexRequest("hotel");
//添加请求参数
createIndexRequest.source(ESTemplate.CreateHotelTemplate(), XContentType.JSON);
//发送请求
client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
}

添加请求参数时的json语句,就是dev Tools中编写的json语句

删除索引库

@Test
void testDeleteHotelIndex() throws IOException {
// 1.创建Request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2.发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}

判断索引库是否存在

@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 ? "索引库已经存在!" : "索引库不存在!");
}

索引库操作的基本步骤:

  • 初始化RestHighLevelClient
  • 创建XxxIndexRequest。XXX是Create、Get、Delete
  • 准备DSL( Create时需要,其它是无参)
  • 发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete

六、RestAPI操作文档

添加文档

  @Test
void hotelDocCreate() throws IOException {
//获取mysql表hotel记录
Hotel hotel = hotelService.getById(36934L);
//转化为doc
HotelDoc hotelDoc = new HotelDoc(hotel); //获取create请求
IndexRequest request = new IndexRequest("hotel" ).id(hotelDoc.getId().toString());
//添加请求参数
request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
//发送请求(文档操作,不需要indices)
client.index(request,RequestOptions.DEFAULT);
}

查询文档

@Test
void testGetDocumentById() throws IOException {
// 1.准备Request
GetRequest request = new GetRequest("hotel", "36934");
// 2.发送请求,得到响应
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3.解析响应结果
String json = response.getSourceAsString(); HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}

修改文档

  • 全量修改:本质是先根据id删除,再新增
  • 增量修改:修改文档中的指定字段值

在RestClient的API中,全量修改与新增的API完全一致,判断依据是ID:

  • 如果新增时,ID已经存在,则修改
  • 如果新增时,ID不存在,则新增
 @Test
void testUpdateDocument() throws IOException {
// 1.准备Request
UpdateRequest request = new UpdateRequest("hotel", "36934");
// 2.准备请求参数
request.doc(
"price", "100000000",
"starName", "四钻"
);
// 3.发送请求
client.update(request, RequestOptions.DEFAULT);
}

删除文档

@Test
void testDeleteDocument() throws IOException {
// 1.准备Request
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}

批量添加文档

步骤如下:

  • 利用mybatis-plus查询酒店数据
  • 将查询到的酒店数据(Hotel)转换为文档类型数据(HotelDoc)
  • 利用JavaRestClient中的BulkRequest批处理,实现批量新增文档

@Test

void testBulkRequest() throws IOException {

// 批量查询酒店数据

List hotels = hotelService.list();

// 1.创建Request
BulkRequest request = new BulkRequest();
// 2.准备参数,添加多个新增的Request
for (Hotel hotel : hotels) {
// 2.1.转换为文档类型HotelDoc
HotelDoc hotelDoc = new HotelDoc(hotel);
// 2.2.创建新增文档的Request对象
request.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc), XContentType.JSON));
}
// 3.发送请求
client.bulk(request, RequestOptions.DEFAULT);

}

ElasticSearch-1的更多相关文章

  1. Elasticsearch之java的基本操作一

    摘要   接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...

  2. Elasticsearch 5.0 中term 查询和match 查询的认识

    Elasticsearch 5.0 关于term query和match query的认识 一.基本情况 前言:term query和match query牵扯的东西比较多,例如分词器.mapping ...

  3. 以bank account 数据为例,认识elasticsearch query 和 filter

    Elasticsearch 查询语言(Query DSL)认识(一) 一.基本认识 查询子句的行为取决于 query context filter context 也就是执行的是查询(query)还是 ...

  4. Ubuntu 14.04中Elasticsearch集群配置

    Ubuntu 14.04中Elasticsearch集群配置 前言:本文可用于elasticsearch集群搭建参考.细分为elasticsearch.yml配置和系统配置 达到的目的:各台机器配置成 ...

  5. ElasticSearch 5学习(10)——结构化查询(包括新特性)

    之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...

  6. ElasticSearch 5学习(9)——映射和分析(string类型废弃)

    在ElasticSearch中,存入文档的内容类似于传统数据每个字段一样,都会有一个指定的属性,为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成字符串值,Elasticsearc ...

  7. .net Elasticsearch 学习入门笔记

    一. es安装相关1.elasticsearch安装  运行http://localhost:9200/2.head插件3.bigdesk插件安装(安装细节百度:windows elasticsear ...

  8. 自己写的数据交换工具——从Oracle到Elasticsearch

    先说说需求的背景,由于业务数据都在Oracle数据库中,想要对它进行数据的分析会非常非常慢,用传统的数据仓库-->数据集市这种方式,集市层表会非常大,查询的时候如果再做一些group的操作,一个 ...

  9. 如何在Elasticsearch中安装中文分词器(IK+pinyin)

    如果直接使用Elasticsearch的朋友在处理中文内容的搜索时,肯定会遇到很尴尬的问题--中文词语被分成了一个一个的汉字,当用Kibana作图的时候,按照term来分组,结果一个汉字被分成了一组. ...

  10. jar hell & elasticsearch ik 版本问题

    想给es 安装一个ik 的插件, 我的es 是 2.4.0, 下载了一个版本是 1.9.5, [2016-10-09 16:56:26,248][INFO ][node ] [node-2] init ...

随机推荐

  1. Ubuntu 14.04解决登录界面无限循环的方法

    在Ubuntu下配置Android的环境时,想像在Windows中那样在终端中直接启动adb,以为Linux和Windows一样,将adb的路径添加到环境变量中,于是将adb的路径也export到/e ...

  2. C转C++ 个人总结

    # C转C++ 个人总结 1.使用C++的好处 2.using namespace std 3.cin和cout #include<iostream> //必备的头文件 using nam ...

  3. IDEA工具第一篇:细节使用-习惯设置

    安装好Idea后,直接上手clone代码进入编码时代,有没有那么一刻你会觉用起来没有那么顺手流畅呢? 下面是关于 [Windows] 下安装idea的一些习惯设置[ Mac大致一样 ] 一.修改系统文 ...

  4. 造轮子之集成GraphQL

    先简单对比以下GraphQL和WebAPI:GraphQL和Web API(如RESTful API)是用于构建和提供Web服务的不同技术. 数据获取方式: Web API:通常使用RESTful A ...

  5. sqlserver在设计表结构时,如何选择字段的数据类型

    在设计表结构时,选择适当的字段数据类型是非常重要的,它会直接影响数据库的性能.存储空间和数据的完整性.以下是在 SQL Server 中选择字段数据类型时的一些建议和理由: 1. 整数类型:在 SQL ...

  6. Vue之style的用法

    Vue中style的用法总结如下: v-bind:style  简写:style 1.基本用法 <!DOCTYPE html> <html lang="en"&g ...

  7. ExtJS的使用方法汇总(1)——配置和表格控件使用

    在网上差一些关于ExtJS的相关资料,看到这篇博客写的不错,拿出来分享一下! 博客文章:ExtJS的使用方法汇总(1)--配置和表格控件使用              ExtJS的使用方法汇总(2)- ...

  8. 怎么用Python写一个浏览器集群框架

    这是做什么用的 框架用途 在采集大量新闻网站时,不可避免的遇到动态加载的网站,这给配模版的人增加了很大难度.本来配静态网站只需要两个技能点:xpath和正则,如果是动态网站的还得抓包,遇到加密的还得j ...

  9. Mach-O Inside: 命令行工具集 otool objdump od 与 dwarfdump

    1 otool otool 命令行工具用来查看 Mach-O 文件的结构. 1.1 查看文件头 otool -h -v 文件路径 -h选项表明查看 Mach-O 文件头. -v 选项表明将展示的内容进 ...

  10. 聊聊RNN&LSTM

    RNN 用于解决输入数据为,序列到序列(时间序列)数据,不能在传统的前馈神经网络(FNN)很好应用的问题.时间序列数据是指在不同时间点上收集到的数据,这类数据反映了某一事物.现象等随时间的变化状态或程 ...