Flink(七)【输出算子(Sink)】

前言

        今天是我写博客的第 200 篇,恍惚间两年过去了,现在已经是大三的学长了。仍然记得两年前第一次写博客的时候,当时学的应该是 Java 语言,菜的一批,写了就删,怕被人看到丢脸。当时就想着自己一年之后,两年之后能学到什么水平,什么是 JDBC、什么是 MVC、SSM,在当时都是特别好奇的东西,不过都在后来的学习中慢慢接触到,并且好多已经烂熟于心了。

        那,今天我在畅想一下,一年后的今天,我又学到了什么水平?能否达到三花聚顶、草木山石皆可为码的超凡入圣的境界?拿没拿到心仪的 offer?和那个心动过的女孩相处怎么样了?哈哈哈哈哈


输出算子(Sink)

学完了 Flink 在不同执行环境(本地测试环境和集群环境)下的多种读取(多种数据源)和转换操作(多种转换算子),最后就是输出操作了。

1、连接到外部系统

Flink 1.12 之前,Sink 算子是通过调用 DataStream 的 addSink 方法来实现的:

stream.addSink(new SinkFunction(...));

从 Flink 1.12 开始,Flink 重构了 Sink 架构:

stream.sinkTo(...)

查看 Flink 支持的连接器

需要我们自己导入依赖,比如上面的 Kfaka 和 DataGen 我们之前使用的时候都导入过相关依赖,需要知道,有的是只支持source,有的只支持sink,有的全都支持。

 <dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-kafka</artifactId><version>${flink.version}</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-datagen</artifactId><version>${flink.version}</version></dependency>

2、输出到文件

        Flink 专门提供了一个流式文件系统的连接器:FileSink,为批处理和流处理提供了一个统一的 Sink,它可以将分区文件写入 Flink支持的文件系统。
        它的主要操作是将数据写入桶(buckets),每个桶中的数据都可以分割成一个个大小有限的分区文件,这样一来就实现真正意义上的分布式文件存储。我们可以通过各种配置来控制“分桶”的操作;默认的分桶方式是基于时间的,我们每小时写入一个新的桶。换句话说,每个桶内保存的文件,记录的都是 1 小时的输出数据。
        FileSink 支持行编码(Row-encoded)和批量编码(Bulk-encoded,比如 Parquet)格式。这两种不同的方式都有各自的构建器(builder),调用方法也非常简单,可以直接调用 FileSink 的静态方法:

  • 行编码:FileSink.forRowFormat(basePath,rowEncoder)。
  • 批量编码:FileSink.forBulkFormat(basePath,bulkWriterFactory)。

在创建行或批量编码 Sink 时,我们需要传入两个参数,用来指定存储桶的基本路径(basePath)和数据的编码逻辑(rowEncoder 或 bulkWriterFactory)。

package com.lyh.sink;import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.serialization.SimpleStringEncoder;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.connector.source.util.ratelimit.RateLimiterStrategy;
import org.apache.flink.configuration.MemorySize;
import org.apache.flink.connector.datagen.source.DataGeneratorSource;
import org.apache.flink.connector.datagen.source.GeneratorFunction;
import org.apache.flink.connector.file.sink.FileSink;
import org.apache.flink.core.fs.Path;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.filesystem.OutputFileConfig;
import org.apache.flink.streaming.api.functions.sink.filesystem.bucketassigners.DateTimeBucketAssigner;
import org.apache.flink.streaming.api.functions.sink.filesystem.rollingpolicies.DefaultRollingPolicy;import java.time.Duration;
import java.time.ZoneId;/*** @author 刘xx* @version 1.0* @date 2023-11-18 9:51*/
public class SinkFile {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(2);// 必须开启 检查点 不然一直都是 .inprogressenv.enableCheckpointing(2000, CheckpointingMode.EXACTLY_ONCE);DataGeneratorSource<String> dataGeneratorSource = new DataGeneratorSource<String>(new GeneratorFunction<Long, String>() {@Overridepublic String map(Long value) throws Exception {return "Number:"+value;}},Long.MAX_VALUE,RateLimiterStrategy.perSecond(10), // 每s 10条Types.STRING);DataStreamSource<String> dataGen = env.fromSource(dataGeneratorSource, WatermarkStrategy.noWatermarks(), "data-generate");// todo 输出到文件系统FileSink<String> fileSink = FileSink.// 泛型方法 需要和输出结果的泛型保持一致<String>forRowFormat(new Path("D:/Desktop"),    // 指定输出路径 可以是 hdfs:// 路径new SimpleStringEncoder<>("UTF-8")) // 指定编码.withOutputFileConfig(OutputFileConfig.builder().withPartPrefix("lyh").withPartSuffix(".log").build())// 按照目录分桶 一个小时一个目录(这里的时间格式别改为分钟 会报错: flink Relative path in absolute URI:).withBucketAssigner(new DateTimeBucketAssigner<>("yyyy-MM-dd HH", ZoneId.systemDefault()))// 设置文件滚动策略-时间或者大小 10s 或 1KB 或 5min内没有新数据写入 滚动一次// 滚动的时候 文件就会更名为我们设定的格式(前缀)不再写入.withRollingPolicy(DefaultRollingPolicy.builder().withRolloverInterval(Duration.ofSeconds(10L))  // 10s.withMaxPartSize(new MemorySize(1024)) // 1KB.withInactivityInterval(Duration.ofMinutes(5))  // 5min.build()).build();dataGen.sinkTo(fileSink);env.execute();}
}

