Scala 使用Spark将非规范化配置单元表加载到Elasticsearch中
所以,我找到了很多相反的答案,但不是这个。现在听起来很傻,因为Elasticsearch只处理非规范化数据,但这就是我们的问题所在。我们有一个格式如下的表:Scala 使用Spark将非规范化配置单元表加载到Elasticsearch中,scala,apache-spark,elasticsearch,hive,apache-spark-sql,Scala,Apache Spark,elasticsearch,Hive,Apache Spark Sql,所以,我找到了很多相反的答案,但不是这个。现在听起来很傻,因为Elasticsearch只处理非规范化数据,但这就是我们的问题所在。我们有一个格式如下的表: +----+--------+--------+--------+--------+---------+ | id | attr_1 | attr_2 | attr_3 | attr_4 | fst_nm | +----+--------+--------+--------+--------+---------+ | 1 | 298
+----+--------+--------+--------+--------+---------+
| id | attr_1 | attr_2 | attr_3 | attr_4 | fst_nm |
+----+--------+--------+--------+--------+---------+
| 1 | 2984 | 0324 | 38432 | | john |
| 2 | 2343 | 28347 | 238493 | 34923 | patrick |
| 3 | 3293 | 3823 | 38423 | 34823 | george |
+----+--------+--------+--------+--------+---------+
其中attr_x表示相同的确切内容,假设它们是另一个表的外键,当该表在规范化世界中分离时。因此,所有的属性都存在于一个单独的表中。然而,这些表被反序列化,它们都被转储到一个长表中。通常情况下,这个问题不大,无法加载到Elasticsearch中,但这个表非常庞大,大约有1000多列。我们希望将这些属性作为数组存储在Elasticsearch中,如下所示:
_source: {
"id": 1,
"fst_nm": "john",
"attrs": [
2984,
0324,
38432
]
}
+-----+--------+
| id | attr |
+-----+--------+
| 1 | 2984 |
| 1 | 0324 |
| 1 | 38432 |
| 2 | 2343 |
| ... | ... |
| 3 | 34823 |
+-----+--------+
而不是:
_source: {
"id": 1,
"fst_nm": "john",
"attr_1": 2984,
"attr_2": 0324,
"attr_3": 38432
}
当我们使用默认的Spark过程时,它只创建底部的Elasticsearch文档。我的一些想法是创建一个新的attrs
表,并取消对它们的调用,然后按ID查询该表,以获取attrs,因此它看起来像这样:
_source: {
"id": 1,
"fst_nm": "john",
"attrs": [
2984,
0324,
38432
]
}
+-----+--------+
| id | attr |
+-----+--------+
| 1 | 2984 |
| 1 | 0324 |
| 1 | 38432 |
| 2 | 2343 |
| ... | ... |
| 3 | 34823 |
+-----+--------+
然后我们可以使用Spark SQL在这个新创建的表上按id进行查询,获取属性,但是我们如何使用Spark将其作为数组插入Elasticsearch
我的另一个想法是在Hive中创建一个新表,并将attr更改为Hive复杂类型的数组,但我不知道该怎么做。此外,如果我们使用Spark在Hive中查询表,当结果以数组形式返回时,是否可以轻松转储到Elasticsearch中?至于数据转换部分,您可以使用
array
将多个列收集到一个数组中,然后您可以使用.write.json(“jsonfile”)
写入json文件:
import org.apache.spark.sql.functions.col
val attrs = df.columns.filter(_.startsWith("attr")).map(col(_))
val df_array = df.withColumn("attrs", array(attrs:_*)).select("id", "fst_nm", "attrs")
df_array.toJSON.collect
//res8: Array[String] = Array({"id":1,"fst_nm":"john","attrs":[2984,324,38432,null]}, {"id":2,"fst_nm":"patrick","attrs":[2343,28347,238493,34923]})
写入文件:
df_array.write.json("/PATH/TO/jsonfile")
对于数据转换部分,您可以使用
array
将多个列收集为一个数组,然后使用.write.json(“jsonfile”)
写入json文件:
import org.apache.spark.sql.functions.col
val attrs = df.columns.filter(_.startsWith("attr")).map(col(_))
val df_array = df.withColumn("attrs", array(attrs:_*)).select("id", "fst_nm", "attrs")
df_array.toJSON.collect
//res8: Array[String] = Array({"id":1,"fst_nm":"john","attrs":[2984,324,38432,null]}, {"id":2,"fst_nm":"patrick","attrs":[2343,28347,238493,34923]})
写入文件:
df_array.write.json("/PATH/TO/jsonfile")
这看起来像我想要的,但是我在
列上找不到符号。这是为较旧版本的Scala/Spark设计的吗?col
是一个sql函数,您需要导入它,请参阅更新。这看起来像我想要的,但是我在col
上找不到符号。这是否适用于较旧版本的Scala/Spark?col
是一个sql函数,需要导入它,请参阅更新。