Java 正在尝试统计Spark中两个类别之间的唯一用户

Java 正在尝试统计Spark中两个类别之间的唯一用户,java,sql,apache-spark,apache-spark-dataset,Java,Sql,Apache Spark,Apache Spark Dataset,我在Spark中有一个数据集结构,有两列,一列名为user,另一列名为category。这样表格看起来像这样: +---------------+---------------+ | user| category| +---------------+---------------+ | garrett| syncopy| | garrison| musictheory| | marta| sh

我在Spark中有一个数据集结构,有两列,一列名为
user
,另一列名为
category
。这样表格看起来像这样:

+---------------+---------------+
|           user|       category|
+---------------+---------------+
|        garrett|        syncopy|
|       garrison|    musictheory|
|          marta|     sheetmusic|
|        garrett|  orchestration|
|         harold|         chopin|
|          marta|   russianmusic|
|           niko|          piano|
|          james|     sheetmusic|
|          manny|         violin|
|        charles|       gershwin|
|         dawson|          cello|
|            bob|          cello|
|         george|          cello|
|         george|  americanmusic|
|            bob| personalcompos|
|         george|     sheetmusic|
|           fred|     sheetmusic|
|            bob|     sheetmusic|
|       garrison|     sheetmusic|
|         george|    musictheory|
+---------------+---------------+
only showing top 20 rows
+---------------+---------------+---------------+
|           user|       category|       category|
+---------------+---------------+---------------+
|       garrison|    musictheory|     sheetmusic|
|         george|    musictheory|     sheetmusic|
|       garrison|    musictheory|    musictheory|
|         george|    musictheory|    musicthoery|
|       garrison|     sheetmusic|    musictheory|
|         george|     sheetmusic|    musictheory|
+---------------+---------------+---------------+
表中的每一行都是唯一的,但用户和类别可以出现多次。目标是统计两个类别共享的用户数。例如,
cello
americanmusic
共享名为
george
musictheory
sheetmusic
的用户
george
garrison
。目标是获得n个类别之间不同用户的数量,这意味着类别之间最多有n个平方边。我部分了解如何进行此操作,但我正在努力将我的想法转换为Spark Java

我的想法是,我需要在
user
上进行自联接,以获得如下结构的表:

+---------------+---------------+
|           user|       category|
+---------------+---------------+
|        garrett|        syncopy|
|       garrison|    musictheory|
|          marta|     sheetmusic|
|        garrett|  orchestration|
|         harold|         chopin|
|          marta|   russianmusic|
|           niko|          piano|
|          james|     sheetmusic|
|          manny|         violin|
|        charles|       gershwin|
|         dawson|          cello|
|            bob|          cello|
|         george|          cello|
|         george|  americanmusic|
|            bob| personalcompos|
|         george|     sheetmusic|
|           fred|     sheetmusic|
|            bob|     sheetmusic|
|       garrison|     sheetmusic|
|         george|    musictheory|
+---------------+---------------+
only showing top 20 rows
+---------------+---------------+---------------+
|           user|       category|       category|
+---------------+---------------+---------------+
|       garrison|    musictheory|     sheetmusic|
|         george|    musictheory|     sheetmusic|
|       garrison|    musictheory|    musictheory|
|         george|    musictheory|    musicthoery|
|       garrison|     sheetmusic|    musictheory|
|         george|     sheetmusic|    musictheory|
+---------------+---------------+---------------+
Spark(Java代码)中的自连接操作并不困难:

Dataset<Row> newDataset = allUsersToCategories.join(allUsersToCategories, "users");
Dataset newDataset=allUsersToCategories.join(allUsersToCategories,“用户”);
这是有意义的,但是我得到了与上面示例中的第3行和第4行相同的类别的映射,并且我得到了向后映射,其中类别是颠倒的,本质上是重复计算每个用户交互,就像上面示例中的第5行和第6行一样

我认为我需要做的是在我的连接中加入某种条件,它表示沿着
X
的一些内容,这样就可以丢弃相同的类别和重复项。最后,我需要计算n个平方组合的不同行数,其中n是类别数

有人能解释一下如何在Spark中做到这一点吗?特别是Spark Java,因为我对Scala语法有点不熟悉


谢谢您的帮助。

我不确定是否正确理解您的要求,但我会尽力帮助您

根据我的理解,上述数据的预期结果如下所示。如果这不是真的,请让我知道,我会尝试作出要求的修改

+--------------+--------------+-+
|_1            |_2            |
+--------------+--------------+-+
|personalcompos|sheetmusic    |1|
|cello         |musictheory   |1|
|americanmusic |cello         |1|
|cello         |sheetmusic    |2|
|cello         |personalcompos|1|
|russianmusic  |sheetmusic    |1|
|americanmusic |sheetmusic    |1|
|americanmusic |musictheory   |1|
|musictheory   |sheetmusic    |2|
|orchestration |syncopy       |1|
+--------------+--------------+-+
在这种情况下,您可以使用以下Scala代码解决问题:

allUsersToCategories
    .groupByKey(_.user)
    .flatMapGroups{case (user, userCategories) =>
      val categories = userCategories.map(uc => uc.category).toSeq
      for {
         c1 <- categories
         c2 <- categories
         if c1 < c2
      } yield (c1, c2)
    }
    .groupByKey(x => x)
    .count()
    .show()

我试图用Java提供示例,但我没有Java+Spark的任何经验,而且将上面的示例从Scala迁移到Java对我来说太耗时了。

几小时前,我使用
Spark sql
找到了答案:

    Dataset<Row> connection per shared user = spark.sql("SELECT a.user as user, "
                                                            + "a.category as categoryOne, "
                                                            + "b.category as categoryTwo "
                                                            + "FROM allTable as a INNER JOIN allTable as b "
                                                            + "ON a.user = b.user AND a.user < b.user");
Dataset connection per shared user=spark.sql(“选择一个.user作为用户,”
+“a.作为类别的类别,”
+“b.分类为类别2”
+“从allTable作为内部联接allTable作为b”
+“ON a.user=b.user和a.user

然后,这将创建一个包含三列的数据集
user
categoryOne
,和
categoryTwo
。每一行都是唯一的,并将指示用户何时存在于这两个类别中。

编写SQL查询并执行它。任何过滤器都可以使用,SQL查询会显式使用什么