这里我们创建了一个简单的文件 Sink,通过.withRollingPolicy()方法指定了一个“滚动策略”。“滚动”的概念在日志文件的写入中经常遇到:因为文件会有内容持续不断地写入,所以我们应该给一个标准,到什么时候就开启新的文件,将之前的内容归档保存。也就是说,上面的代码设置了在以下 3 种情况下,我们就会滚动分区文件:
⚫ 至少包含 10 秒的数据
⚫ 最近 5 分钟没有收到新的数据
⚫ 文件大小已达到 1 KB

通过 withOutputFileConfig()方法指定了输出的文件名前缀和后缀。

需要特别注意的就是一定要开启检查点,否则我们的数据一直都是正在写入的状态(具体原因后面学习到检查点的时候会详细说)。

运行结果:

3、输出到 Kafka

  1. 需要添加 Kafka 依赖(之前导入过了)
  2. 启动 Kafka
  3. 编写示例代码
package com.lyh.sink;import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.kafka.sink.KafkaRecordSerializationSchema;
import org.apache.flink.connector.kafka.sink.KafkaSink;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.kafka.clients.producer.ProducerConfig;/*** @author 刘xx* @version 1.0* @date 2023-11-18 11:20*/
public class SinkKafka {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);// 如果是 精准一次 必须开启 checkpointenv.enableCheckpointing(2000, CheckpointingMode.EXACTLY_ONCE);SingleOutputStreamOperator<String> sensorDS = env.socketTextStream("localhost", 9999);KafkaSink<String> kafkaSink = KafkaSink.<String>builder()// 指定 kafka 的地址和端口.setBootstrapServers("hadoop102:9092,hadoop103:9092,hadoop104:9092")// 指定序列化器 我们是发送方 所以我们是生产者.setRecordSerializer(KafkaRecordSerializationSchema.<String>builder().setTopic("like").setValueSerializationSchema(new SimpleStringSchema()).build())// 写到 kafka 的一致性级别: 精准一次 / 至少一次// 如果是精准一次//  1.必须开启检查点 env.enableCheckpointing(2000, CheckpointingMode.EXACTLY_ONCE)//  2.必须设置事务的前缀//  3.必须设置事务的超时时间: 大于 checkpoint间隔 小于 max 15分钟.setDeliveryGuarantee(DeliveryGuarantee.EXACTLY_ONCE).setTransactionalIdPrefix("lyh-").setProperty(ProducerConfig.TRANSACTION_TIMEOUT_CONFIG,10*60*1000+"").build();sensorDS.sinkTo(kafkaSink);env.execute();}
}

启动 kafka 并开启一个消费者:

kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic like

运行结果:

需要特别注意的三点:

如果是精准一次1.必须开启检查点 env.enableCheckpointing(2000, CheckpointingMode.EXACTLY_ONCE)2.必须设置事务的前缀3.必须设置事务的超时时间: 大于 checkpoint间隔 小于 max 15分钟

自定义序列化器

我们上面用的自带的序列化器,但是如果我们有 key 的话,就需要自定义序列化器了,替换上面的代码:

