У меня есть 2 набора данных Spark: LessonDS и latestLessonDS;

Это мой набор данных Spark POJO:

Lesson class:
    private List<SessionFilter> info;
    private lessonId;

LatestLesson class:

   private String id:

SessionFilter class:
   private String id;
   private String sessionName;

Я хочу получить все данные урока, где info.id в классе Lesson не в идентификаторе LatestLesson.

Что-то вроде этого:

lessonDS.filter(explode(col("info.id")).notEqual(latestLessonDS.col("value"))).show();

latestLessonDS contain:

100A
200C
300A
400A


lessonDS contain:

1,[[100A,jon],[200C,natalie]]
2,[[100A,jon]]
3,[[600A,jon],[400A,Kim]]

result:
3,[[600A,jon]
1
Coder123 1 Сен 2020 в 19:41

2 ответа

Лучший ответ

Обычно array_contains может использоваться как условие соединения при объединении lessonDs и latestLessonDs. Но эта функция здесь не работает, поскольку условие соединения требует, чтобы все элементы lessonDs.info.id появлялись в latestLessonDS.

Чтобы получить результат, нужно взорвать lessonDs, соединить с latestLessonDs и затем проверить, есть ли для всех элементов lessonDs.info запись в latestLessonDs существует путем сравнения количества информационных элементов до и после соединения:

lessonDs
  .withColumn("noOfEntries", size('info))
  .withColumn("id", explode(col("info.id")))
  .join(latestLessonDs, "id" )
  .groupBy("lessonId", "info", "noOfEntries").count()
  .filter("noOfEntries = count")
  .drop("noOfEntries", "count")
  .show(false)

Печать

+--------+------------------------------+
|lessonId|info                          |
+--------+------------------------------+
|1       |[[100A, jon], [200C, natalie]]|
|2       |[[100A, jon]]                 |
+--------+------------------------------+
1
werner 1 Сен 2020 в 19:29

Если размер вашего набора данных latestLessonDS достаточно разумен, вы можете собрать его и транслировать, а затем простое преобразование фильтра на lessonDS даст вам желаемый результат.

Нравится

import scala.collection.JavaConversions._
 import spark.implicits._ 
 val bc = spark.sparkContext.broadcast(latestLessonDS.collectAsList().toSeq)
    lessonDS.mapPartitions(itr => {
      val cache = bc.value;
      itr.filter(x => {
        //check in cache 
      })
    })
2
kavetiraviteja 1 Сен 2020 в 17:04