介绍MongoDB Spark连接器的最新版本
MongoDB刚刚发布了一个全新的Spark连接器版本。本文讨论了MongoDB Spark连接器背后的背景以及新版本的一些关键功能。
为什么是新版本?
当前版本的MongoDB Spark连接器是在2016年编写的,基于Spark数据源API的第一版。这个API仍然被支持,但Databricks已经发布了API的更新版本,使MongoDB等数据源更容易在Spark生态系统中工作。通过使用MongoDB Spark连接器的第2版,你将立即受益于各种功能,如与Spark结构化流的更紧密集成。
MongoDB将继续支持版本1,直到Databricks废弃其数据源API,但不会实现新的功能,连接器的升级将只包括错误修复和对当前版本的支持。
我应该使用哪个版本?
新的Spark连接器(10.0版)并不打算直接替代使用当前MongoDB Spark连接器的应用程序。请注意,新的连接器使用不同的命名空间,"com.mongodb.spark.sql.connector.MongoTableProvider",而原来的Spark连接器则使用 "com.mongodb.spark.DefaultSource"。有了不同的命名空间,就有可能在同一个Spark应用程序中使用两个版本的连接器。这有助于用新的连接器对你的应用程序进行单元测试,并在你的时间线上进行过渡。
还要注意MongoDB Spark连接器的版本变化。现有MongoDB Spark连接器的当前版本是3.0。到目前为止,随着MongoDB发布连接器的版本,其编号与支持的Spark版本一致--即MongoDB Spark连接器的2.4版本与Spark 2.4兼容。今后,情况就不是这样了。MongoDB的文档将明确说明连接器支持哪些版本的Spark并提供适当的信息。
结构化流向MongoDB
Apache Spark自带的流处理引擎称为结构化流,它是基于Spark的SQL引擎和DataFrame APIs。Spark结构化流将每个传入的数据流视为一个微批,不断地将每个微批追加到目标数据集。这使得现有的Spark批处理作业很容易转换为流作业。结构化流通过使Spark成为如此受欢迎的平台的同样的分布式能力,提供了最大的吞吐量。在下面的例子中,我们将向你展示如何使用结构化流将数据流转到MongoDB。
考虑一个包含天然气价格的CSV文件。下面的PySpark代码将把CSV文件读入一个流中,计算移动平均线,并将结果流向MongoDB。
from pyspark.sql.types import StructType, DateType, StringType, TimestampType, DoubleType
from pyspark.sql import functions as F
from pyspark.sql.window import Window
from pyspark.sql.functions import lit, count
sc.setLogLevel('DEBUG')
readSchema = ( StructType()
.add('Type', StringType())
.add('Date', TimestampType())
.add('Price', DoubleType())
)
ds = (spark
.readStream.format("csv")
.option("header", "true")
.schema(readSchema)
.load("daily*.csv"))
slidingWindows = (ds
.withWatermark("Date", "1 minute")
.groupBy(ds.Type, F.window(ds.Date, "7 day"))
.avg()
.orderBy(ds.Type,'window'))
dsw = (
slidingWindows
.writeStream
.format("mongodb")
.queryName("7DaySlidingWindow")
.option("checkpointLocation", "/tmp/pyspark/")
.option("forceDeleteTempCheckpointLocation", "true")
.option('spark.mongodb.connection.uri', 'MONGODB CONNECTION HERE')
.option('spark.mongodb.database', 'Pricing')
.option('spark.mongodb.collection', 'NaturalGas')
.outputMode("complete"))
query = dsw.start()
query.processAllAvailable()
query.stop()