.setRecordSerializer(/*** 如果要指定写入 kafka 的key 就需要自定义序列化器* 实现一个接口 重写序列化方法* 指定key 转为 bytes[]* 指定value 转为 bytes[]* 返回一个 ProducerRecord(topic名,key,value)对象*/new KafkaRecordSerializationSchema<String>() {@Nullable@Override// ProducerRecord<byte[], byte[]> 返回一个生产者消息,key,value 分别对应两个字节数组public ProducerRecord<byte[], byte[]> serialize(String element, KafkaSinkContext context, Long timestamp) {String[] datas = element.split(",");byte[] key = datas[0].getBytes(StandardCharsets.UTF_8);byte[] value = element.getBytes(StandardCharsets.UTF_8);return new ProducerRecord<>("like",key,value);}}
)

运行结果: 

4、输出到 MySQL

添加依赖(1.17版本的依赖需要指定仓库才能找到,因为阿里云和默认的maven仓库是没有的):

<dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-jdbc</artifactId><version>1.17-SNAPSHOT</version></dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.31</version></dependency>....<repositories><repository><id>apache-snapshots</id><name>apache snapshots</name><url>https://repository.apache.org/content/repositories/snapshots/</url></repository></repositories>

创建表格 

编写代码,将输入的数据行分隔为对象参数,每行数据生成一个对象进行处理。 

package com.lyh.sink;import com.lyh.bean.WaterSensor;
import function.WaterSensorFunction;
import org.apache.flink.connector.jdbc.JdbcConnectionOptions;
import org.apache.flink.connector.jdbc.JdbcExecutionOptions;
import org.apache.flink.connector.jdbc.JdbcSink;
import org.apache.flink.connector.jdbc.JdbcStatementBuilder;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.SinkFunction;import java.sql.PreparedStatement;
import java.sql.SQLException;/*** @author 刘xx* @version 1.0* @date 2023-11-18 12:32*/
public class SinkMySQL {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);SingleOutputStreamOperator<WaterSensor> sensorDS = env.socketTextStream("localhost", 9999).map(new WaterSensorFunction()); //输入进来的数据自动转为 WaterSensor类型/*** todo 写入 mysql* 1.这里需要用旧的sink写法:addSink* 2.JDBC的4个参数*   (1) 执行的sql语句*   (2) 对占位符进行填充*   (3) 执行选项  -> 攒批,重试*   (4) 连接选项 -> driver,username,password,url*/SinkFunction<WaterSensor> jdbcSink = JdbcSink.sink("insert into flink.ws values(?,?,?)",// 指定 sql 中占位符的值new JdbcStatementBuilder<WaterSensor>() {@Overridepublic void accept(PreparedStatement stmt, WaterSensor sensor) throws SQLException {// 占位符从 1 开始stmt.setString(1, sensor.getId());stmt.setLong(2, sensor.getTs());stmt.setInt(3, sensor.getVc());}}, JdbcExecutionOptions.builder().withMaxRetries(3)  //最多重试3次(不包括第一次,共4次).withBatchSize(100) //每收集100条记录进行一次写入.withBatchIntervalMs(3000)  // 批次3s(即使没有达到100条记录,只要过了3s JDBCSink也会进行记录的写入),这有助于确保数据及时写入,而不是无限期地等待批处理大小达到。.build(), new JdbcConnectionOptions.JdbcConnectionOptionsBuilder().withUrl("jdbc:mysql://localhost:3306/flink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8").withDriverName("com.mysql.cj.jdbc.Driver").withUsername("root").withPassword("Yan1029.")// mysql 默认8小时不使用连接就主动断开连接.withConnectionCheckTimeoutSeconds(60) // 重试连接直接的间隔,上面我们设置最多重试3次,每次间隔60s.build());sensorDS.addSink(jdbcSink);env.execute();}
}

 查询结果:

5、自定义 Sink 输出

与 Source 类似,Flink 为我们提供了通用的 SinkFunction 接口和对应的 RichSinkDunction抽象类,只要实现它,通过简单地调用 DataStream 的.addSink()方法就可以自定义写入任何外部存储。

这里我们自定义实现一个向 HBase 中插入数据的 Sink。

注意:这里只是做一个简单的 Demo,下面的代码不难发现,我们只是对 nosq:student 表下的 info:name 进行了两次的覆盖。如果要实现复杂的处理功能,需要对数据类型进行定义,因为 HBase 的数据是按列存储的,所以对于复杂的 Hbase 表,我们难以通过 Java bean 来插入数据。而且,一般经常用的连接器,Flink 大部分已经提供了,开发中我们一般也很少自定义 Sink 输出。

