logo头像

分享技术,品味人生

微服务-ES使用

Day05- ES安装使用

本章小结:

  1. 同步

  • idea的alt+insert, 自动添加测试代码、getset方法很哇塞!
  • idea在方法参数上用ctrl+p,效果很赞

[TOC]

No.01-ES、Kibana、IK安装使用

1、初识ES

  • ES是什么
    • 来源lucene,因lucene开发维护难度大,不支持水平扩展、局限java、接口不优化等问题而在2010年问世
  • ES的组成部分
    • 指的是Elastic Stack,主要包括可视化kibana,存储搜索引擎ElasticSearch,数据抓取Logstash、Beats
  • 什么是倒排索引
    • 相比正向索引,对行数据(文档)进行分词、排序形成的索引表,使用时先查倒排索引再查一般索引而得到json
  • ES与Mysql的关系
    • 小量数据,高效索引建议直接用mysql
    • 强事务增删改必须用mysql!数据及时同步到es即可。
    • es的优势在于面向海量数据、水平扩展、复杂查询全表遍历的情况下效果显著!

2、ElasticSearch安装

  • 部署单点es

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

docker network create es-net

运行docker命令,部署单点es:

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.14.2

命令解释:

  • -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:端口映射配置

在浏览器中输入:http://192.168.20.165:9200 即可看到elasticsearch的响应结果:

3、Kibana安装

运行docker命令,部署kibana

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

kibana启动一般比较慢,需要多等待一会,可以通过命令:

docker logs -f kibana

查看运行日志,当查看到==日志出现5601端口号==,说明成功:

此时,在浏览器输入地址访问:http://192.168.20.165:5601,即可看到结果

4、Kibana DevTools基本操作(含分词器调用)

image-20211019171159554

  • 一般操作

    ```json
    GET _search
    {
    “query”: {
    “match_all”: {}
    }
    }

同kibana首页

GET /

对比分词器,standard, ik_smart, ik_max_word

POST /_analyze
{
“analyzer”: “ik_smart”,
“text”: “传智播客的Java就业超过90%,奥力给!!”
}


![image-20211019171515356](http://image.iyyxx.com/i/2022/08/11/62f459a56f7d2.png)



### 5、IK安装、分词器插件升级

- IK安装

```sh
# 卷来自于es安装时指定的plugins目录, 操作只是找到目录,创建一个ik文件夹,然后上传压缩包、解压,重启es即可

[root@docker volumes]# docker volume inspect es-plugins
[
    {
        "CreatedAt": "2021-10-19T15:09:25+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/es-plugins/_data",
        "Name": "es-plugins",
        "Options": null,
        "Scope": "local"
    }
]
[root@docker volumes]# cd /var/lib/docker/volumes/es-plugins/_data
[root@docker _data]# mkdir ik
[root@docker _data]# cd ik
[root@docker ik]# rz
rz waiting to receive.
Starting zmodem transfer.  Press Ctrl+C to cancel.
Transferring elasticsearch-analysis-ik-7.14.2.zip...
  100%    4398 KB    4398 KB/sec    00:00:01       0 Errors  

[root@docker ik]# unzip elasticsearch-analysis-ik-7.14.2.zip 
[root@docker ik]# mv elasticsearch-analysis-ik-7.14.2.zip /tmp/
[root@docker ik]# docker restart es
  • 分词器增加扩展分词、停用分词

    • 修改配置,添加扩展
    [root@docker ik]# cd /var/lib/docker/volumes/es-plugins/_data/ik/config/
    [root@docker config]# vim 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>
               <!--用户可以在这里配置自己的扩展停止词字典-->
              <entry key="ext_stopwords">stopwords.dic</entry>
              <!--用户可以在这里配置远程扩展字典 -->
              <!-- <entry key="remote_ext_dict">words_location</entry> -->
              <!--用户可以在这里配置远程扩展停止词字典-->
              <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
      </properties>
      
    • 添加词库到扩展、停用

      [root@docker config]# touch ext.dic
      [root@docker config]# echo "传智播客" >> ext.dic
      [root@docker config]# echo "奥利给" >> ext.dic
      [root@docker config]# echo "的" >> stopwords.dic
      [root@docker ik]# docker restart es
      
  • 使用

    ```json

对比分词器,standard, ik_smart, ik_max_word

POST /_analyze
{
“analyzer”: “ik_smart”,
“text”: “传智播客的Java就业超过90%,奥力给!!”
}




`效果`

![image-20211019171515356](http://image.iyyxx.com/i/2022/08/11/62f459a56f7d2.png)

## No.02-Kibana DevTools操作

### 1、操作索引库(CRUD)

`修改部分只允许新增字段`

```json
# 创建索引库
PUT /iyyxx
{
"mappings": {
  "properties": {
    "test": {
      "type": "text",
      "analyzer": "ik_smart"
    },
    "age": {
      "type": "text",
      "index": false
    },
    "name": {
      "properties": {
        "firstName": {
          "type": "keyword"
        },
        "lastName": {
          "type": "keyword"
        }
      }
    }
  }
}
}

