【Elasticsearch】实现气象数据存储与查询系统

🧑 博主简介:CSDN博客专家历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程高并发设计Springboot和微服务,熟悉LinuxESXI虚拟化以及云原生Docker和K8s,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
技术合作请加本人wx(注明来自csdn):foreast_sea

在这里插入图片描述


在这里插入图片描述

基于 Elasticsearch 的气象数据存储与查询系统:构建气象数据处理的强大引擎

一、引言

在当今科技飞速发展的时代,气象数据的收集、存储与分析对于气象研究、天气预报以及应对气候变化等诸多方面都具有极为关键的意义。气象部门每天都会通过各种先进的观测设备和技术手段,收集海量的气象数据,这些数据涵盖了气温气压湿度风速降水等多个重要的气象要素。

传统的气象数据处理方式在面对如此庞大且复杂的数据量时,逐渐暴露出诸多局限性。数据存储的效率、查询的速度以及分析的深度和广度都难以满足日益增长的气象研究和业务需求。而 Elasticsearch 的出现,为气象数据的管理带来了全新的解决方案。

Elasticsearch 是一个分布式高可用、实时的搜索与数据分析引擎,它基于 Lucene 构建,具备强大的全文搜索功能和高效的数据存储与检索能力。在气象领域,它能够轻松应对海量气象数据的存储挑战,通过其灵活且可定制的索引结构,使得气象数据可以被快速地组织和索引。气象工作人员可以利用 Elasticsearch 的丰富查询接口,迅速地从海量数据中提取出所需的气象信息,无论是特定时间段内的气温变化趋势,还是某一地区在历史上的极端气象事件记录,都能够在瞬间得到精准的查询结果。这不仅大大提高了气象数据的利用效率,还为气象预报员深入分析气象变化规律提供了有力的工具,从而能够更加准确地预测未来的天气状况,为农业生产航空航天交通运输等众多行业提供可靠的气象服务保障,助力人类更好地适应和应对气候变化带来的各种影响。

我们将深入探讨如何基于 Elasticsearch 构建气象数据存储与查询系统,详细介绍其中所涉及的技术细节、代码实现以及测试方法。

二、Elasticsearch 数据类型在气象数据中的应用

  1. 数值类型
    • 整数类型(如 long、integer 等):在气象数据中,许多数据可以用整数表示。例如,气压值通常在一定范围内,可以使用整数类型来存储。以百帕为单位的气压数据,一般在 900 到 1100 之间,使用 integer 类型就可以很好地容纳。
    • 浮点数类型(如 double、float 等):气温、湿度等数据可能包含小数部分,适合用浮点数类型存储。比如气温数据,可能精确到小数点后一位,像 25.5℃,使用 double 类型能够准确地记录这些数据。
  2. 日期类型(date):气象数据中的观测时间是非常重要的信息。例如,降水数据的记录必然关联着对应的时间点。通过 date 类型,可以方便地存储和处理这些时间信息,便于后续按照时间维度进行数据查询和分析,如查询某一天或某一时间段内的气象数据变化。
  3. 文本类型(keyword、text):对于一些气象站点的名称、地区名称等信息,可以使用 keyword 类型。keyword 类型适合存储结构化的文本数据,在查询时可以进行精确匹配。而对于一些气象现象的描述,如“暴雨”“大风”等,如果需要进行全文搜索和相关性分析,则可以使用 text 类型。

三、Elasticsearch 索引结构设计

  1. 索引名称:为气象数据创建一个专门的索引,例如“meteorological_data_index”。这个索引将作为所有气象数据存储和查询的基础容器。
  2. 映射(Mapping)
    • 对于气温数据字段,定义如下映射:
{"properties": {"temperature": {"type": "double"}}
}
  • 气压字段映射:
{"properties": {"pressure": {"type": "integer"}}
}
  • 湿度字段映射:
{"properties": {"humidity": {"type": "double"}}
}
  • 风速字段映射:
{"properties": {"wind_speed": {"type": "double"}}
}
  • 降水字段映射:
{"properties": {"precipitation": {"type": "double"}}
}
  • 观测时间字段映射:
{"properties": {"observation_time": {"type": "date","format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"}}
}
  • 气象站点名称字段映射:
{"properties": {"station_name": {"type": "keyword"}}
}

四、相关 Maven 依赖

在 Java 项目中使用 Elasticsearch,需要添加以下 Maven 依赖:

<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.17.9</version>
</dependency>
<dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.17.9</version>
</dependency>

这里使用的是 Elasticsearch 7.17.9 版本,其中elasticsearch-rest-high-level-client用于与 Elasticsearch 进行高级别的 REST 交互,elasticsearch核心库提供了基础的功能支持。

五、实现步骤

