ES的使用(Elasticsearch)

ES的使用(Elasticsearch)

es是什么?
es是非关系型数据库,是分布式文档数据库,本质上是一个JSON 文本
为什么要用es?
搜索速度快,近乎是实时的存储、检索数据
怎么使用es?
1.下载es的包(环境要是jdk1.8及以上)(我的资源中有)
2.下载es的可视化界面包(我的资源中有)
3.java编写es的工具类
es与关系型数据库对比
在这里插入图片描述

1.下载es的包,解压,运行bat文件(windows)

下载地址:es官网下载地址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
elasticsearch.yml配置允许跨域

http.cors.enabled: true
http.cors.allow-origin: "*"

在这里插入图片描述

2.下载es的可视化界面包,解压,使用命令npm run start

下载地址:elasticsearch-head-master es可视化工具
在这里插入图片描述
打开http:localhost:9100
在这里插入图片描述

3.java编写es的工具类

引入es的依赖包

		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>elasticsearch-rest-high-level-client</artifactId>
			<version>6.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>elasticsearch-rest-client</artifactId>
			<version>6.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.elasticsearch</groupId>
			<artifactId>elasticsearch</artifactId>
			<version>6.2.4</version>
		</dependency>
package com.next.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;


@Service
@Slf4j
public class ESClient implements ApplicationListener<ContextRefreshedEvent> {

    private final static int CONNECT_TIMEOUT = 100;
    private final static int SOCKET_TIMEOUT = 60 * 1000;
    private final static int REQUEST_TIMEOUT = SOCKET_TIMEOUT;
    private RestHighLevelClient restHighLevelClient; //JDK8及以上
    private BasicHeader[] basicHeaders;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        try {
            initClient();
        } catch (Exception e) {
            log.error("es client init exception", e);
            try {
                Thread.sleep(1000);
            } catch (Exception e1) {

            }
            initClient();
        }
    }

    private void initClient() {
        log.info("es client init start");
        //请求头时允许的格式
        basicHeaders = new BasicHeader[]{
                new BasicHeader("Accept", "application/json;charset=UTF-8")};

        //es客户端连接设置初始化
        RestClientBuilder builder = RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"));
        builder.setDefaultHeaders(basicHeaders)
                //设置相关超时间配置
                .setRequestConfigCallback((RequestConfig.Builder configBuilder) -> {
                    configBuilder.setConnectTimeout(CONNECT_TIMEOUT);
                    configBuilder.setSocketTimeout(SOCKET_TIMEOUT);
                    configBuilder.setConnectionRequestTimeout(REQUEST_TIMEOUT);
                    return configBuilder;
                });
        restHighLevelClient = new RestHighLevelClient(builder);
        log.info("es client init end");
    }

    //es新增操作
    public IndexResponse index(IndexRequest indexRequest) throws Exception {
        try {
            return restHighLevelClient.index(indexRequest);
        } catch (Exception e) {
            log.error("es.index exception,indexRequest:{}", indexRequest, e);
            throw e;
        }
    }

    //更新操作
    public UpdateResponse update(UpdateRequest updateRequest) throws Exception {
        try {
            return restHighLevelClient.update(updateRequest, basicHeaders);
        } catch (Exception e) {
            log.error("es.update exception,updateRequest:{}", updateRequest, e);
            throw e;
        }
    }

    //查询
    public GetResponse get(GetRequest getRequest) throws Exception {
        try {
            return restHighLevelClient.get(getRequest, basicHeaders);
        } catch (Exception e) {
            log.error("es.get exception,updateRequest:{}", getRequest, e);
            throw e;
        }
    }

    //多个查询请求放在一起查
    public MultiGetResponse multiGet(MultiGetRequest multiGetRequest) throws Exception {
        try {
            return restHighLevelClient.multiGet(multiGetRequest);
        } catch (Exception e) {
            log.error("es.multiGet exception,getRequest:{}", multiGetRequest, e);
            throw e;
        }
    }


    /**
     * @desc 批量更新
     */
    public BulkResponse bulk(BulkRequest bulkRequest) throws Exception {
        try {
            return restHighLevelClient.bulk(bulkRequest,basicHeaders);
        } catch (Exception e) {
            log.error("es.multiGet exception,bulkRequest:{}", bulkRequest, e);
            throw e;
        }
    }
}

es启动
在这里插入图片描述

4.使用例子:

将车次信息存到es中,方便用户查询(从此地到目的地有哪些车可以乘坐)

package com.next.service;


