Scala — сопоставление шаблонов строк Spark sql в структуре

Я пытаюсь выполнить сопоставление шаблонов внутри функции карты Dataframe - сопоставление строки с шаблоном строки, имеющим вложенный класс Case. Этот кадр данных является результатом объединения и имеет схему, показанную ниже. Он имеет несколько столбцов примитивных типов и 2 составных столбца:

case class MyList(values: Seq[Integer])
case class MyItem(key1: String, key2: String, field1: Integer, group1: MyList, group2: MyList, field2: Integer)
val myLine1 = new MyItem ("MyKey01", "MyKey02", 1, new MyList(Seq(1)), new MyList(Seq(2)), 2)
val myLine2 = new MyItem ("YourKey01", "YourKey02", 2, new MyList(Seq(2,3)), new MyList(Seq(4,5)), 20)
val dfRaw = Seq(myLine1, myLine2).toDF
dfRaw.printSchema
dfRaw.show
val df2 = dfRaw.map(r => r match {
    case Row(key1: String, key2: String, field1: Integer, group1: MyList, group2: MyList, field2: Integer) => "Matched"
    case _ => "Un matched"
})
df2.show

Моя проблема в том, что после этой функции карты все, что я получил, было «Не сопоставлено»:

root
 |-- key1: string (nullable = true)
 |-- key2: string (nullable = true)
 |-- field1: integer (nullable = true)
 |-- group1: struct (nullable = true)
 |    |-- values: array (nullable = true)
 |    |    |-- element: integer (containsNull = true)
 |-- group2: struct (nullable = true)
 |    |-- values: array (nullable = true)
 |    |    |-- element: integer (containsNull = true)
 |-- field2: integer (nullable = true)
+---------+---------+------+--------------------+--------------------+------+
|     key1|     key2|field1|              group1|              group2|field2|
+---------+---------+------+--------------------+--------------------+------+
|  MyKey01|  MyKey02|     1|   [WrappedArray(1)]|   [WrappedArray(2)]|     2|
|YourKey01|YourKey02|     2|[WrappedArray(2, 3)]|[WrappedArray(4, 5)]|    20|
+---------+---------+------+--------------------+--------------------+------+
df2: org.apache.spark.sql.Dataset[String] = [value: string]
+----------+
|     value|
+----------+
|Un matched|
|Un matched|
+----------+

Если я проигнорирую эти два столбца структуры в ветви case (заменив group1: MyList, group2: MyList на _, _, тогда это работает

case Row(key1: String, key2: String, field1: Integer, group1: MyList, group2: MyList, field2: Integer) => "Matched"

Не могли бы вы помочь, как выполнить сопоставление с образцом в этом классе Case? Спасибо!


person Averell    schedule 19.04.2018    source источник
comment
Используйте dfRaw.as[MyItem] и замените Row на MyItem, и ваш существующий код также должен работать.   -  person philantrovert    schedule 19.04.2018


Ответы (1)


struct столбцы обрабатываются как org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema в spark

поэтому вам придется определить регистр соответствия как

import org.apache.spark.sql.catalyst.expressions._
val df2 = dfRaw.map(r => r match {
    case Row(key1: String, key2: String, field1: Integer, group1: GenericRowWithSchema, group2: GenericRowWithSchema, field2: Integer) => "Matched"
    case _ => "Un matched"
})

И определение регистра соответствия с подстановочным знаком (_) работает, потому что компилятор Scala неявно оценивает org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema как тип данных.

Определение case, как показано ниже, должно работать также, как и с подстановочным знаком, из-за неявной оценки

case Row(key1: String, key2: String, field1: Integer, group1, group2, field2: Integer) => "Matched"
person Ramesh Maharjan    schedule 19.04.2018
comment
Спасибо Рамеш. Это сработало. Однако теперь мне нужно будет извлечь Seq[Integer] из этой GenericRowWithSchema. Я ищу, как это сделать. Если можете, тоже помогите. Моя цель состоит в том, чтобы хранить упорядоченный список, который будет служить очередью FIFO. Будет ли лучше, если я сохраню свой список непосредственно в виде массива? - person Averell; 19.04.2018
comment
Вы должны принять этот ответ как принятый и задать для этого другой вопрос. Но прежде чем задать другой вопрос, изучите, был ли этот вопрос уже задан и на него есть принятый ответ или нет. Я помогу вам, если на него еще не ответили - person Ramesh Maharjan; 19.04.2018
comment
Извините, я просматриваю свой телефон и не нашел, как принять ответ. Сделаю это правильно, когда у меня будет доступ к настольному браузеру. Да, я пытался искать и еще не нашел решения для этой GenericRowWithSchema. Буду продолжать искать - person Averell; 19.04.2018
comment
Да так и должно быть. Вы должны искать ответ на свою проблему, и когда вы его не найдете, тогда только вы должны задавать вопрос. - person Ramesh Maharjan; 19.04.2018
comment
Я использую spark 2.1, и, похоже, там пока нет поддержки использования Seq. Так что до сих пор у меня нет решения. Сопоставление с образцом с помощью GenericRowWithSchema помогает перейти к правильной ветке case, но не может помочь дальше. - person Averell; 19.04.2018
comment
разве ваш вопрос не Could you please help on how to do pattern matching on that Case class?? На ваш вопрос о сопоставлении с образцом отвечает этот вопрос. тогда почему ты проголосовал? Вы должны задать другой вопрос для другой проблемы. - person Ramesh Maharjan; 19.04.2018
comment
какую помощь вы хотите дальше? - person Ramesh Maharjan; 19.04.2018
comment
Привет, Рамеш. Извините, но я не проголосовал. Думаю, кто-то еще. И я отметил ваш ответ как принятый. Спасибо за помощь. Я все еще ищу решение для извлечения данных из этого Seq[Integer] в Spark 2.1. - person Averell; 20.04.2018
comment
@Averell Аверелл Я догадался, что это не ты проголосовал против. :) удачи в вашем поиске. если вы не найдете ответ, вы всегда можете задать другой вопрос;) - person Ramesh Maharjan; 20.04.2018