Basics
Queryβ
To use scalaql
features, you should start by importing:
import scalaql._
// Docs classes
import scalaql.docs.Hogwarts._
The basic abstraction you'll use is a Query
.
It's a description of computations you want to perform on your data.
It doesn't evaluate until you explicitly run it:
select[Student]
// res0: Query[From[Student], Student] = FROM(Hogwarts::Student)
Then you could add basic filtering. For instance:
val filtered = select[Student]
.where(_.age >= 18)
// filtered: Query[From[Student], Student] = FROM(Hogwarts::Student) -> WHERE
To run the query and collect the results into a List
, there is a run
method, which could be used as follows:
filtered.toList.run(from(students))
// res1: List[Student] = List(
// Student(
// name = "Harry",
// age = 19,
// faculty = "Gryffindor",
// grade = 85.1,
// specialization = "getting into troubles",
// birthDay = 1980-07-31
// ),
// Student(
// name = "Ron",
// age = 18,
// faculty = "Gryffindor",
// grade = 66.2,
// specialization = "eating",
// birthDay = 1980-05-01
// ),
// Student(
// name = "Hermione",
// age = 18,
// faculty = "Gryffindor",
// grade = 99.6,
// specialization = "learning",
// birthDay = 1979-09-17
// ),
// Student(
// name = "Draco",
// age = 18,
// faculty = "Slytherin",
// grade = 85.1,
// specialization = "trolling",
// birthDay = 1980-06-05
// )
// )
Alternatively, you could also print them to the console via show
method.
It would render your data as a table:
filtered.show(truncate=false).run(from(students))
// +--------+---+----------+-----+---------------------+----------+
// |name |age|faculty |grade|specialization |birthDay |
// +--------+---+----------+-----+---------------------+----------+
// |Harry |19 |Gryffindor|85.1 |getting into troubles|1980-07-31|
// |Ron |18 |Gryffindor|66.2 |eating |1980-05-01|
// |Hermione|18 |Gryffindor|99.6 |learning |1979-09-17|
// |Draco |18 |Slytherin |85.1 |trolling |1980-06-05|
// +--------+---+----------+-----+---------------------+----------+
//
Data explorationβ
Assume you'd like to explore your data.
You could do this simply by calling describe
method on a Query
:
select[Student]
.describe()
.show(truncate=false)
.run(
from(students)
)
// +--------------+-----+-----+---------+----------+------------+------------+------------+----------+------+
// |field |count|mean |std |min |percentile25|percentile75|percentile90|max |unique|
// +--------------+-----+-----+---------+----------+------------+------------+------------+----------+------+
// |birthDay |5 |null |null |1977-10-01|null |null |null |1980-07-31|[] |
// |grade |5 |85.22|10.88474 |66.2 |85.1 |90.1 |99.6 |99.6 |[] |
// |name |5 |null |null |null |null |null |null |null |[] |
// |specialization|5 |null |null |null |null |null |null |null |[] |
// |age |5 |18.0 |0.6324555|17.0 |18.0 |18.0 |19.0 |19.0 |[] |
// |faculty |5 |null |null |null |null |null |null |null |[] |
// +--------------+-----+-----+---------+----------+------------+------------+------------+----------+------+
//
Using for comprehensionβ
It's allowed to use the Query
inside a for
comprehension.
For instance:
// it's cartesian product, not a join
val flatMapQuery: Query[From[Student] with From[Faculty], (Student, Faculty)] =
for {
student <- select[Student]
if student.age >= 18
faculty <- select[Faculty]
if faculty.name isIn ("Gryffindor", "Hufflepuff")
if student.faculty == faculty.name
} yield (student, faculty)
// flatMapQuery: Query[From[Student] with From[Faculty], (Student, Faculty)] = FROM(Hogwarts::Student) -> WHERE -> FLATMAP({From[=Hogwarts::Faculty] & From[=Hogwarts::Student]} => Tuple2[+Hogwarts::Student,+Hogwarts::Faculty])
NOTE
When combining multiple select
expressions, the type use pass as Query
input will be automatically captured in
the Query
type signature.
In this case, the resulting Query
input type will become From[Student] with From[Faculty]
.
This basically means that query expects both Student
and Faculty
data sources to be provided.
To run such Query
with multiple inputs, you could use &
operator on from
:
val input = from(students) & from(faculties)
// input: From[Student] with From[Faculty] = From[Hogwarts::Student] & From[Hogwarts::Faculty]
flatMapQuery
.show(truncate = false)
.run(input)
// +--------+------+----------+--------+---------------------+-----------+----------+-----------------+---------------------+
// |_1.name |_1.age|_1.faculty|_1.grade|_1.specialization |_1.birthDay|_2.name |_2.founder |_2.description |
// +--------+------+----------+--------+---------------------+-----------+----------+-----------------+---------------------+
// |Harry |19 |Gryffindor|85.1 |getting into troubles|1980-07-31 |Gryffindor|Godric Gryffindor|100 points by default|
// |Ron |18 |Gryffindor|66.2 |eating |1980-05-01 |Gryffindor|Godric Gryffindor|100 points by default|
// |Hermione|18 |Gryffindor|99.6 |learning |1979-09-17 |Gryffindor|Godric Gryffindor|100 points by default|
// +--------+------+----------+--------+---------------------+-----------+----------+-----------------+---------------------+
//