Dynamic queries and query composition
The FQL API natively supports composition by using query interpolation. This eliminates injection attack vulnerability, which is a common database security exploit, and makes the query a powerful composition primitive to use in building applications and libraries.
Driver design is based on string-based query templates, using string interpolation to parameterize the templates. When you define a query template, you add placeholders in the template for query arguments. When the query executes, the template with query variables is sent over the wire, parsed, and the variables evaluated to ensure that injection can’t occur.
Composition in drivers
Fauna drivers expose an ergonomic API for composition and use query interpolation in their implementations.
Template and variable syntax can vary by language, although Fauna tries to
make them look and feel similar. For example, the JavaScript, Python, and Go
drivers use a common template format for declaring FQL queries, using ${}
as variable placeholders, but they have syntactic differences in how
to pass variables. Review your driver
README file for guidance.
Choose a language to see an example of string substitution with composition for that language:
Here are some things to consider when thinking about composition:
-
You can and should use the composition API by default, even when writing simple string queries. This ensures that your code is safe and extensible. Most drivers make this easy by accepting only template-constructed queries.
-
You can compose queries with primitives, objects, and other queries. Support for serialization and deserialization of user-defined types depends on the driver, so see the README for your driver for the most up-to-date advice.
-
When writing subqueries to be reused using composition, that subquery isn’t required to be syntactically complete. Only the final query in which it is used needs to be complete. This means you can write snippets that can be composed, although they can’t be run by themselves.
Composition with one or more queries example
These are more advanced examples for each driver, showing multiple queries:
A simple example
Take an example e-commerce application where you want to search a product catalog by product type and where the type of product varies with each query. This code snippet shows you how to parameterize the query.
const type = "book"
let query = fql`Product.where(.type == ${type})`
let result = await client.query(query)
console.log(result)
Notice that the product type is parameterized using ${type}
placeholder syntax.
Add flexibility to your query
The following code snippet expands that example to cover the case where you want to also search for products by type, minimum price, and maximum price:
fql`Product
.where(.type == "book")
.where(.price <= 10000)
.where(.price >= 10)
`
The equivalent templating syntax gives you the flexibility of searching on any combination of parameters:
// Set up parameterized inclusive, exclusive,
// or exact matches
const comparators = {
eq: (field, value) => fql`x => x[${field}] == ${value}`,
gt: (field, value) => fql`x => x[${field}] > ${value}`,
gte: (field, value) => fql`x => x[${field}] >= ${value}`,
lt: (field, value) => fql`x => x[${field}] < ${value}`,
lte: (field, value) => fql`x => x[${field}] <= ${value}`,
}
// Define the product search parameters set in the UI
var predicates = [
{ field: "type", comparator: "eq", value: "book" },
{ field: "price", comparator: "lte", value: 10000 },
{ field: "price", comparator: "gte", value: 10 },
];
const base_query = fql`Product`
// chain successive where() methods to the query,
// effectively ANDing the predicates
const dynamicQuery = predicates.reduce(
(acc, val) =>
fql`${acc}.where( ${comparators[val.comparator] ( val.field, val.value)})`,
base_query
)
let result = await client.query(dynamicQuery)
console.log(result)
Sometimes you might want to search on all three parameters, and at other times only search on one parameter.
Is this article helpful?
Tell Fauna how the article can be improved:
Visit Fauna's forums
or email docs@fauna.com
Thank you for your feedback!