# 查看索引库
GET /iyyxx

# 删除索引库
DELETE /iyyxx

# 修改索引库(添加字段,不允许修改)
PUT /iyyxx/_mapping
{
"properties": {
  "newField": {
    "type": "keyword"
  }
}
}

2、操作文档

# 新增文档(存在就是先删除)
POST /iyyxx/_doc/1
{
  "test":"测试",
  "age":"15",
  "name":{
    "lastName":"三",
    "firstName":"张"
  },
  "newField":"ttt"
}

# 查询文档
GET /iyyxx/_doc/1

# 全量替换
PUT /iyyxx/_doc/1
{
  "test":"测试"
}

# 部分修改
POST /iyyxx/_update/1
{
  "doc": {
    "test":"测试22"
  }
}

# 删除文档
DELETE /iyyxx/_doc/1

No.03-RestClient操作

使用培训机构提供的demo工程和数据库脚本

  • pom依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.10.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <groupId>org.example</groupId>
        <artifactId>hotel-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>hotel-demo</name>
        <description>xxxxxxxxxxxxxxxxx</description>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.4.2</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--FastJson-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.71</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    
  • pojo/Hotel

    package com.iyyxx.hotel.pojo;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    @Data
    @TableName("tb_hotel")
    public class Hotel {
        @TableId(type = IdType.INPUT)
        private Long id;
        private String name;
        private String address;
        private Integer price;
        private Integer score;
        private String brand;
        private String city;
        private String starName;
        private String business;
        private String longitude;
        private String latitude;
        private String pic;
    }
    
  • pojo/HotelDoc

    package com.iyyxx.hotel.pojo;
    
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    public class HotelDoc {
        private Long id;
        private String name;
        private String address;
        private Integer price;
        private Integer score;
        private String brand;
        private String city;
        private String starName;
        private String business;
        private String location;
        private String pic;
    
        public HotelDoc(Hotel hotel) {
            this.id = hotel.getId();
            this.name = hotel.getName();
            this.address = hotel.getAddress();
            this.price = hotel.getPrice();
            this.score = hotel.getScore();
            this.brand = hotel.getBrand();
            this.city = hotel.getCity();
            this.starName = hotel.getStarName();
            this.business = hotel.getBusiness();
            this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
            this.pic = hotel.getPic();
        }
    }
    
  • mapper/HotelMapper

    package com.iyyxx.hotel.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.iyyxx.hotel.pojo.Hotel;
    
    public interface HotelMapper extends BaseMapper<Hotel> {
    }
    
  • service/IHotelService

    package com.iyyxx.hotel.service;
    
    import com.baomidou.mybatisplus.extension.service.IService;
    import com.iyyxx.hotel.pojo.Hotel;
    
    public interface IHotelService extends IService<Hotel> {
    }
    
  • service/impl/HotelService

    package com.iyyxx.hotel.service.impl;
    
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.iyyxx.hotel.mapper.HotelMapper;
    import com.iyyxx.hotel.pojo.Hotel;
    import com.iyyxx.hotel.service.IHotelService;
    import org.springframework.stereotype.Service;
    
    @Service
    public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
    }
    
  • 入口程序HotelDemoApplication

    package com.iyyxx.hotel;
    
    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    
    @MapperScan("com.iyyxx.hotel.mapper")
    @SpringBootApplication
    public class HotelDemoApplication {
    
      public static void main(String[] args) {
        SpringApplication.run(HotelDemoApplication.class, args);
      }
    }
    

