从MongoDB中读取数据,并在Scala Spark Connector中对多层JSON应用过滤器

时间:2019-08-02 09:32:23

标签: json scala apache-spark

我正在将MongoDb Scala连接器用于Spark。在文档中 https://docs.mongodb.com/spark-connector/master/scala/aggregation/

提到了如何在给定的JSON文档上应用过滤器。我无法弄清楚的是,如果我们有一个多层json并想对其应用过滤器,我们将如何访问json文档中的键/值。

Json文档:

{ "_id" : 1, "test" : 1 }
{ "_id" : 2, "test" : 2 }
{ "_id" : 3, "test" : 3 }
{ "_id" : 4, "test" : 4 }
{ "_id" : 5, "test" : 5 }
{ "_id" : 6, "test" : 6 }

过滤文档:

val rdd = MongoSpark.load(sc)

val filteredRdd = rdd.filter(doc => doc.getInteger("test") > 5)
println(filteredRdd.count)
println(filteredRdd.first.toJson)

多层Json文档

{
    "_id": 1,
    "test": 1,
    "additionalProperties": {
        "value": "35",
        "phone": "566623232"
    }
}

问题陈述:

我想基于“值”属性进行过滤,但是我不知道如何访问它。我尝试执行以下操作,但无法正常工作。

val filteredRdd = rdd.filter(doc => doc.getInteger("value") > 5)

val filteredRdd = rdd.filter(doc => doc.getInteger("additionalProperties.value") > 5)  

有人可以指导我如何访问“值”属性吗?什么是正确的语法。

我尝试过的其他一些选项:

根据Scala Connector for MongoDB的官方文档。我尝试使用聚合管道过滤文档。因此以下代码行可以正常工作:

val filterWithPipeline = customRdd.withPipeline(Seq(Document.parse("{ $match: { id: { $eq : '134' } } }")))

但是,如果我想使用相同的语法访问“值”项。没用

 val filterWithPipeline = customRdd.withPipeline(Seq(Document.parse("{ $match: { value: { $eq : '134' } } }")))

那么我该如何使用相同的方法来查询多级JSON?

2 个答案:

答案 0 :(得分:1)

如果使用dafaframe,该怎么办?

val df = spark.read.json("path")

这是我的例子,

+---+--------------------+----+
|_id|additionalProperties|test|
+---+--------------------+----+
|1  |[566623232, 35]     |1   |
|2  |[566623232, 35]     |2   |
|3  |[566623232, 1]      |3   |
+---+--------------------+----+

架构是

root
 |-- _id: long (nullable = true)
 |-- additionalProperties: struct (nullable = true)
 |    |-- phone: string (nullable = true)
 |    |-- value: string (nullable = true)
 |-- test: long (nullable = true)

然后

df.filter(col("additionalProperties").getItem("value").cast("int") > 5)

将给出如下结果:

+---+--------------------+----+
|_id|additionalProperties|test|
+---+--------------------+----+
|1  |[566623232, 35]     |1   |
|2  |[566623232, 35]     |2   |
+---+--------------------+----+

答案 1 :(得分:1)

以下是您可以从mongoDB中读取并过滤它的几种方法 创建SparkSession

val spark = SparkSession.builder().master("local").appName("Test")
  .config("spark.mongodb.input.uri", "mongodb://127.0.0.1/db.collectionName")
  .config("spark.mongodb.output.uri", "mongodb://127.0.0.1/db.CollectionName")
  .getOrCreate

import spark.implicits._
import com.mongodb.spark.sql._

读取为MongoRDD[Document]并对其进行过滤

MongoSpark.load(spark.sparkContext).filter(doc => {
  val value = doc.get("additionalProperties").asInstanceOf[Document].get("value")
  value.toString.toInt > 5
})

通过spark.read.mongo()读为Dataframe

val filterDF = spark.read.mongo().filter($"additionalProperties.value".lt(5))

输出:

+---+--------------------+----+
|_id|additionalProperties|test|
+---+--------------------+----+
|2.0|[5, 566623232]      |2.0 |
+---+--------------------+----+

希望这会有所帮助!