import com.alibaba.google.common.base.Splitter;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.next.common.TrainEsConstant;
import com.next.dao.TrainNumberDetailMapper;
import com.next.dao.TrainNumberMapper;
import com.next.model.TrainNumber;
import com.next.model.TrainNumberDetail;
import com.next.util.JsonMapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.*;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.common.util.set.Sets;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Slf4j
public class TrainNumberService {

    @Resource
    private TrainNumberMapper trainNumberMapper;

    @Resource
    private TrainCacheService trainCacheService;

    @Resource
    private TrainNumberDetailMapper trainNumberDetailMapper;

    @Resource
    private ESClient esClient;

    public void handle(List<CanalEntry.Column> columns, CanalEntry.EventType eventType) throws Exception{
        if (eventType != CanalEntry.EventType.UPDATE) {
            log.info("not update,no need care");
            return;
        }

        int trainNumberId = 0;
        //获取数据库的trainNumberId
        for (CanalEntry.Column column : columns) {
            if (column.getName().equals("id")) {
                trainNumberId = Integer.parseInt(column.getValue());
                break;
            }
        }

        TrainNumber trainNumber = trainNumberMapper.selectByPrimaryKey(trainNumberId);
        //校验是否有车次
        if (null == trainNumber) {
            log.error("not found trainNumber,trainNumberId:{}", trainNumberId);
            return;
        }

        List<TrainNumberDetail> detailList = trainNumberDetailMapper.getByTrainNumberId(trainNumberId);
        //校验是否有车次详情
        if (CollectionUtils.isEmpty(detailList)) {
            log.warn("no detail,no need care,trainNumberId:{}", trainNumber.getName());
            return;
        }
        //将数据写入缓存中
        trainCacheService.set("TN_" + trainNumber.getName(), JsonMapper.obj2String(detailList));
        log.info("trainNumber:{} detailList update redis", trainNumber.getName());

        //将数据存入es中
        saveES(detailList,trainNumber);
        log.info("trainNumber:{} detailList update es", trainNumber.getName());
    }

    //数据保存到es(客户需要查询的数据放到es--->从此地到目的地有哪些车可以乘坐)
    private void saveES(List<TrainNumberDetail> detailList, TrainNumber trainNumber) throws Exception{
        /**
         * A-B fromStationId- toStationId
         * 例:北京到大连有多少趟车?
         * 根据车站的开始结束站,去找车次,即根据fromStationId- toStationId获取到 trainNumberId1,trainNumberId2。。。。
         * trainNumber: A->B->C
         * D386:北京->锦州->大连
         * D387:北京->鞍山->大连
         *
         * 拆分如下
         * D386: 北京-锦州 锦州-大连 北京-大连
         * D387: 北京-鞍山 鞍山-大连 北京-大连
         */
        List<String> list = Lists.newArrayList();
        int fromStationId = trainNumber.getFromStationId();
        if (detailList.size() == 1) {
            //单段
            int toStationId = trainNumber.getToStationId();
            list.add(fromStationId + "_" + toStationId);

        } else {
            //多段,枚举所有的车次,要保证多段有序
            for (int i = 0; i < detailList.size(); i++) {
                //获取开始车站id
                int tempFromStationId = detailList.get(i).getFromStationId();
                for (int j = i; j < detailList.size(); j++) {
                    //获取到达车站id
                    int tempToStationId = detailList.get(j).getToStationId();
                    list.add(tempFromStationId+"_"+tempToStationId);
                }
            }
        }

        //检查数据是否已经存在,存在则不新增,不存在则新增
        //★如果是for循环里面的话,要封装成批量操作IO
        MultiGetRequest multiGetRequest = new MultiGetRequest();
        BulkRequest bulkRequest = new BulkRequest();
        for(String item:list){
            multiGetRequest.add(new MultiGetRequest.Item(TrainEsConstant.INDEX,TrainEsConstant.TYPE,item));
        }
        //获取处理后的结果
        MultiGetResponse multiGetItemResponses = esClient.multiGet(multiGetRequest);
        for(MultiGetItemResponse itemResponse:multiGetItemResponses.getResponses()){
            if(itemResponse.isFailed()){
                log.error("multiGet item failed,itemResponse:{}",itemResponse);
                continue;
            }
            GetResponse getResponse = itemResponse.getResponse();
            if(getResponse == null){
                log.error("multiGet item is null,itemResponse:{}",itemResponse);
                continue;
            }
            //存储更新es的数据,新增用source传入数据  更新用doc传入数据
            Map<String,Object> dataMap = Maps.newHashMap();
            Map<String,Object> map = getResponse.getSourceAsMap();
            if(!getResponse.isExists() || map == null){
                //add index
                dataMap.put(TrainEsConstant.COLUMN_TRAIN_NUMBER,trainNumber.getName());
                IndexRequest indexRequest = new IndexRequest(TrainEsConstant.INDEX,TrainEsConstant.TYPE,getResponse.getId()).source(dataMap);
                bulkRequest.add(indexRequest);
                continue;
            }
            //里面是车次信息 trainNumberId1,trainNumberId2。。。。,需要拆分
            String origin = (String) map.get(TrainEsConstant.COLUMN_TRAIN_NUMBER);
            Set<String> set = Sets.newHashSet(Splitter.on(",").trimResults().omitEmptyStrings().split(origin));
            if(!set.contains(trainNumber.getName())){
                //update index
                dataMap.put(TrainEsConstant.COLUMN_TRAIN_NUMBER,origin+","+trainNumber.getName());
                UpdateRequest updateRequest = new UpdateRequest(TrainEsConstant.INDEX,TrainEsConstant.TYPE,getResponse.getId()).doc(dataMap);
                bulkRequest.add(updateRequest);
            }
        }

        //批量更新es的数据(bulkResponse是批量对象转成string打印日志)
        BulkResponse bulkResponse = esClient.bulk(bulkRequest);
        log.info("es bulk response:{}",JsonMapper.obj2String(bulkResponse));
        if(bulkResponse.hasFailures()){
            throw new RuntimeException("es bulk failure");
        }

    }


}