1、操作索引库

  • pom依赖增加es,并强制覆盖父工程对es的版本限制

    <properties>
        <elasticsearch.version>7.14.2</elasticsearch.version>
    </properties>
    
    <!-- elasticSearch依赖 -->
    <dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    </dependency>
    
  • 添加测试程序

    package com.iyyxx.hotel;
    
    import org.apache.http.HttpHost;
    import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
    import org.elasticsearch.client.RequestOptions;
    import org.elasticsearch.client.indices.CreateIndexRequest;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.elasticsearch.client.indices.GetIndexRequest;
    import org.elasticsearch.common.xcontent.XContentType;
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    
    import java.io.IOException;
    
    import static com.iyyxx.hotel.constants.HotelConstants.MAPPING_TEMPLATE;
    
    public class HotelIndexTest {
      private RestHighLevelClient restHighLevelClient;
    
      @BeforeEach
      void setUp() {
        restHighLevelClient =
            new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.20.165:9200")));
      }
    
      @AfterEach
      void tearDown() throws IOException {
        this.restHighLevelClient.close();
      }
    
      @Test
      void testCreateHotelIndex() throws IOException {
        // 创建对象
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        // 配置请求参数
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        // 发起请求
        restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
      }
    
      @Test
      void testDeleteHotelIndex() throws IOException {
    
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");
    
        restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
      }
    
      @Test
      void testExistsHotelIndex() throws IOException {
    
        GetIndexRequest request = new GetIndexRequest("hotel");
        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
      }
    
    
    }
    

2、操作文档

文档操作类似索引操作,多了数据增删改、批量导入

package com.iyyxx.hotel;

import com.alibaba.fastjson.JSON;
import com.iyyxx.hotel.pojo.Hotel;
import com.iyyxx.hotel.pojo.HotelDoc;
import com.iyyxx.hotel.service.IHotelService;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.List;

import static com.iyyxx.hotel.constants.HotelConstants.MAPPING_TEMPLATE;

@SpringBootTest
public class HotelDocumentTest {

  @Autowired private IHotelService service;

  private RestHighLevelClient restHighLevelClient;

  @BeforeEach
  void setUp() {
    restHighLevelClient =
        new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.20.165:9200")));
  }

  @AfterEach
  void tearDown() throws IOException {
    this.restHighLevelClient.close();
  }

  @Test
  void test() {
    System.out.println(restHighLevelClient);
  }

  @Test
  void testIndexDocument() throws IOException {
    Hotel hotel = service.getById(38812L);
    HotelDoc doc = new HotelDoc(hotel);
    IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
    request.source(JSON.toJSONString(doc), XContentType.JSON);
    restHighLevelClient.index(request, RequestOptions.DEFAULT);
  }

  @Test
  void testGetDocument() throws IOException {
    GetRequest request = new GetRequest("hotel", "38812");
    GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
    String json = response.getSourceAsString();
    HotelDoc doc = JSON.parseObject(json, HotelDoc.class);
    System.err.println(doc);
  }

  @Test
  void testUpdateDocument() throws IOException {
    UpdateRequest request = new UpdateRequest("hotel", "38812");
    request.doc("score", 55, "starName", "三三钻");
    restHighLevelClient.update(request, RequestOptions.DEFAULT);
  }

  @Test
  void testDeleteDocument() throws IOException {
    DeleteRequest request = new DeleteRequest("hotel", "38812");
    restHighLevelClient.delete(request, RequestOptions.DEFAULT);
  }

  @Test
  void testBulkOperateDocument() throws IOException {
    BulkRequest request = new BulkRequest();
    List<Hotel> list = service.list();
    IndexRequest index;
    for (Hotel hotel : list) {
      HotelDoc doc = new HotelDoc(hotel);
      index = new IndexRequest("hotel").id(hotel.getId().toString());
      index.source(JSON.toJSONString(doc), XContentType.JSON);
      request.add(index);
    }
    restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
  }
}

评论系统未开启,无法评论!