package com.lyh.sink;import com.lyh.utils.HBaseConnection;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.RichSinkFunction;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;import java.nio.charset.StandardCharsets;/*** @author 刘xx* @version 1.0* @date 2023-11-18 15:59*/
public class SinkCustomHBase {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);env.fromElements("tom","bob").addSink(new RichSinkFunction<String>() {public Connection con;@Overridepublic void open(Configuration parameters) throws Exception {super.open(parameters);con = HBaseConnection.getConnection("hadoop102:2181");}@Overridepublic void invoke(String value, Context context) throws Exception {super.invoke(value, context);Table table = con.getTable(TableName.valueOf("nosql","student"));Put put = new Put("1001".getBytes(StandardCharsets.UTF_8));put.addColumn("info".getBytes(StandardCharsets.UTF_8),"name".getBytes(StandardCharsets.UTF_8),value.getBytes(StandardCharsets.UTF_8));table.put(put);table.close();}@Overridepublic void close() throws Exception {super.close();HBaseConnection.close();}});env.execute();}
}

这里用到一个简单的连接 HBase 的工具类:
 

package com.lyh.utils;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;import java.io.IOException;/*** @author 刘xx* @version 1.0* @date 2023-11-18 16:04*/
public class HBaseConnection {private static Connection connection;public static Connection getConnection(String hosts) throws IOException {Configuration conf = new Configuration();conf.set("hbase.zookeeper.quorum", hosts);conf.setInt("hbase.rpc.timeout", 10000); // 设置最大超时 10 sconnection = ConnectionFactory.createConnection(conf);return connection;}public static void close() throws IOException {if (connection!=null)connection.close();}
}

 

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

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

相关文章

Windows上搭建一个网站(基本生产环境)

前言 本博客记录的是Windows上一次网站搭建的过程&#xff0c;主要是在前端采用的是React&#xff0c;后端采用的是Flask&#xff0c;记录一下生产版本搭建流程和坑点&#xff0c;供有缘人一起进步&#xff0c;当然本博客还存在很多不足。 前端项目构建生产版本 以React为例…

Pandas+Matplotlib 数据分析

利用可视化探索图表 一、数据可视化与探索图 数据可视化是指用图形或表格的方式来呈现数据。图表能够清楚地呈现数据性质&#xff0c; 以及数据间或属性间的关系&#xff0c;可以轻易地让人看图释义。用户通过探索图&#xff08;Exploratory Graph&#xff09;可以了解数据的…

实在智能携手中国电信翼支付,全球首款Agent智能体亮相2023数字科技生态大会

11月10日-13日&#xff0c;中国电信与广东省人民政府联合主办的“2023数字科技生态大会”在广州隆重举行。本届大会以“数字科技焕新启航”为主题&#xff0c;邀请众多生态合作伙伴全方位展示数字科技新成果&#xff0c;包括数字新消费、产业数字化、智能电子、人工智能大模型等…

K-Means算法进行分类

已知数据集D中有9个数据点&#xff0c;分别是&#xff08;1,2&#xff09;&#xff0c;(2,3), (2,1), (3,1),(2,4),(3,5),(4,3),(1,5),(4,2)。采用K-Means算法进行聚类&#xff0c;k2&#xff0c;设初始中心点为&#xff08;1.1,2.2&#xff09;&#xff0c;&#xff08;2.3,3.…

OpenAI发布会中不起眼的重大更新

上周&#xff0c;OpenAI的历史首届开发者大会上&#xff0c;OpenAI的首席执行官山姆奥特曼展示了一系列产品更新&#xff0c;包含了众多重磅功能&#xff0c;就算单独拿出来都能让科技圈震一震&#xff0c;一下能发布这么多也真是家底厚。 果不其然&#xff0c;接下来的一周&am…

Java拼图

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 创建一个代码类 和一个运行类 代码如下&#xff1a; package heima;import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import jav…

Hive语法,函数--学习笔记

1&#xff0c;排序处理 1.1cluster by排序 &#xff0c;在Hive中使用order by排序时是全表扫描&#xff0c;且仅使用一个Reduce完成。 在海量数据待排序查询处理时&#xff0c;可以采用【先分桶再排序】的策略提升效率。此时&#xff0c; 就可以使用cluster by语法。 cluster…

RocketMQ(三):集成SpringBoot

RocketMQ系列文章 RocketMQ(一)&#xff1a;基本概念和环境搭建 RocketMQ(二)&#xff1a;原生API快速入门 RocketMQ(三)&#xff1a;集成SpringBoot 目录 一、搭建环境二、不同类型消息1、同步消息2、异步消息3、单向消息4、延迟消息5、顺序消息6、带tag消息7、带key消息 一…

Accelerate 0.24.0文档 三:超大模型推理(内存估算、Sharded checkpoints、bitsandbytes量化、分布式推理)

文章目录 一、内存估算1.1 Gradio Demos1.2 The Command 二、使用Accelerate加载超大模型2.1 模型加载的常规流程2.2 加载空模型2.3 分片检查点&#xff08;Sharded checkpoints&#xff09;2.4 示例&#xff1a;使用Accelerate推理GPT2-1.5B2.5 device_map 三、bitsandbytes量…

LeetCode【13】罗马数字转整数

题目&#xff1a; 思路&#xff1a; 第十二题的逆运算&#xff0c;方法同理。需要注意的是IV、IX、XL、XC、CD、CM这六种特殊的情况。正常情况下每个字符找到对应的数值累加&#xff0c;这六种特殊字符都是左边的数值比右边的数值小。 这里以IV举例&#xff0c;IV对应数字是1和…

详解如何使用Jenkins一键打包部署SpringBoot项目

目录 1、Jenkins简介 2、Jenkins的安装及配置 2.1、Docker环境下的安装​编辑 2.2、Jenkins的配置 3、打包部署SpringBoot应用 3.1、在Jenkins中创建执行任务 3.2、测试结果 1、Jenkins简介 任何简单操作的背后&#xff0c;都有一套相当复杂的机制。本文将以SpringBoot应…

文本向量化

文本向量化表示的输出比较 import timeimport torch from transformers import AutoTokenizer, AutoModelForMaskedLM, AutoModel# simcse相似度分数 def get_model_output(model, tokenizer, text_str):"""验证文本向量化表示的输出:param model: 模型的…

linux systemd start stop enable disable命令区别

一、systemd 的服务在三个文件件下 /lib/systemd/system /etc/systemd/system /usr/lib/systemd/system 终于明白这几个命令的区别 systemd star systemd stop systemd enable systemd disable 二、 1、用ssh服务为例&#xff0c;&#xff0c;ssh是客户端&#xff0c;远程ss…

持续集成交付CICD:Jenkins通过API触发流水线

目录 一、理论 1.HTTP请求 2.调用接口的方法 3.HTTP常见错误码 二、实验 1.Jenkins通过API触发流水线 三、问题 1.如何拿到上一次jenkinsfile文件进行自动触发流水线 一、理论 1.HTTP请求 &#xff08;1&#xff09;概念 HTTP超文本传输协议&#xff0c;是确保服务器…

JS特效:跟随鼠标移动的小飞机

前端网页中&#xff0c;用JS实现鼠标移动时&#xff0c;页面中的小飞机向着鼠标移动。 效果 源码 <!DOCTYPE html> <html><head><style>*{margin: 0;padding: 0;}body{height: 100vh;background: linear-gradient(200deg,#005bea,#00c6fb);}#plane{…

[C/C++]数据结构 链表(单向链表,双向链表)

前言: 上一文中我们介绍了顺序表的特点及实现,但是顺序表由于每次扩容都是呈二倍增长(扩容大小是自己定义的),可能会造成空间的大量浪费,但是链表却可以解决这个问题. 概念及结构: 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接…

HC-SR501传感器制作一个报警系统

接线图&#xff1a; 引脚连接&#xff1a; 1. 将 PIR 信号引脚连接到 arduino 数字 引脚 13。 2. 将 PIR V 引脚连接 到 arduino 5v 引脚。 3. 将 PIR GND 引脚连接到 arduino GND 引脚。 4. 将arduino数字 引脚12连接 到220欧姆电阻&#xff0c;并将该电阻连接到 LED V …

提升工作效率,打造精细思维——OmniOutliner 5 Pro for Mac

在当今快节奏的工作环境中&#xff0c;如何高效地组织和管理我们的思维和任务成为了关键。而OmniOutliner 5 Pro for Mac正是为此而生的一款强大工具。无论你是专业写作者、项目经理还是学生&#xff0c;OmniOutliner 5 Pro for Mac都能帮助你提升工作效率&#xff0c;打造精细…

Fibonacci 数列与黄金分割

mapp[1 for item in range(30)] for item in range(3,30):mapp[item]mapp[item-1]mapp[item-2]pass numint(input()) if num>19:print("0.61803399")pass else:anss float((mapp[num]*1.0) / (mapp[num 1]*1.0))print(format(anss,.8f))进行短程的打表就可以看出…

实用篇-ES-DSL查询文档

数据的存储不是目的&#xff0c;我们希望从海量的酒店数据中检索出需要的信息&#xff0c;这就是ES的搜索功能 官方文档: https://elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html#query-dsl。DSL是用来查询文档的 Elasticsearch提供了基于JSON的DSL来定…