(一)连接到 Elasticsearch

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;public class ElasticsearchConnection {private static final String HOST = "localhost";private static final int PORT = 9200;public static RestHighLevelClient getClient() {// 创建 HttpHost 对象,指定 Elasticsearch 服务器地址和端口HttpHost httpHost = new HttpHost(HOST, PORT, "http");// 创建 RestHighLevelClient 对象,用于与 Elasticsearch 进行交互return new RestHighLevelClient(RestClient.builder(httpHost));}
}

在上述代码中,首先定义了 Elasticsearch 服务器的主机地址和端口。然后通过HttpHost构建了服务器的连接信息,并使用RestClient.builder创建了RestHighLevelClient,这是与 Elasticsearch 进行交互的核心客户端对象。

(二)创建索引

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;import java.io.IOException;public class IndexCreator {public static void createMeteorologicalIndex(RestHighLevelClient client) throws IOException {// 创建索引请求对象CreateIndexRequest request = new CreateIndexRequest("meteorological_data_index");// 设置索引的设置,例如分片数量和副本数量request.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 1));// 设置索引的映射,即字段类型等信息request.mapping("{\n" +"  \"properties\": {\n" +"    \"temperature\": {\n" +"      \"type\": \"double\"\n" +"    },\n" +"    \"pressure\": {\n" +"      \"type\": \"integer\"\n" +"    },\n" +"    \"humidity\": {\n" +"      \"type\": \"double\"\n" +"    },\n" +"    \"wind_speed\": {\n" +"      \"type\": \"double\"\n" +"    },\n" +"    \"precipitation\": {\n" +"      \"type\": \"double\"\n" +"    },\n" +"    \"observation_time\": {\n" +"      \"type\": \"date\",\n" +"      \"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis\"\n" +"    },\n" +"    \"station_name\": {\n" +"      \"type\": \"keyword\"\n" +"    }\n" +"  }\n" +"}", XContentType.JSON);// 执行创建索引操作CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);// 检查索引是否创建成功boolean acknowledged = response.isAcknowledged();if (acknowledged) {System.out.println("气象数据索引创建成功");} else {System.out.println("气象数据索引创建失败");}}
}

这段代码首先创建了CreateIndexRequest对象,指定了要创建的索引名称。然后设置了索引的一些基本设置,如分片数和副本数,接着设置了之前设计好的索引映射。最后通过client.indices().create方法执行索引创建操作,并根据返回结果判断索引是否创建成功。

(三)插入气象数据

import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class DataInserter {public static void insertMeteorologicalData(RestHighLevelClient client) throws IOException {// 创建要插入的数据对象Map<String, Object> data = new HashMap<>();data.put("temperature", 25.5);data.put("pressure", 1010);data.put("humidity", 60.0);data.put("wind_speed", 3.5);data.put("precipitation", 0.0);data.put("observation_time", new Date());data.put("station_name", "StationA");// 创建索引请求对象IndexRequest request = new IndexRequest("meteorological_data_index");// 设置文档 ID,如果不设置,Elasticsearch 会自动生成request.id("1");// 设置要插入的数据内容request.source(data, XContentType.JSON);// 执行插入数据操作IndexResponse response = client.index(request, RequestOptions.DEFAULT);// 检查数据是否插入成功if (response.status().getStatus() == 201) {System.out.println("气象数据插入成功");} else {System.out.println("气象数据插入失败");}}
}

这里首先构建了一个Map对象来表示要插入的气象数据,包含了各种气象要素的值以及观测时间和站点名称。然后创建IndexRequest对象,指定索引名称,并设置文档 ID 和数据内容。最后通过client.index方法将数据插入到 Elasticsearch 中,并根据返回状态判断插入是否成功。

(四)查询气象数据

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class DataSearcher {public static List<Map<String, Object>> searchMeteorologicalData(RestHighLevelClient client) throws IOException {// 创建搜索请求对象SearchRequest request = new SearchRequest("meteorological_data_index");// 创建搜索源构建器SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();// 设置查询条件,这里查询所有数据sourceBuilder.query(QueryBuilders.matchAllQuery());request.source(sourceBuilder);// 执行搜索操作SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 处理搜索结果List<Map<String, Object>> resultList = new ArrayList<>();for (SearchHit hit : response.getHits().getHits()) {resultList.add(hit.getSourceAsMap());}return resultList;}
}

上述代码创建了SearchRequest对象用于指定搜索的索引。然后通过SearchSourceBuilder构建搜索条件,这里使用QueryBuilders.matchAllQuery查询所有数据。执行搜索操作后,遍历搜索结果SearchHit对象,将其源数据(即气象数据)添加到List中并返回。

六、单元测试及预期输出

(一)测试连接到 Elasticsearch

import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.assertNotNull;public class ElasticsearchConnectionTest {@Testpublic void testGetClient() {// 获取 Elasticsearch 客户端RestHighLevelClient client = ElasticsearchConnection.getClient();// 断言客户端不为空assertNotNull(client);}
}

预期输出:测试通过,表明能够成功获取到 Elasticsearch 客户端对象。

(二)测试创建索引

import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;import java.io.IOException;import static org.junit.jupiter.api.Assertions.assertTrue;public class IndexCreatorTest {@Testpublic void testCreateMeteorologicalIndex() throws IOException {// 获取 Elasticsearch 客户端RestHighLevelClient client = ElasticsearchConnection.getClient();// 创建气象数据索引IndexCreator.createMeteorologicalIndex(client);// 这里可以进一步添加代码来验证索引是否真正创建成功,例如检查索引是否存在等操作// 暂时简单地假设创建成功,后续可完善assertTrue(true);}
}

预期输出:如果索引创建成功,测试通过,控制台输出“气象数据索引创建成功”。如果创建失败,控制台输出“气象数据索引创建失败”,并且测试不通过。

(三)测试插入气象数据

import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;import java.io.IOException;import static org.junit.jupiter.api.Assertions.assertTrue;public class DataInserterTest {@Testpublic void testInsertMeteorologicalData() throws IOException {// 获取 Elasticsearch 客户端RestHighLevelClient client = ElasticsearchConnection.getClient();// 插入气象数据DataInserter.insertMeteorologicalData(client);// 这里可以进一步添加代码来验证数据是否真正插入成功,例如根据插入的文档 ID 进行查询验证等操作// 暂时简单地假设插入成功,后续可完善assertTrue(true);}
}

预期输出:如果数据插入成功,测试通过,控制台输出“气象数据插入成功”。如果插入失败,控制台输出“气象数据插入失败”,并且测试不通过。

(四)测试查询气象数据

import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;import java.io.IOException;
import java.util.List;
import java.util.Map;import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;public class DataSearcherTest {@Testpublic void testSearchMeteorologicalData() throws IOException {// 获取 Elasticsearch 客户端RestHighLevelClient client = ElasticsearchConnection.getClient();// 查询气象数据List<Map<String, Object>> resultList = DataSearcher.searchMeteorologicalData(client);// 断言查询结果不为空assertFalse(resultList.isEmpty());}
}

预期输出:如果查询到数据,测试通过,表明能够成功从 Elasticsearch 中查询到气象数据。如果查询结果为空,测试不通过。

七、参考资料文献

  1. Elasticsearch 官方文档:https://www.elasticsearch.org/guide/index.html
  2. Elasticsearch 实战》书籍,作者:[美] 拉法尔·库切拉[波] 马雷克·罗戈津斯基
  3. 相关气象数据处理与存储的学术论文和技术报告。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

精密制造中智能扭矩系统的关键作用

【大家好&#xff0c;我是唐Sun&#xff0c;唐Sun的唐&#xff0c;唐Sun的Sun。】 电子、半导体、医疗器械等精密制造行业对于产品质量和性能的要求达到了前所未有的高度。在这一背景下&#xff0c;智能扭矩系统成为了确保零部件装配高精度和一致性的关键要素&#xff0c;对提升…

使用mtools搭建MongoDB复制集和分片集群

mtools介绍 mtools是一套基于Python实现的MongoDB工具集&#xff0c;其包括MongoDB日志分析、报表生成及简易的数据库安装等功能。它由MongoDB原生的工程师单独发起并做开源维护&#xff0c;目前已经有大量的使用者。 mtools所包含的一些常用组件如下&#xff1a; mlaunch支…

软件测试最新项目合集【商城、外卖、银行、金融等等.......】

项目一&#xff1a;ShopNC商城 项目概况&#xff1a; ShopNC商城是一个电子商务B2C电商平台系统&#xff0c;功能强大&#xff0c;安全便捷。适合企业及个人快速构建个性化网上商城。 包含PCIOS客户端Adroid客户端微商城&#xff0c;系统PC后台是基于ThinkPHP MVC构架开发的跨…

Artec Leo 3D扫描仪 革新家具行业的数字化展示【沪敖3D】

随着科技的飞速进步&#xff0c;三维扫描技术已被广泛应用于包括家居行业在内的多个行业。面对现代消费者对家居产品日益增长的个性化和多样化需求&#xff0c;传统的家居设计和展示方法已难以满足市场需求。三维扫描技术的出现&#xff0c;为家居行业带来了新的发展机遇&#…

爬虫项目基础知识详解

文章目录 Python爬虫项目基础知识一、爬虫与数据分析1.1 Python中的requests库Requests 库的安装Requests 库的 get() 方法爬取网页的通用代码框架HTTP 协议及 Requests 库方法Requests 库主要方法解析 1.2 python中的json库1.3 xpath学习之python中lxml库html了解html结构html…

Tomcat,javaweb, servlet , springBoot

在server.xml里配置服务器 <scope>provided</scope>打包的时候&#xff0c;这个jar包不会被打进去&#xff0c;因为tomcat已将封装了这个jar包&#xff0c;没必要要这个

棋牌项目Go的日志打印问题

棋牌项目Go的日志打印问题 项目使用 go work 管理模块 github.com/spf13/viper 通过 application.yml 加载配置 $ tree . ├── README.md ├── common │ ├── application.yml │ ├── config │ │ └── config.go │ ├── go.mod │ ├── go.su…

【Linux操作系统】多线程控制(创建,等待,终止、分离)

目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数&#xff08;pthread&#xff09;查看和理解线程id主线程与其他线程之间的关系 三、线程等待&#xff08;回收&#xff09;四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程…

小程序 —— Day1

组件 — view和scroll-view view 类似于HTML中的div&#xff0c;是一个块级元素 案例&#xff1a;通过view组件实现页面的基础布局 scroll-view 可滚动的视图区域&#xff0c;用来实现滚动列表效果 案例&#xff1a;实现纵向滚动效果 scroll-x属性&#xff1a;允许横向滚动…

快速构建NLP理论知识体系

NLP理论知识体系 一句话解释NLPNLP模型及原理简述1、Rag 一句话解释NLP 如果我们要实现机器翻译、情感分析、问答系统、文本摘要、聊天机器人、构造智能化的辅助文件填写模板&#xff0c;NLP可以通过现成的模型对输入的语音、文字、图片进行处理&#xff08;分词、标词性、去停…

Kafka的消费消息是如何传递的?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka的消费消息是如何传递的&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka的消费消息是如何传递的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka 的消息传递是通过 消费者&#xff08…

shell脚本实战案例

文章目录 实战第一坑功能说明脚本实现 实战第一坑 实战第一坑&#xff1a;在Windows系统写了一个脚本&#xff0c;比如上面&#xff0c;随后上传到服务&#xff0c;执行会报错 原因&#xff1a; 解决方案&#xff1a;在linux系统touch文件&#xff0c;并通过vim添加内容&…

Android 使用 Canvas 和 Paint 实现圆形图片

学习笔记 效果展示: 全部代码: public class YuanActivity extends AppCompatActivity {private ActivityYuanBinding binding;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 通过 DataBinding 获取布局文件binding …

敖汉宝塔油页岩露天矿山安全自动化监测

1. 项目简介 本次项目位于内蒙古自治区赤峰市敖汉旗宝国吐乡大青山村&#xff0c;地理位置好。主营许可经营项目&#xff1a;无一般经营项目&#xff1a;页岩油生产&#xff1b;页岩油、润滑油、建筑材料&#xff08;不含油漆&#xff09;销售等单位规模1-20人&#xff0c;单位…

fedora下Jetbrains系列IDE窗口中文乱码解决方法

可以看到窗口右部分的中文内容为小方块。 进入 Settings - Appearance & Behavior - Appearance - Use custom font : Note Sans Mono CJK SC &#xff0c;设置后如下图&#xff1a;

LeetCode题练习与总结:删除二叉搜索树中的节点--450

一、题目描述 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&am…

Python_Flask03

这篇文章主要介绍的是数据库的增删改查操作&#xff0c;无多余好说的。 from flask import Flask from flask_sqlalchemy import SQLAlchemy from sqlalchemy import text from flask_migrate import Migrateapp Flask(__name__)# 本地基础信息的主机名 HOSTNAME "127.0…

我国基本比例尺地形图介绍

目录 1.前言2.大中小比例尺划分3.使用的投影4.使用3度带6度带&#xff1f;5.详细介绍1:100万地形图1:50万地形图1:25万地形图1:10万地形图1:5万地形图1:2.5万地形图1:1万地形图1:5000地形图 6.总结 1.前言 本文搜集整理了我国国家基本比例尺地形图的情况&#xff0c;共11种&…

离线安装ollama到服务器

搜了很多教程不满意,弄了半天才弄好&#xff0c;这里记录下&#xff0c;方便以后的人用&#xff0c;那个在线下载太慢&#xff0c;怕不是得下载到明年。 一.从官网下在liunx版的tgz安装包 Releases ollama/ollama (github.com) 查看自己的服务器信息&#xff08;参考 https:/…

Face2QR:可根据人脸图像生成二维码,还可以扫描,以后个人名片就这样用了!

今天给大家介绍的是一种专为生成个性化二维码而设计的新方法Face2QR&#xff0c;可以将美观、人脸识别和可扫描性完美地融合在一起。 下图展示为Face2QR 生成的面部图像&#xff08;第一行&#xff09;和二维码图像&#xff08;第二行&#xff09;。生成的二维码不仅忠实地保留…