Java 如何在apachespark中为两个不同结构的数据帧实现notin

Java 如何在apachespark中为两个不同结构的数据帧实现notin,java,sql,apache-spark,apache-spark-sql,Java,Sql,Apache Spark,Apache Spark Sql,我在Java应用程序中使用ApacheSpark。 我有两个DataFrames:df1和df2。df1包含行s和电子邮件、名字和姓氏df2包含行和电子邮件 我想创建一个数据框:df3,其中包含df1中的所有行,该电子邮件在df2中不存在 有没有办法用ApacheSpark做到这一点?我试图从df1和df2创建JavaRDD,方法是将它们转换为toJavaRDD()并过滤df1以包含所有电子邮件,然后使用subtract,但我不知道如何将新的JavaRDD映射到ds1,并获得数据框架 基本上,我

我在Java应用程序中使用ApacheSpark。 我有两个
DataFrame
s:
df1
df2
df1
包含
s和
电子邮件
名字
姓氏
<代码>df2包含
电子邮件

我想创建一个
数据框
df3
,其中包含
df1
中的所有行,该电子邮件在
df2
中不存在

有没有办法用ApacheSpark做到这一点?我试图从
df1
df2
创建
JavaRDD
,方法是将它们转换为
toJavaRDD()
并过滤
df1
以包含所有电子邮件,然后使用
subtract
,但我不知道如何将新的
JavaRDD
映射到
ds1
,并获得
数据框架

基本上,我需要
df1
中的所有行,它们的电子邮件不在
df2

DataFrame customers = sqlContext.cassandraSql("SELECT email, first_name, last_name FROM customer ");

DataFrame customersWhoOrderedTheProduct = sqlContext.cassandraSql("SELECT email FROM customer_bought_product " +
                            "WHERE product_id = '" + productId + "'");

JavaRDD<String> customersBoughtEmail = customersWhoOrderedTheProduct.toJavaRDD().map(row -> row.getString(0));

List<String> notBoughtEmails = customers.javaRDD()
                        .map(row -> row.getString(0))
                        .subtract(customersBoughtEmail).collect();
DataFrame customers=sqlContext.cassandraSql(“从客户处选择电子邮件、名字、姓氏”);
DataFrame CustomerwhoOrderedtheProduct=sqlContext.cassandraSql(“从客户购买的产品中选择电子邮件”+
“其中product_id=”“+productId+”);
JavaRDD customersBoughtEmail=customerswhoordedtheproduct.toJavaRDD().map(row->row.getString(0));
List notBoughtEmails=customers.javaRDD()
.map(行->行.getString(0))
.subtract(customersBoughtEmail.collect();

Spark 2.0.0+

您可以直接在
中使用

火花<2.0.0

它可以使用外部联接和过滤器表示

val客户=sc.parallelize(Seq(
("john@example.com“,”约翰“,”多伊“,
("jane@example.com“,”简“,”多伊“)
)).toDF(“电子邮件”、“名”、“姓”)
val订购产品的客户=sc.parallelize(序号(
元组1(“jane@example.com")
)).toDF(“电子邮件”)
val未订购产品的客户=customers.join(
订购产品的客户。选择($“email”。别名(“email”),
$“email”==$“email”;“leftouter”)
.where($“email”.isNull).删除(“email”)
未订购产品的客户。显示
// +----------------+----------+---------+
//|电子邮件|名|姓|
// +----------------+----------+---------+
// |john@example.com|约翰·多伊|
// +----------------+----------+---------+
原始SQL等价物:

customers.RegisterEmptable(“客户”)
订购Product.RegisterEmptable的客户(
“订购产品的客户”)
val query=“”从客户c左外部联接中选择c*
订购产品o的客户
在c.email=o.email上
其中o.email为空“”
sqlContext.sql(查询).show
// +----------------+----------+---------+
//|电子邮件|名|姓|
// +----------------+----------+---------+
// |john@example.com|约翰·多伊|
// +----------------+----------+---------+

我是在
python
中完成的,此外,我建议您使用整数作为键,而不是字符串

from pyspark.sql.types import *

samples = sc.parallelize([
    ("abonsanto@fakemail.com", "Alberto", "Bonsanto"), ("mbonsanto@fakemail.com", "Miguel", "Bonsanto"),
    ("stranger@fakemail.com", "Stranger", "Weirdo"), ("dbonsanto@fakemail.com", "Dakota", "Bonsanto")
])

keys = sc.parallelize(
    [("abonsanto@fakemail.com",), ("mbonsanto@fakemail.com",), ("dbonsanto@fakemail.com",)]
)

complex_schema = StructType([
    StructField("email", StringType(), True),
    StructField("first_name", StringType(), True),
    StructField("last_name", StringType(), True)
])

simple_schema = StructType([
    StructField("email", StringType(), True)
])

df1 = sqlContext.createDataFrame(samples, complex_schema)
df2 = sqlContext.createDataFrame(keys, simple_schema)

df1.show()
df2.show()

df3 = df1.join(df2, df1.email == df2.email, "left_outer").where(df2.email.isNull()).show()

非常感谢。第一个例子对我很有用。这是Java版本
DataFrame customers whoOrderedtheProduct=customers.join(customers whoOrderedtheProduct.select(customers whoOrderedtheProduct.col)(“电子邮件”)、customers.col(“电子邮件”).equalTo(customers whoOrderedtheProduct.col”(“电子邮件”)、“leftouter”)。其中(customers whoOrderedtheProduct.col)(“电子邮件”).isNull()).drop(订购Product.col(“电子邮件”)的客户)
我尝试了SQL等价物,但出现了
scala.MatchError:UUIDType(类org.apache.spark.SQL.cassandra.types.UUIDType$)
我很高兴能提供帮助。我使用
cassandra
并且我有一个
UUID
作为主键。可能Scala无法匹配类型。能否尝试导入
com.datastax.spark.connector.types.UUIDType
?我正在IDE中运行此操作。我正在使用
setJars
将所有依赖项添加到Spark。我应该从哪里进口这个?我没有在查询中使用任何
UUID
。谢谢。我使用的是
Cassandra
,因此我的很多主键都包含
UUID