ES的使用(Elasticsearch)

news2025/1/19 20:20:36

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.coloradmin.cn/o/1344841.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件测试/测试开发丨学习笔记之 Python 函数

python 函数 函数的作用 函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一或相关联功能的代码段函数能提高应用的模块性和代码的重复利用率python 内置函数&#xff1a;docs.python.org/zh-cn/3.8/l… 函数定义 def&#xff1a;函数定义关键词function_nam…

轻松调整视频时长,创意与技术的新篇章

传统的视频剪辑工具往往难以精确控制时间&#xff0c;而【媒体梦工厂】凭借其先进的算法和界面设计&#xff0c;让视频时长的调整变得简单而精确&#xff0c;助你释放无限的创意&#xff0c;用技术为你的创意插上翅膀&#xff0c;让每一秒都有意义。 所需工具&#xff1a; 一…

MongoDB 概念介绍

1、MongoDB 应用场景 传统的关系型数据库&#xff0c;在数据操作的"三高"需求以及应对Web2.0的网站需求面前&#xff0c;显得力不从心。 High performance -对数据库高并发读写的需求。Huge Storage -对海量数据的高效率存储和访问的需求。High Scalability &&…

基于Java图书借阅管理系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

Android : 使用GestureOverlayView进行手势识别—简单应用

示例图&#xff1a; GestureOverlayView介绍&#xff1a; GestureOverlayView 是 Android 开发中用于识别和显示手势的视图组件。它允许用户在屏幕上绘制手势&#xff0c;并且应用程序可以检测和响应这些手势。以下是关于 GestureOverlayView 的主要特点&#xff1a; 手势识别…

RS-485 RS-232 RS-422 区别和理解

RS-485&#xff0c;RS-232&#xff0c;RS-422区别和理解 目录概述需求&#xff1a; 设计思路实现思路分析1.概述2.区别 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a b…

Vue : 监视属性

目录 一个案例 监听属性 handler immediate vm.$watch(xxx) 深度监视 监视的简写 computed和watch之间的区别 一个案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport"…

湘潭大学-2023年下学期-c语言-作业0x0a-综合1

A 求最小公倍数 #include<stdio.h>int gcd(int a,int b) {return b>0?gcd(b,a%b):a; }int main() {int a,b;while(~scanf("%d%d",&a,&b)){if(a0&&b0) break;printf("%d\n",a*b/gcd(a,b));}return 0; }记住最大公约数的函数&…

java cpu使用率高排查

1、top 找到对应进程&#xff0c;如这里是4060434 2、找线程 ps H -eo pid,tid,%cpu | grep 4060434找到那个线程id 高的 如4066606 3、转化16进制 printf 0x%x\n 40666064、找16进制对应的运行信息 jstack 4060434 | grep 0x3e0d2e -A 20

Hive集群出现报错信息解决办法

一、报错信息&#xff1a;hive> show databases;FAILED: HiveException java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient 解决办法&#xff1a;1.删除mysql中的元数据库&#xff08;metastore&#xff0…

MySQL:权限控制

要授予用户帐户权限&#xff0c;可以用GRANT命令。有撤销用户的权限&#xff0c;可以用REVOKE命令。这里以 MySQl 为例&#xff0c;介绍权限控制实际应用。 GRANT授予权限语法&#xff1a; GRANT privilege,[privilege],.. ON privilege_level TO user [IDENTIFIED BY passwo…

List常见方法和遍历操作

List集合的特点 有序&#xff1a; 存和取的元素顺序一致有索引&#xff1a;可以通过索引操作元素可重复&#xff1a;存储的元素可以重复 List集合的特有方法 Collection的方法List都继承了List集合因为有索引&#xff0c;所以有了很多操作索引的方法 ublic static void main…

【C语言】分支与循环语句

什么是语句&#xff1f; C语句可分为以下五类&#xff1a; 表达式语句函数调用语句控制语句 &#xff08;本篇重点介绍&#xff09;复合语句空语句 控制语句用于控制程序的执行流程&#xff0c;以实现程序的各种结构方式。C语言支持三种结构&#xff1a; 顺序结构选择结构循…

软件测试/测试开发丨Python 虚拟环境及pip环境管理

venv 虚拟环境管理 venv 虚拟环境的优点 独立的 Python 环境&#xff0c;不会产生冲突有助于包的管理删除和卸载方便 venv 使用方法 创建虚拟环境 python3 -m venv test 激活虚拟环境 切换指定文件夹Windows&#xff1a;/Scripts/macOS&#xff1a;/bin/ 执行指令&#xff…

基于STM/APM32F072制作的J-Link OB调试器项目验证

基于STM/APM32F072制作的J-Link OB调试器项目验证 &#x1f4cd;本文基于github项目&#xff1a;https://github.com/geekchun/Jlink-OB/tree/master⚡申明&#xff1a;仅限个人研究学习&#xff0c;无其他用途。&#x1f33f;采用该项目提供的固件&#xff0c;烧录STM32f4时信…

技能分析:这就是人们写在简历上的内容

您希望您的技能部分听起来像其他人一样吗&#xff1f;另一方面&#xff0c;您是否想遗漏一项顶级技能&#xff0c;因为许多其他简历也列出了它&#xff1f;在脱颖而出和涵盖雇主寻求的所有技能之间找到平衡可能是一个挑战。 优秀的简历技能部分会考虑到每个雇主所寻求的特质。…

驾驭AI助手,开启高效创作之旅:一篇文章,轻松搞定!

在信息爆炸的时代&#xff0c;内容创作已成为个人和企业的核心竞争力。但撰写一篇高质量的文章需要大量时间和精力。现在&#xff0c;有了AI助手&#xff0c;这些烦恼全部消失 首先&#xff0c;我们要进入首助编辑高手主页面&#xff0c;并在上方的板块栏里选择“AI文章创作”…

【docker实战】安装tomcat并连接mysql数据库

本节用docker来安装tomcat&#xff0c;并用这个tomcat连接我们上一节安装好的mysql数据库 一、拉取镜像 [rootlocalhost data]# docker pull tomcat:8.5.69二、运行tomcat bitnami的tomcat的根目录在/opt/bitnami/tomcat/webapps下面&#xff0c;所以我们为了方便部署我们的…

conda环境下nvrtc: error: invalid value for --gpu-architecture解决方法

1 问题描述 在运行视频处理的模型过程中&#xff0c;出现如下异常&#xff1a; nvrtc: error: invalid value for --gpu-architecture (-arch)nvrtc compilation failed: #define NAN __int_as_float(0x7fffffff) #define POS_INFINITY __int_as_float(0x7f800000) #define N…

Cisco模拟器-OSPF路由协议

设计要求用两台双口路由器连接不同IP网段的计算机&#xff0c;并使用OSFP协议发现路由表使不同IP网段的计算机可以相互通信。 通过设计&#xff0c;可以连通IP地址网段不同的局域网&#xff0c;可应用在园区网的互连和互通的实现上。 主要配置步骤 路由器0&#xff1a; Router…