Fauna cheat sheet
This cheat sheet contains examples of common database operations in Fauna Query Language (FQL) and Fauna Schema Language (FSL). For additional context, check out the Overview and Quick start.
Collections
Create a collection
To create a collection, add an FSL collection schema in the Fauna Dashboard or upload the schema using the Fauna CLI:
// Defines the `Customer` collection.
collection Customer {
// Field definitions.
// Define the structure of the collection's documents.
email: String
firstName: String?
lastName: String?
status: String?
address: {
street: String?,
city: String?,
state: String?,
zipCode: String?,
}?
telephone: String?
creditCard: {
network: "Visa" | "MasterCard" | "American Express"?,
number: String?,
}?
// Wildcard constraint.
// Allows arbitrary ad hoc fields of any type.
*: Any
// If a collection schema has no field definitions
// and no wildcard constraint, it has an implicit
// wildcard constraint of `*: Any`.
}
See Schema |
---|
Edit a collection
Update a collection’s document type using a zero-downtime schema migration:
collection Customer {
email: String
firstName: String?
lastName: String?
status: String?
address: {
street: String?,
city: String?,
state: String?,
zipCode: String?,
}?
telephone: String?
creditCard: {
network: "Visa" | "MasterCard" | "American Express"?,
number: String?,
}?
// Adds the `age` field. Accepts `int` or `null` values.
// Accepting `null` means the field is not required.
age: Int?
// Adds the `typeConflicts` field as a catch-all field for
// existing `age` values that aren't `Int` or `null`.
typeConflicts: { *: Any }?
*: Any
migrations {
// Adds the `typeConflicts` field.
add .typeConflicts
// Adds the `age` field.
add .age
// Nests non-conforming `age` and `typeConflicts`
// field values in the `typeConflicts` catch-all field.
move_conflicts .typeConflicts
}
}
See Schema migrations |
---|
Delete a collection
To delete a collection, delete its schema using the Fauna Dashboard or Fauna CLI. Deleting a collection deletes its documents and indexes.
Documents
Create a document
// Creates a `Customer` collection document.
Customer.create({
firstName: "John",
lastName: "Doe",
email: "jdoe@example.com"
})
Reference:
create() |
---|
Get a single document
// Gets a `Customer` collection document.
// Replace `<DOCUMENT_ID>` with a document `id`.
Customer.byId("<DOCUMENT_ID>")
Reference:
byId() |
---|
Update a document
// Updates a `Customer` collection document.
Customer.byId("<DOCUMENT_ID>")?.update({
// Updates the existing `firstName` field value.
firstName: "Jonathan",
// Adds new `age` field.
age: 42
})
Reference:
update() |
---|
Remove a document field
// Updates a `Customer` collection document.
Customer.byId("<DOCUMENT_ID>")?.update({
// Removes the `age` field.
age: null
})
Reference:
update() |
---|
Replace a document
// Replaces a `Customer` collection document.
Customer.byId("<DOCUMENT_ID>")?.replace({
firstName: "Jane",
lastName: "Doe",
email: "jane.doe@example.com"
})
Reference:
replace() |
---|
Delete a document
// Deletes a `Customer` collection document.
Customer.byId("<DOCUMENT_ID>")?.delete()
Reference:
delete() |
---|
Bulk writes
Use forEach()
to iteratively update each document in a set:
// Get a set of `Customer` collection documents with an
// `address` in the `state` of `DC`.
let customers = Customer.where(.address?.state == "DC")
// Use `forEach()` to update each document in the previous set.
customers.forEach(doc => doc.update({
address: {
state: "District of Columbia"
}
})) // `forEach()` returns `null`.
For more examples, see Bulk writes.
Reference: forEach() |
---|
Indexes and reads
Create an index
You define indexes in FSL as part of a collection schema:
collection Customer {
...
index byEmail {
// `terms` are document fields for exact match searches.
// In this example, you get `Customer` collection documents
// by their `email` field value.
terms [.email]
// `values` are document fields for sorting and range searches.
// In this example, you sort or filter index results by their
// descending `firstName` and `lastName` field values.
values [.firstName, .lastName]
}
}
See Define an index |
---|
Exact match search
// Runs an unindexed query.
Customer.where(.email == "alice.appleseed@example.com")
For better performance on large datasets, use an index with a term to run an exact match search.
Define the index in the collection schema:
collection Customer {
...
// Defines the `byEmail()` index for the `Customer`
// collection.
index byEmail {
// Includes the `email` field as an index term.
terms [.email]
values [.firstName, .lastName]
}
}
You call an index as a method on its collection:
// Uses the `Customer` collection's `byEmail()` index
// to run an exact match search on an `email` field value.
Customer.byEmail("alice.appleseed@example.com")
See Run an exact match search |
---|
Sort collection documents
// Runs an unindexed query.
// Sorts `Product` collection documents by:
// - `price` (ascending), then ...
// - `name` (ascending), then ...
// - `description` (ascending).
Product.all().order(.price, .name, .description)
For better performance on large datasets, use an index with values to sort collection documents.
Define the index in the collection schema:
collection Product {
...
// Defines the `sortedByPriceLowToHigh()` index.
index sortedByPriceLowToHigh {
// `values` are document fields for sorting and range searches.
values [.price, .name, .description]
}
}
Call the index in a query:
// Uses the `Product` collection's `sortedByPriceLowToHigh()` index
// to sort `Product` collection documents by:
// - `price` (ascending), then ...
// - `name` (ascending), then ...
// - `description` (ascending).
Product.sortedByPriceLowToHigh()
See Sort collection documents |
---|
Range search
// Runs an unindexed query.
// Get `Product` collection documents with a `price` between
// 10 and 100 (inclusive).
Product.where(.price >= 10 && .price <= 100)
.order(.price, .name, .description)
For better performance on large datasets, use an index with values to run range searches on collection documents,
Define the index in the collection schema:
collection Product {
...
// Defines the `sortedByPriceLowToHigh()` index.
index sortedByPriceLowToHigh {
// `values` are document fields for sorting and range searches.
values [.price, .name, .description]
}
}
Call the index in a query:
// Get `Product` collection documents with a `price` between
// 10 and 100 (inclusive).
Product.sortedByPriceLowToHigh({ from: 10, to: 100 })
See Run a range search |
---|
Projection
// Projects the `name`, `description`, and `price` fields.
Product.sortedByPriceLowToHigh() {
name,
description,
price
}
{
data: [
{
name: "limes",
description: "Conventional, 1 ct",
price: 0.35
},
{
name: "cilantro",
description: "Organic, 1 bunch",
price: 1.49
},
...
]
}
Reference: Projection and field aliasing |
---|
Document relationships
Create a document relationship
To create a document relationship, include the document as a field value:
// Gets a `Store` collection document.
let store = Store.byId("<DOCUMENT_ID>")
// Creates a `Product` collection document.
Product.create({
name: "limes",
description: "Organic, 2 ct",
price: 1.98,
quantity: 70,
// Adds the previous `Store` collection document as
// a `store` field value.
store: store,
backorderLimit: 5,
backordered: false
})
See Create a document relationship |
---|
Traverse document relationships
You can project a field that contains a document to dynamically traverse the document relationship:
// Projects the `name`, `description`, `price`, and `store` fields.
Product.sortedByPriceLowToHigh() {
name,
description,
price,
store
}
{
data: [
{
name: "limes",
description: "Conventional, 1 ct",
price: 0.35,
// Traverses the `Store` collection document in
// the `store` field.
store: {
id: "402336425534554189",
coll: Store,
ts: Time("2099-07-02T21:46:05.720Z"),
name: "DC Fruits",
address: {
street: "13 Pierstorff Drive",
city: "Washington",
state: "DC",
zipCode: "20220"
}
}
},
{
name: "cilantro",
description: "Organic, 1 bunch",
price: 1.49,
store: {
id: "402336425534554189",
coll: Store,
ts: Time("2099-07-02T21:46:05.720Z"),
name: "DC Fruits",
address: {
street: "13 Pierstorff Drive",
city: "Washington",
state: "DC",
zipCode: "20220"
}
}
},
...
]
}
See Traverse document relationships with projection |
---|
Event Streaming
Track changes to a collection
// Track changes to `Product` collection documents.
Product.all().toStream()
Reference: Collection streams |
---|
Track changes to an index
// Track changes to the set of documents
// returned by the `byCategory()` index call.
Product.byCategory('sports').toStream()
Reference: Index streams |
---|
Track changes to a single document
// Track changes on a single `Product` collection document.
let product = Product.byId("<DOCUMENT_ID>")!
Set.single(product).toStream()
Reference: Document streams |
---|
Track changes on specific fields
// Only track changes to the `category` and `name` fields
// of the set of documents returned by the `byCategory()`
// index call.
Product.byCategory('sports').changesOn(.category, .name)
Reference: Event Streaming reference |
---|
Child databases
Create a child database
// Creates the `childDB` child database.
Database.create({
name: "childDB",
// Enables typechecking for the database.
typechecked: true
})
Reference:
Database.create() |
---|
Get a child database
// Gets the `childDB` child database.
Database.byName("childDB")
Reference:
Database.byName() |
---|
Update a child database
// Updates the `childDB` child database's
// `typechecked` field.
Database.byName("childDB")?.update({typechecked: false})
Reference:
update() |
---|
Delete a child database
// Deletes the `childDB` child database.
Database.byName("childDB")?.delete()
Reference:
delete() |
---|
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!