Check out v4 of the Fauna CLI
v4 of the Fauna CLI is now in beta. The new version introduces enhancements to the developer experience, including an improved authentication workflow. To get started, check out the CLI v4 quick start. |
CRUD and basic operations
This page contains examples of CRUD queries and other common database operations in Fauna Query Language (FQL) and Fauna Schema Language (FSL).
Collections
Create a collection
To create a collection, add an FSL collection schema to Fauna using a staged schema change.
// Defines the `Customer` collection.
collection Customer {
// Field definitions.
// Define the structure of the collection's documents.
name: String
email: String
address: {
street: String
city: String
state: String
postalCode: String
country: 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 {
name: String
email: String
address: {
street: String
city: String
state: String
postalCode: String
country: String
}
// Adds the `points` field. Accepts `int` or `null` values.
// Accepting `null` means the field is not required.
points: Int?
// Adds the `typeConflicts` field as a catch-all field for
// existing `points` values that aren't `Int` or `null`.
typeConflicts: { *: Any }?
*: Any
migrations {
// Adds the `typeConflicts` field.
add .typeConflicts
// Adds the `points` field.
add .points
// Nests non-conforming `points` 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 any of the following:
-
The Fauna CLI
-
The Fauna Dashboard
-
The Fauna Core HTTP API’s Schema endpoints
-
The FQL
collectionDef.delete()
method.
Deleting a collection deletes its documents and indexes.
Documents
Create a document
// Creates a `Customer` collection document.
Customer.create({
name: "John Doe",
email: "john.doe@example.com",
address: {
street: "123 Main St",
city: "San Francisco",
state: "CA",
postalCode: "12345",
country: "United States"
}
})
Reference:
collection.create() |
---|
Get a single document
// Gets a `Customer` collection document.
// Replace `111` with a document `id`.
Customer.byId("111")
Reference:
collection.byId() |
---|
Update a document
// Updates a `Customer` collection document.
Customer.byId("111")?.update({
// Updates the existing `name` field value.
name: "Jonathan Doe",
// Adds new `points` field.
points: 42
})
Reference:
document.update() |
---|
Upsert a document
// Try to find an existing customer.
// If the customer doesn't exist, returns `null`.
let customer = Customer.byId("111")
// Customer data to upsert
let data = {
name: "Alice Appleseed",
email: "alice.appleseed@example.com",
address: {
street: "87856 Mendota Court",
city: "Washington",
state: "DC",
postalCode: "20220",
country: "US"
}
}
// Create or update the customer
// based on existence.
if (customer == null) {
Customer.create(data)
} else {
customer!.update(data)
}
Remove a document field
// Updates a `Customer` collection document.
Customer.byId("111")?.update({
// Removes the `points` field.
points: null
})
Reference:
document.update() |
---|
Replace a document
// Replaces a `Customer` collection document.
Customer.byId("111")?.replace({
name: "Jane Doe",
email: "jane.doe@example.com",
address: {
street: "87856 Mendota Court",
city: "Washington",
state: "DC",
postalCode: "20220",
country: "US"
}
})
Reference:
document.replace() |
---|
Delete a document
// Deletes a `Customer` collection document.
Customer.byId("111")?.delete()
Reference:
document.delete() |
---|
Bulk writes
Use set.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: {
street: doc?.address?.street,
city: doc?.address?.city,
state: "District of Columbia",
postalCode: doc?.address?.postalCode,
country: doc?.address?.country,
}
})) // `forEach()` returns `null`.
For more examples, see Bulk writes.
Reference: set.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 `name` and `email` field values.
values [.name, .email]
}
}
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 [.name, .email]
}
}
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), then ...
// - `stock` (ascending).
Product.all().order(.price, .name, .description, .stock)
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, .stock]
}
}
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), then ...
// - `stock` (ascending).
Product.sortedByPriceLowToHigh()
See Sort collection documents |
---|
Range search
// Runs an unindexed query.
// Get `Product` collection documents with a `price` between
// 10_00 and 100_00 (inclusive).
Product.where(.price >= 10_00 && .price <= 100_00)
.order(.price, .name, .description, .stock)
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, .stock]
}
}
Call the index in a query:
// Get `Product` collection documents with a `price` between
// 10_00 and 100_00 (inclusive).
Product.sortedByPriceLowToHigh({ from: 10_00, to: 100_00 })
See Run a range search |
---|
Projection
// Projects the `name`, `description`, and `price` fields.
Product.sortedByPriceLowToHigh() {
name,
description,
price
}
{
data: [
{
name: "single lime",
description: "Conventional, 1 ct",
price: 35
},
{
name: "cilantro",
description: "Organic, 1 bunch",
price: 149
},
...
]
}
Reference: Projection and field aliasing |
---|
Paginate results
Fauna automatically paginates result Sets with 16 or more elements.
When a query returns paginated results, Fauna materializes a subset of the
Set with an after
pagination cursor:
// Uses the `Product` collection's `sortedByPriceLowToHigh()` index to
// return all `Product` collection documents.
// The collection contains more than 16 documents.
Product.sortedByPriceLowToHigh()
{
// The result Set contains 16 elements.
data: [
{
id: "555",
coll: Product,
ts: Time("2099-07-30T15:57:03.730Z"),
name: "single lime",
description: "Conventional, 1 ct",
price: 35,
stock: 1000,
category: Category("789")
},
{
id: "888",
coll: Product,
ts: Time("2099-07-30T15:57:03.730Z"),
name: "cilantro",
description: "Organic, 1 bunch",
price: 149,
stock: 100,
category: Category("789")
}
],
// Use the `after` cursor to get the next page of results.
after: "hdW..."
}
To get the next page of results, pass the after
cursor to
Set.paginate()
:
Set.paginate("hdW...")
The Fauna client drivers also include methods for automatically iterating through pages. See:
Document relationships
Create a document relationship
To create a document relationship, include the document as a field value:
// Gets a `Category` collection document.
let produce = Category.byName("produce").first()
// Creates a `Product` collection document.
Product.create({
name: "lemons",
description: "Organic, 16 ct",
price: 2_49,
stock: 200,
// Adds the previous `Category` collection document as
// a `category` field value.
category: produce
})
See Create a document relationship |
---|
Traverse document relationships
You can project a field that contains a document to dynamically traverse the document relationship:
let produce = Category.byName("produce").first()
// Projects the `name`, `description`, `price`,
// and `category` fields.
Product.byCategory(produce) {
name,
description,
price,
category
}
{
data: [
{
name: "avocados",
description: "Conventional Hass, 4ct bag",
price: 399,
// Traverses the `Category` collection document in
// the `category` field.
category: {
id: "789",
coll: Category,
ts: Time("2099-07-29T21:18:48.680Z"),
products: "hdW...",
name: "produce",
description: "Fresh Produce"
}
},
{
name: "single lime",
description: "Conventional, 1 ct",
price: 35,
category: {
id: "789",
coll: Category,
ts: Time("2099-07-29T21:18:48.680Z"),
products: "hdW...",
name: "produce",
description: "Fresh Produce"
}
},
...
]
}
See Traverse document relationships with projection |
---|
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:
database.update() |
---|
Delete a child database
// Deletes the `childDB` child database.
Database.byName("childDB")?.delete()
Reference:
database.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!