Querying data
Working with where
expressions
The where
expression is a core component of building queries in Exposed, allowing you to filter data by specifying conditions. A where
expression expects a boolean operator (Op<Boolean>
), which evaluates to either true
or false
.
We’ve categorized the available conditions into the following groups:
Basic conditions
Basic conditions are simple comparisons, such as equality (eq
) and inequality (neq
).
eq
Checks if an expression is equal to some value.
neq
Checks if an expression is not equal to some value.
isNull()
Returns
true
if this expression is null,false
otherwise.isNotNull()
Returns
false
if this expression is null,true
otherwise.less
Checks if an expression is less than some value.
lessEq
Checks if an expression is less than or equal to some value.
greater
Checks if an expression is greater than some value.
greaterEq
Checks if an expression is greater than or equal to some value.
exists
Checks if a subquery returns at least one row.
notExists
Checks if a subquery does not return any row.
isDistinctFrom
Checks if this expression is not equal to another value, with null treated as a comparable value.
isNotDistinctFrom
Checks if an expression is equal to another value, with null treated as a comparable value.
Logical conditions
Logical conditions are those that use logical operators, such as AND
, OR
, and NOT
.
and
Returns the result of performing a logical
and
operation between two expressions.or
Returns the result of performing a logical
or
operation between two expressions.not
Returns the inverse of an expression.
andIfNotNull
Returns the result of performing a logical
and
operation between two expressions if the second one is not null.orIfNotNull
Returns the result of performing a logical
or
operation between two expressions if the second is not null.compoundAnd()
Reduces a list to a single expression by performing an
and
operation between all the expressions in the list.compoundOr()
Reduces a list to a single expression by performing an
or
operation between all the expressions in the list.
Pattern-matching conditions
Conditions that allow you to check for a match in a pattern using operators, such as LIKE
.
like
Checks if an expression matches the specified pattern.
val allMoviesLike = StarWarsFilmsTable.selectAll() .where { StarWarsFilmsTable.name like "The %" }notLike
Checks if an expression doesn't match the specified pattern.
val allMoviesNotLike = StarWarsFilmsTable.selectAll() .where { StarWarsFilmsTable.name notLike "The %" }regexp
Checks if an expression matches a regular expression.
val allMatchingRegex = StarWarsFilmsTable.selectAll() .where { StarWarsFilmsTable.name regexp "^The(\\s\\w+){2}\$" }match
Checks whether an expression matches a given pattern based on a specific mode.
Supported only on MySQL and MariaDB.
Range conditions
To check if a value lies within a specified range, use the between()
function.
It checks if an expression is between the values from and to. Returns true
if the expression is between the lower and upper range values (inclusive). Date and time values are also supported as arguments.
Collection conditions
To check if an expression is equal or not to any element from a list, use the inList
or notInList
operators.
Using inList
with lists
The inList
operator checks if an expression matches any value in a list. In the following example, the query selects all films with sequelId
values of 6 or 4.
Using inList
with Pairs or Triples
The inList
operator can also handle multiple expressions, such as pairs or triples, to check for equality across multiple columns.
Using ANY
and ALL
In addition to the IN
operator, the ANY
and ALL
operators are available with any preceding comparison operator:
anyFrom()
and allFrom()
also accept subqueries, tables, and array expressions as arguments.
Conditional WHERE
When working with SQL databases, it is a rather common case to have a query with a WHERE
clause that depends on certain conditions. These conditions often come from application logic or user input. Managing such conditions can become complex, especially with independent or nested conditions.
Imagine a form on a website where a user can optionally filter "Star Wars" films by a director and/or a sequel. To construct such a query, you can use the andWhere
function:
In the above example, the query starts with selectAll()
, which retrieves all rows from the StarWarsFilmsTable
. Then, the let
function is used to ensure that conditional WHERE
clauses for the directorName
and sequelId
are applied only if values are provided.
Conditional joins
Sometimes, you may need to modify not just the WHERE
clause but also the underlying table joins based on certain conditions. For example, filtering by an actor's name might require joining ActorsTable
conditionally.
In these cases, you can use the adjustColumnSet
and adjustSelect
functions, which allow to extend and modify JOIN
and SELECT
parts of a query:
Aggregating and sorting data
Count
The count()
method is used to determine the number of rows matching a query. It is called on a Query
object and returns the total count of rows.
The following example counts all rows where sequelId
equals 8
:
Order by
The orderBy()
function allows you to sort query results by specifying a list of columns and their sort order (ascending or descending).
In the following example, StarWarsFilmsTable.sequelId
specifies the column to sort by and SortOrder.ASC
sets the sort order to be ascending:
Group by
In groupBy
, define fields and their functions by the select()
method.
Available field functions are: count
, sum
, average
, min
and max
.
Limiting result sets
You can use the limit
function to prevent loading large data sets or to accomplish pagination by using the offset
function.
Mapping fields with alias
Aliases allow preventing ambiguity between field names and table names. Use the aliased var instead of original one:
Also, aliases allow you to use the same table in a join multiple times:
And they can be used when selecting from sub-queries:
Custom Select Queries
A Query
instance, which can be instantiated by calling selectAll()
or select()
on a Table
or Join
, has many extension functions for building complex queries. Some of these have already been mentioned above, like where(), groupBy(), and orderBy().
If a SELECT
query with a special clause is required, a custom extension function can be implemented to enable its use with other standard queries.
For example, MySQL index hints, which follow the table name in SQL, can be implemented on a SELECT
query by using the following custom function and class: