根据spark中的模式匹配加载文件

时间:2018-03-02 07:46:17

标签: scala apache-spark rdd

我有31个输入文件,名称从date=2018-01-01date=2018-01-31

我能够以这种方式将所有这些文件加载​​到rdd中:

val input = sc.textFile("hdfs://user/cloudera/date=*")

但是如果我只想加载文件一周呢? (日期= 2018-01-15至日期= 2018-01-22的文件)。

2 个答案:

答案 0 :(得分:5)

您可以通过textFile

加入文件,将文件单独指定给,
val files = (15 to 22).map(
  day => "hdfs://user/cloudera/date=2018-01-" + "%02d".format(day)
).mkString(",")

产生:

hdfs://user/cloudera/date=2018-01-15,hdfs://user/cloudera/date=2018-01-16,hdfs://user/cloudera/date=2018-01-17,hdfs://user/cloudera/date=2018-01-18,hdfs://user/cloudera/date=2018-01-19,hdfs://user/cloudera/date=2018-01-20,hdfs://user/cloudera/date=2018-01-21,hdfs://user/cloudera/date=2018-01-22

你可以这样称呼它:

val input = sc.textFile(files)

注意当天的格式("%02d".format(day)),以便将前导0添加到1到9之间的日期。

答案 1 :(得分:2)

通过列出要加载的特定文件进行过滤,但为什么不再使用DataFrameReader更进一步,以便可以使用Spark SQL过滤掉date作为正确的列?在您使用CSV文件(通常很小)的情况下可能并不重要,并且您将使用RDD,但是学习更新的Spark API将来可能会有所帮助。适用于https://github.com/databricks/spark-csv

的Spark 2.0+
  val df = spark
    .read
    .format("com.databricks.spark.csv")
    .option("header", "true") // Use first line of all files as header
    .option("inferSchema", "true") // Automatically infer data types
    .option("basePath", "hdfs://user/cloudera/") // see https://spark.apache.org/docs/latest/sql-programming-guide.html#partition-discovery
    .load("hdfs://user/cloudera/*")

  val rdd = df
    .filter($"date" >= "2018-01-01" && $"date" <= "2018-01-31")
    .rdd

这种方法使用较新的API来加载数据,Spark SQL用于过滤掉所需的Hive分区,并依赖Spark Catalyst来确定只需要加载的必要文件(来自filter)。当您切换到更大量的数据和更高级的文件格式(如Parquet)时,可能会变得更有用。

spark-shell中的简化演示(Spark 2.0.2):

1)准备CSV文件

% cat ~/testdata/date=2018-01-03/test1
A,B,C
21,22,23
24,25,26
% cat ~/testdata/date=2018-01-02/test1
A,B,C
11,12,13
14,15,16
% cat ~/testdata/date=2018-01-01/test1
A,B,C
1,2,3
4,5,6

2)在spark-shell中运行

scala> val df = spark.read.format("com.databricks.spark.csv").option("header", "true").option("inferSchema", "true").option("basePath", "/Users/igork/testdata/").load("/Users/igork/testdata/*")
df: org.apache.spark.sql.DataFrame = [A: int, B: int ... 2 more fields]

scala> df.printSchema()
root
 |-- A: integer (nullable = true)
 |-- B: integer (nullable = true)
 |-- C: integer (nullable = true)
 |-- date: string (nullable = true)


scala> val rdd = df.filter($"date" >= "2018-01-01" && $"date" <= "2018-01-02").rdd
rdd: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row] = MapPartitionsRDD[25] at rdd at <console>:25

scala> rdd.collect().foreach(println)
[11,12,13,2018-01-02]
[14,15,16,2018-01-02]
[1,2,3,2018-01-01]
[4,5,6,2018-01-01]

注意RDD(和DataFrame)现在如何包含date作为字符串列,其值取自路径。这包含在https://spark.apache.org/docs/latest/sql-programming-guide.html#partition-discovery