Scala 按键查找Spark RDD

Scala 按键查找Spark RDD,scala,apache-spark,mapreduce,hbase,rdd,Scala,Apache Spark,Mapreduce,Hbase,Rdd,我有一个从HBase转换而来的RDD: val hbaseRDD:RDD[(字符串,数组[String]),其中tuple.\u 1是行键。数组是HBase中的值 4929101-ACTIVE, ["4929101","2015-05-20 10:02:44","dummy1","dummy2"] 4929102-ACTIVE, ["4929102","2015-05-20 10:02:44","dummy1","dummy2"] 4929103-ACTIVE, ["4929103","2015

我有一个从HBase转换而来的RDD:

val hbaseRDD:RDD[(字符串,数组[String]),其中tuple.\u 1是行键。数组是HBase中的值

4929101-ACTIVE, ["4929101","2015-05-20 10:02:44","dummy1","dummy2"]
4929102-ACTIVE, ["4929102","2015-05-20 10:02:44","dummy1","dummy2"]
4929103-ACTIVE, ["4929103","2015-05-20 10:02:44","dummy1","dummy2"]
我还将SchemaRDD(id、date1、col1、col2、col3)转换为

val refDataRDD:RDD[(String,Array[String]),我将对其进行迭代并检查它是否存在于hbaseRDD中:

4929103, ["2015-05-21 10:03:44","EV01","col2","col3"]
4929104, ["2015-05-21 10:03:44","EV02","col2","col3"]
问题是,

  • 如何检查hbaseRDD中是否存在键(tuple.\u 1)/(“4929103”)并获取相应的值(tuple.\u 2)?-我不能在rdd.filter中使用pairdd的查找函数,它抛出“scala.MatchError:null”,但它在外部工作

    val filteredRDD = rdd.filter(sqlRow => {
      val hbaseLookup = hbaseRDD.lookup(sqlRow(0).toString + "-ACTIVE")
      // if found, check if date1 of hbaseRDD < sqlRow(1)
      // else if not found, retain row
      true
    })
    
    注意:我在这些行之前进行hbaseRDD.count。hbaseRDD.lookup在rdd.filter之外工作正常


因此,基本上,我试图通过hbaseRDD中的键“查找”并获取行/值。连接它们有点复杂,因为两个RDD中的某些值都可能为null。这取决于很多场景,哪些行将保留哪些数据。

假设您需要查找的一组id包含在RDD中,我认为您可以使用leftOuterJoin,而不是迭代和查找每个值

我在上面看到了你关于date1可能变化的位置的评论。不过,我不会在下面讨论它,我认为应该在查找之前通过每行的某种特定映射来处理它

如果我正确地获取了伪代码,那么您的RDD为
(id,date)
,并且希望通过在hbase中查找数据来更新它,并且如果在hbase中找到此id的行并且其日期早于refData中的行,则更新日期。对吗

如果是这样,假设您有如下参考数据:

val refData = sc.parallelize(Array(
 ("4929103","2015-05-21 10:03:44"),
 ("4929104","2015-05-21 10:03:44")
))
以及来自Hbase的一些行数据:

val hbaseRDD = sc.parallelize(Array(
    ("4929101-ACTIVE", Array("4929101","2015-05-20 10:02:44")),
    ("4929102-ACTIVE", Array("4929102","2015-05-20 10:02:44")),
    ("4929103-ACTIVE", Array("4929103","2015-05-20 10:02:44"))
))
然后,您可以使用一个简单的leftOuterJoin将每个id从refData查找到hbase中,对于找到的每一行:如有必要,更新日期:

refData
  // looks up in Hbase all rows whose date1 a_id value matches the id in searchedIds
  .leftOuterJoin(hbaseRDD.map{ case (rowkey, Array(a_id, date1)) => (a_id, date1)})

  // update the date in refData if date from hBase is earlier
  .map { case (rowKey, (refDate, maybeRowDate)) => ( rowKey, chooseDate (refDate, maybeRowDate)) }
  .collect


def chooseDate(refDate: String, rowDate: Option[String]) =  rowDate match {

  // if row not found in Hbase: keep ref date
  case None => refDate

  case Some(rDate) => 
    if (true) /* replace this by first parsing the date, then check if rowDate < refDate */ 
        rowDate
    else
        refDate
}
refData
//在Hbase中查找date1 a_id值与searchedIds中的id匹配的所有行
.leftOuterJoin(hbaseRDD.map{case(rowkey,数组(a_id,date1))=>(a_id,date1)})
//如果hBase中的日期更早,则更新refData中的日期
.map{case(rowKey,(refDate,maybeRowDate))=>(rowKey,choostate(refDate,maybeRowDate))}
.收集
def choostate(refDate:String,rowDate:Option[String])=rowDate匹配{
//如果在Hbase中未找到行:保留参考日期
案例无=>refDate
案例部分(rDate)=>
如果(true)/*请首先解析日期,然后检查rowDate是否
Hi,我不想更新rdd.date1,我想通过比较rdd和hbaseRDD的值来过滤rdd。我更新了帖子来澄清事情。谢谢你的澄清。我认为leftOuterJoin仍然是一条路要走,它比迭代rdd并在另一个rdd中查找值的计算成本要低得多。在上面定义的leftOuterJoin之后,基本上refData中每行有一个结果行,其中包含来自refData的数据,如果找到,还包含来自Hbase的数据。基于此,我相信您应该能够编写基于日期描述的过滤/标记逻辑。
refData
  // looks up in Hbase all rows whose date1 a_id value matches the id in searchedIds
  .leftOuterJoin(hbaseRDD.map{ case (rowkey, Array(a_id, date1)) => (a_id, date1)})

  // update the date in refData if date from hBase is earlier
  .map { case (rowKey, (refDate, maybeRowDate)) => ( rowKey, chooseDate (refDate, maybeRowDate)) }
  .collect


def chooseDate(refDate: String, rowDate: Option[String]) =  rowDate match {

  // if row not found in Hbase: keep ref date
  case None => refDate

  case Some(rDate) => 
    if (true) /* replace this by first parsing the date, then check if rowDate < refDate */ 
        rowDate
    else
        refDate
}