Query composition

The Fauna client drivers compose queries using FQL template strings. You can interpolate variables, including other FQL template strings, into the template strings to compose dynamic queries.

For example, using the JavaScript driver:

import { Client, fql, FaunaError } from "fauna";

const client = new Client({
    secret: 'FAUNA_SECRET'
});

// Create a native JS var.
const name = "avocados";

// Pass the var to an FQL query.
let query  = fql`Product.where(.name == ${name})`;
let response = await client.query( query );
console.log(response.data);
client.close();

To prevent injection attacks, the drivers encode interpolated variables to an appropriate FQL type before passing the query to Query HTTP API endpoint.

An e-commerce app has a product catalog that users search by various criteria, such as product category, price range, or other properties. A user may search by product type, minimum price, maximum price, or any combination of these criteria.

The following dynamic query handles various combinations of these search parameters:

import { Client, fql, FaunaError } from "fauna";

const client = new Client({
    secret: 'FAUNA_SECRET'
});

// Set up parameterized inclusive, exclusive,
// or exact matches.
const operators = {
  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.
const predicates = [
  { field: "type",  operator: "eq",  value: "food" },
  { field: "price", operator: "lte", value: 10000 },
  { field: "price", operator: "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( ${operators[val.operator] ( val.field, val.value)})`,
  base_query
)
let response = await client.query(dynamicQuery)
console.log(response.data)
client.close();

 

For simplicity, the example uses collection.where(), which requires a read of each document and isn’t performant on large datasets. For better performance, use indexes instead.

Driver examples

For additional query composition examples, see the driver documentation:

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!