Java 如何在apachespark中为两个不同结构的数据帧实现notin
我在Java应用程序中使用ApacheSpark。 我有两个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,并获得数据框架 基本上,我
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
。