Iskra — это библиотека-оболочка Scala 3 вокруг Apache Spark API, которая позволяет писать типобезопасный и не требующий шаблонов, но при этом эффективный код Spark.
Начиная с версии 3.2.0, Spark кросс-компилируется также для Scala 2.13, что открывает возможность использования Spark из кода Scala 3, поскольку проекты Scala 3 могут зависеть от артефактов Scala 2.13.
Однако можно столкнуться с проблемами при попытке вызвать метод, требующий неявного экземпляра типа Spark Encoder
. Создание экземпляров Encoder
зависит от наличия TypeTag
для данного типа. Однако TypeTag
больше не генерируются компилятором Scala 3 (и поддержка этого не планируется), поэтому в большинстве случаев экземпляры Encoder
не могут быть автоматически синтезированы.
Iskra пытается обойти эту проблему, используя свои собственные кодеры (не связанные с типом Encoder
Spark), созданные с использованием нового API метапрограммирования Scala 3.
Iskra предоставляет тонкие (но строго типизированные) оболочки вокруг DataFrame
, которые отслеживают типы и имена столбцов во время компиляции, но позволяют Catalyst выполнять все свои оптимизации во время выполнения.
Iskra использует в качестве моделей данных структурные типы, а не классы Case, что дает нам большую гибкость (нет необходимости явно определять новый класс Case при добавлении/удалении/переименовании столбца!), но мы по-прежнему получаем ошибки компиляции, когда пытаемся относятся к столбцу, который не существует или не может использоваться в данном контексте.
//> using lib " org.virtuslab::iskra:0.0.3 "
scala-cli repl --dep org.virtuslab::iskra:0.0.3
build.sbt
в проекте sbt: libraryDependencies + = " org.virtuslab " %% " iskra " % " 0.0.3 "
Iskra построена на Scala 3.1.3, поэтому она совместима со Scala 3.1.x и более поздними второстепенными выпусками (начиная с 3.2.0 вы получите автодополнение кода для имен столбцов в REPL и Metals!). Искра транзитивно зависит от Спарка 3.2.0.
import org . virtuslab . iskra . api . *
given spark : SparkSession =
SparkSession
.builder()
.master( " local " )
.appName( " my-spark-app " )
.getOrCreate()
toTypedDF
в Seq
классов регистров, например Seq ( Foo ( 1 , " abc " ), Foo ( 2 , " xyz " )).toTypedDF
typed
расширения с параметром типа, представляющим класс случая, например df.typed[ Foo ]
Если по какой-то причине вам нужно вернуться в небезопасный мир нетипизированных фреймов данных, просто вызовите .untyped
для типизированного фрейма данных.
Эта библиотека призвана максимально напоминать исходный API Spark (например, используя те же имена методов и т. д.), где это возможно, хотя и пытается сделать код более похожим на обычный Scala без ненужного шаблона и добавления некоторых других синтаксических улучшений.
Наиболее важные различия:
$.foo.bar
вместо $"foo.bar"
или col("foo.bar")
. При необходимости используйте обратные кавычки, например $.`column with spaces`
..select(...)
или .select{...}
вы должны вернуть что-то, что является именованным столбцом или кортежем именованных столбцов. Из-за особенностей синтаксиса Scala вы можете написать просто .select($.x, $.y)
вместо select(($.x, $.y))
. С помощью фигурных скобок вы можете вычислять промежуточные значения, например .select {
val sum = ($.x + $.y).as( " sum " )
($.x, $.y, sum)
}
foos.innerJoin(bars).on($.foos.barId === $.bars.id).select(...)
foos
и bars
были автоматически выведены. Этот проект создан с использованием scala-cli, поэтому просто используйте традиционные команды с .
как root, как scala-cli compile .
или scala-cli test .
.
Более свежую версию раздела Usage
можно найти здесь.