AnkQL Syntax
AnkQL is Ankurah’s query language for filtering entities. It uses familiar SQL-like syntax that works consistently across all storage backends.
Basic Comparisons
field = value # Equality
field != value # Not equal
field > value # Greater than
field >= value # Greater than or equal
field < value # Less than
field <= value # Less than or equal
Examples
let albums: Vec<AlbumView> = ctx.fetch("name = 'Dark Side of the Moon'").await?;
let albums: Vec<AlbumView> = ctx.fetch("year > 1985").await?;
let albums: Vec<AlbumView> = ctx.fetch("artist != 'Unknown'").await?;
Logical Operators
Combine conditions with AND and OR:
condition1 AND condition2
condition1 OR condition2
Use parentheses for complex logic:
(condition1 OR condition2) AND condition3
Examples
let albums: Vec<AlbumView> = ctx.fetch("year > 1980 AND year < 1990").await?;
let albums: Vec<AlbumView> = ctx.fetch("artist = 'Prince' OR artist = 'Madonna'").await?;
let albums: Vec<AlbumView> = ctx.fetch("(artist = 'Prince' OR artist = 'Madonna') AND year > 1985").await?;
The IN Operator
Check if a value is in a list:
field IN (value1, value2, value3)
Example
let albums: Vec<AlbumView> = ctx.fetch("year IN (1984, 1985, 1986)").await?;
Ordering Results
Use ORDER BY to sort results:
... ORDER BY field ASC
... ORDER BY field DESC
Examples
let albums: Vec<AlbumView> = ctx.fetch("year > 1980 ORDER BY year DESC").await?;
let albums: Vec<AlbumView> = ctx.fetch("true ORDER BY name ASC").await?;
Selecting All Entities
Use true to match all entities:
let albums: Vec<AlbumView> = ctx.fetch("true ORDER BY name ASC").await?;
String Values
String literals use single quotes:
let albums: Vec<AlbumView> = ctx.fetch("name = 'Purple Rain'").await?;
To include a single quote in a string, escape it with another single quote:
let albums: Vec<AlbumView> = ctx.fetch("name = 'Rock ''n'' Roll'").await?;
Variable Interpolation
Use the fetch! and selection! macros for dynamic queries. They support multiple syntaxes:
Unquoted Form
The unquoted form is the most concise. Variables expand to equality by default:
#![allow(unused)]
fn main() {
let artist = "Prince";
fetch!(ctx, {artist}).await?; // Equivalent to: artist = 'Prince'
}
Add comparison operators as prefixes:
// Unquoted form: {>year} expands to year > {year}
let year = 1985;
let albums: Vec<AlbumView> = fetch!(ctx, {>year}).await?;
All comparison operators work: {>var}, {<var}, {>=var}, {<=var}, {!=var}:
// All comparison operators work: >, <, >=, <=, !=
let year = 1985;
let _newer: Vec<AlbumView> = fetch!(ctx, {>year}).await?;
let _older: Vec<AlbumView> = fetch!(ctx, {<year}).await?;
let _gte: Vec<AlbumView> = fetch!(ctx, {>=year}).await?;
let _lte: Vec<AlbumView> = fetch!(ctx, {<=year}).await?;
let _not_eq: Vec<AlbumView> = fetch!(ctx, {!=year}).await?;
Combine conditions with AND/OR:
// Combine multiple conditions with AND/OR
let artist = "Prince";
let year = 1985;
let albums: Vec<AlbumView> = fetch!(ctx, {artist} AND {>year}).await?;
Mix unquoted variables with explicit comparisons:
// Mix unquoted variables with explicit comparisons
let artist = "Prince";
let year = 1985;
let albums: Vec<AlbumView> = fetch!(ctx, {artist} AND year > {year}).await?;
Quoted Form
Use quoted form for string literals and positional arguments:
// Quoted form with positional argument for string values
let artist = "Prince";
let albums: Vec<AlbumView> = fetch!(ctx, "artist = '{}'", artist).await?;
Multiple variables:
// Multiple variables with quoted form
let min_year = 1980;
let max_year = 1990;
let albums: Vec<AlbumView> = fetch!(ctx, "year >= {} AND year <= {}", min_year, max_year).await?;
Pure string literals (no variables):
// Quoted form for pure string literals
let albums: Vec<AlbumView> = fetch!(ctx, "artist = 'Prince' AND year > 1985").await?;
Common Patterns
Check if entity exists
// Check if any entities match the query
let album_name = "Purple Rain";
let matching_albums: Vec<AlbumView> = fetch!(ctx, "name = '{}'", album_name).await?;
let exists = matching_albums.len() > 0;
Get first match
let album = ctx.fetch::<AlbumView>("name = 'Purple Rain'").await?.into_iter().next();
Count matches
let count = ctx.fetch::<AlbumView>("year > 1985").await?.len();
Next Steps
- Querying Data - Overview of fetch vs query
- React Usage - Using queries in React components