车次表
在这里插入图片描述车次明细表
在这里插入图片描述
修改数据库中车次表的信息会将数据处理后(出发站-到达站 车次号)存入es
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/277392.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GreatSQL 8.0.32-25新版本有奖体验!

&#xff08;1&#xff09;活动简介 2023.12.28——2024.1.15 期间&#xff0c;参与 GreatSQL 8.0.32-25 新版本体验测试活动&#xff0c;只要发现并提交有效错误或 bug、或文档手册问题&#xff0c;即可获得社区周边、社区金币奖励&#xff01;GreatSQL 期待您的参与~ &…

2023年华为OD机试(python)B卷-高效的任务规划

一、题目 题目描述&#xff1a; 你有 n 台机器编号为 1~n&#xff0c;每台都需要完成完成一项工作&#xff0c;机器经过配置后都能完成独立完成一项工作。 假设第i台机器你需要花B分钟进行设置&#xff0c;然后开始运行&#xff0c;J分钟后完成任务。 现在&#xff0c;你需要选…

骑砍战团MOD开发(27)-module_tableau_materials.py材质

一.配置材质资源 OpenBrf寻找对应材质资源. tableau配置材质资源 ("round_shield_1", 0, "sample_shield_round_1", 512, 256, 0, 0, 0, 0,[(store_script_param, ":banner_mesh", 1),(set_fixed_point_multiplier, 100),(init_position, pos1),…

证件照3秒换底色|有手机就行,一学就会

友友们&#xff0c;你还在求你的设计师朋友给你证件照换底色吗&#xff1f; 支付宝搜索"亿鸣证件照"小程序或微信搜索"随时照"小程序&#xff0c;选择"换底色”功能&#xff0c;上传一张个人生活照&#xff0c;就能一键换底色了&#xff0c;再也不用求…

MySQL的高级SQL语句

目录 1.mysql高阶查询 select&#xff1a;显示表格中一个或数个字段的所有数据记录 distinct&#xff1a;不显示重复的数据记录 where&#xff1a;有条件查询 AND OR &#xff1a;且 或 in&#xff1a;显示已知值的数据记录 between&#xff1a;显示两个值范围内的数据记…

Elasticsearch:升级索引以使用 ELSER 最新的模型

在此 notebook 中&#xff0c;我们将看到有关如何使用 Reindex API 将索引升级到 ELSER 模型 .elser_model_2 的示例。 注意&#xff1a;或者&#xff0c;你也可以通过 update_by_query 来更新索引以使用 ELSER。 在本笔记本中&#xff0c;我们将看到使用 Reindex API 的示例。…

FPGA 底层资源介绍

Xilinx FPGA底层资源介绍 本文转载自&#xff1a;瓜大三哥微信公众号 XILINX FPGA 芯片整体架构如下所示&#xff0c;整个芯片是以BANK进行划分的&#xff0c;不同的工艺、器件速度和对应的时钟具有不同的BANK数量&#xff08;下面截图是以K7325tffg676为例&#xff09;&…

【Unity入门】UGUI之Slider(滑动条)

目录 什么是Slider&#xff1f;Slider属性与功能 什么是Slider&#xff1f; Slider控件允许用户可以通过鼠标来在预先确定的范围调节数值 我们可以在Hierarchy视图右键 -> UI ->Slider来创建滑动条 通过上图可以发现Unity内置的Slider主要有3部分&#xff0c;一个是最…

还在用Jekins?快来试试这款比Jekins简而轻的自动部署软件!

大家好&#xff0c;我是 Java陈序员。 在工作中&#xff0c;你是否遇到过团队中没有专业的运维&#xff0c;开发还要做运维的活&#xff0c;需要自己手动构建、部署项目&#xff1f; 不同的项目还有不同的部署命令&#xff0c;需要使用 SSH 工具连接远程服务器和使用 FTP 文件…

【算法】枪打出头鸟(js)

牛客链接&#xff1a;https://www.nowcoder.com/practice/1504075c856248748ca444c8c093d638?tpId196&&tqId37268&rp1&ru/ta/job-code-total&qru/ta/job-code-total/question-ranking 本人题解&#xff1a; /*** 代码中的类名、方法名、参数名已经指定&a…

Go 如何通过代码进行格式化 gomft命令

我们都知道 使用JetBrains GoLand 快捷键可以快速对代码进行格式化 现在将使用go的代码进行格式化 源代码如下&#xff1a; package mainimport "fmt"func main() {var n1 int 19var n2 float32 4.78//var n3 bool false//var n4 byte avar s1 string…

Oracle VirtualBox中Linux系统基本使用方法——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

前言 小北的这篇博客介绍的是关于用VirtualBox中下载好的ubuntu系统中&#xff0c;为搭建Hadoop平台所做的命令操作准备&#xff0c;希望能帮助不会的人有指引作用。 没有安装好VirtualBox中的ubuntu系统的请参考小北之前的两篇博客&#xff1a; ubuntu18.04 64 位安装笔记—…

node fs模块写入文件 writeFile、writeFileSync、fsPromises.writeFile、createWriteStream

文章目录 1.writeFile2.writeFileSync3.fsPromises.writeFile4.createWriteStream 1.writeFile 它是一个异步写入的方法 函数参数 file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符 data <string> | <Buffer> | <Typ…

安装 PyQt5 保姆级教程

作者&#xff1a;billy 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 前言 博主之前做应用层开发用的一直是 Qt&#xff0c;这次尝试一下在 python 中使用 Pyqt5 模块来开发 UI 界面&#xff0c;这里做一些…

RabbitMQ是做什么的

rabbitMQ是做异步通讯的。用于解决同步同讯的拓展性差&#xff0c;级联失败的问题。 异步调用方式其实就是基于消息通知的方式&#xff0c;一般包含三个角色:。 消息发送者:投递消息的人&#xff0c;就是原来的调用方 消息代理:管理、暂存、转发消息&#xff0c;你可以把它理…

第 1 场 算法季度赛 蓝桥搜狐畅游(1~5 , 7)

1、水题 2、树上dp 3、模拟 4、概率 5、拆位 6、&#xff08;是没学过的东西了...&#xff09; 7、组合数学 1. 新年快乐【算法赛】 直接模拟 #include <iostream> using namespace std; int main() {cout <<"2024 AK";return 0; } 2. 蓝桥圣诞树…

VS2019 驱动两个函数地址相同?

VS2019对于两个函数名不同&#xff0c;但是函数代码实现相同的情况&#xff0c;在链接时会将两个函数合并为同一个代码段&#xff0c;导致两个函数的地址相等。代码如下&#xff1a; #include <wdm.h>static void InnerFunc(int i, const char* name) {DbgPrint("i…

C语言字符串知识点和算法总结

目录 一、字符串遍历 1、字符串和字符数组 2、获取字符串长度 3、字符串遍历 4、大小写转换 5、字符串数组 二、字符串拷贝 三、字符串比较 四、字符串分割 五、字符串翻转 1、题目详解 2、算法详解 3、源码剖析 六、回文串 1、定义 2、例题讲解 3、算法详解 …

数据库进阶教学——读写分离(Mycat1.6+Ubuntu22.04主+Win10从)

目录 1、概述 2、环境准备 3、读写分离实验 3.1、安装jdk 3.2、安装Mycat 3.3、配置Mycat 3.3.1、配置schema.xml ​​​​3.3.2、配置server.xml 3.4、修改主从机远程登陆权限 3.4.1、主机 3.4.2、从机 3.5、启动Mycat 3.6、登录Mycat 3.7、验证 1、概述 读写分…

Linux自定义shell编写

Linux自定义shell编写 一.最终版本展示1.动图展示2.代码展示 二.具体步骤1.打印提示符2.解析命令行3.分析是否是内建命令1.shell对于内建名令的处理2.cd命令3.cd函数的实现4.echo命令的实现5.export命令的实现6.内建命令函数的实现 4.创建子进程通过程序替换执行命令5.循环往复…