Skip to main content

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|
// +--------+------+----------+--------+---------------------+-----------+----------+-----------------+---------------------+
//