如何与所有其他行火花使用Scala的比较一行(How to compare one row with

2019-09-28 04:01发布

我有一列100K +名。 我需要比较他们每个人,以确定它们是否相同(杜泽,杜泽)或几乎相同(杜泽,Dsouza)。

我试着读卡桑德拉表到RDD,做与自身柱的笛卡尔积,形成一个元组。 但是,由于该列大小是100K,这导致了巨大的RDD,最终火花作业挂。

下面是我的代码:

    val valueRdd = sc.cassandraTable("keyspace", "some_table")
    val dataRDD = valueRdd
    .map(row => {
      (
        row
          .getStringOption("name")
          .get,

    }).cache()

    val cartesianResult = dataRDD cartesian dataRDD
    //Followed by some compare logic. May be soundex or some other library or some fuzzy logic. 

这里的问题是,笛卡尔结果将是100K * 100K这是不理想的秩序。 有没有更好的方式来做到这一点?

问题陈述是确定在给定数据集的兄弟姐妹。 该数据集将有它的100K +的数据。

Answer 1:

这份名单是足够小,可以将列表转换成广播变量,让每个节点进行比较时的RDD到广播列表的一部分:

val valueRddBC =sc.broadcast(valueRdd.collect())
val similarPairsRdd = valueRdd.flatMap(x => 
    valueRddBc.value.filter(y => dist(x,y) > threshold)
                  .map(y => (x,y)))

100K是很小,但有足够的,你可以做整个事情的驱动程序,如果你想(如果DIST功能也不是很贵,这将可能会更快)。

如果RDD是真正的大,你可以映射项某种指纹忽略大多数与战略无关的项目,诸如LSH(局部敏感哈希)。 这是一个近似最近邻算法,给出了O(1)寻找最接近的项目。



Answer 2:

请问您比较函数做任何事情更复杂的比较的名字呢? 如果你正在做的是去掉空格和撇号,你可以简单地转换成RDD键上的名称的简化版本一对RDD,然后用GROUPBY到组相似的名称。 例如:

scala> val rdd = sc.parallelize( List("d'souza", "d souza", "Dsouza") )
scala> rdd.map{ 
     |     case x => x.replaceAll(" ", "").replaceAll("'","").toLowerCase -> x
     | }.groupByKey.collect
res3: Array[(String, Iterable[String])] = Array((dsouza,CompactBuffer(d'souza, d souza, Dsouza)))


文章来源: How to compare one row with all other rows in spark using scala