Quick start

In this quick start guide, you’ll:

  • Create a Fauna database with demo data.

  • Run Fauna Query Language (FQL) queries to read and write data.

  • Build an application that integrates with Fauna using a client driver.

Prefer to learn using a sample application? Check out the Fauna JavaScript sample app on GitHub.

Before you start

Before starting this guide, you should be familiar with the concepts in the Overview.

Create a database

Set up a database with demo data.

  1. Log in to the Fauna Dashboard. You can sign up for a free account at https://dashboard.fauna.com/register.

  2. Create a database. When creating the database, enable demo data.

  3. Navigate to the database in the Dashboard.

Read data

You use FQL queries to read data in a Fauna database. You can run FQL queries in the Dashboard Shell.

Get all collection documents

Fauna stores data as JSON-like documents in collections.

You can filter and fetch documents from a collection as a set, and iterate through each document.

Run the following FQL query to get all documents in the demo data’s Customer collection. The query calls the all() method on the Customer collection:

// Calls `all()` on the `Customer` collection.
Customer.all()

The query returns a set of Customer collection documents. Each document has a 64-bit id that’s unique to the document within the collection.

{
  data: [
    {
      // Document ID, generated on write.
      id: "402336425554477133",
      coll: Customer,
      ts: Time("2099-07-02T21:46:05.720Z"),
      firstName: "Alice",
      lastName: "Appleseed",
      email: "alice.appleseed@example.com",
      address: {
        street: "87856 Mendota Court",
        city: "Washington",
        state: "DC",
        zipCode: "20220"
      },
      telephone: "208-346-0715",
      creditCard: {
        network: "Visa",
        number: "4556781272473393"
      }
    },
    ...
  ]
}

For one-off queries, use Collection.where() to filter documents using a predicate:

// 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. An index stores, or covers, specific document field values for quick retrieval.

You define indexes in an FSL collection schema. The demo data includes a schema for the Customer collection:

collection Customer {
  // Unique constraint.
  // Ensures a field value or combination of field values
  // is unique for each document in the collection.
  unique [.email]

  // Definition for the `byEmail()` index.
  // Use indexes to filter and sort documents
  // in a performant way.
  index byEmail {
    // `terms` are document fields for exact match searches.
    // In this example, you get `Customer` collection documents
    // by their unique `email` field value.
    terms [.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")
{
  data: [
    {
      id: "402336425554477133",
      coll: Customer,
      ts: Time("2099-07-02T21:46:05.720Z"),
      firstName: "Alice",
      lastName: "Appleseed",
      email: "alice.appleseed@example.com",
      address: {
        street: "87856 Mendota Court",
        city: "Washington",
        state: "DC",
        zipCode: "20220"
      },
      telephone: "208-346-0715",
      creditCard: {
        network: "Visa",
        number: "4556781272473393"
      }
    }
  ]
}

Sort data

You can use method chaining to call a method on the output of another method. Expressions are evaluated sequentially from left to right.

The following query calls order() on the output of all():

// 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.

The demo data includes a schema for the Product collection:

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()

For one-off queries, use Collection.where() to filter documents:

// 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:

// Get `Product` collection documents with a `price` between
// 10  and 100 (inclusive).
Product.sortedByPriceLowToHigh({ from: 10, to: 100 })

Project results

Projection lets you return only the specific fields you want from queries. Use projection to create smaller response payloads and decrease egress costs.

// Get only product names, descriptions, and prices
Product.sortedByPriceLowToHigh() {
  name,
  description,
  price
}
{
  data: [
    {
      name: "limes",
      description: "Conventional, 1 ct",
      price: 0.35
    },
    {
      name: "cilantro",
      description: "Organic, 1 bunch",
      price: 1.49
    },
    ...
  ]
}

Paginate results

Fauna automatically paginates sets with 16 or more elements. Use pageSize() to change the maximum number of elements per page:

// Calls `pageSize()` with a size of `2`.
Product.sortedByPriceLowToHigh().pageSize(2) {
  name,
  description,
  price
}

If a set is paginated and a subsequent page is available, the result includes an after cursor:

{
  // The results contain two elements or fewer.
  data: [
    {
      name: "limes",
      description: "Conventional, 1 ct",
      price: 0.35
    },
    {
      name: "cilantro",
      description: "Organic, 1 bunch",
      price: 1.49
    }
  ],
   // Use the `after` cursor to get the next page of results.
  after: "hdWCxmd..."
}

To get the next page of results, pass the after cursor to Set.paginate():

Set.paginate("hdWCxmd...")

The Fauna client drivers also include methods for automatically iterating through pages. See:

Write data

You also use FQL queries to write data to a Fauna database.

Create a document

Use create() to create, or insert, a document in a collection:

// Calls `create()` on the `Customer` collection.
// Creates a `Customer` collection document.
Customer.create({
  firstName: "John",
  lastName: "Doe",
  email: "jdoe@example.com"
})

If wanted, you can also provide a document id. If you don’t provide an ID, Fauna auto-generates one. Once assigned, the document ID is immutable and can’t be changed.

Customer.create({
  id: "12345",
  firstName: "Jacob",
  lastName: "Doe",
  email: "jacob.doe@example.com"
})

Update a document

Use update() to update a document:

// Declares a `customer` variable.
// Uses the `Customer` collection's `byEmail()` index to
// get `Customer` collection documents by `email` field value.
// In the `Customer` collection, `email` field values are unique
// so return the `first()` (and only) document.
let customer = Customer.byEmail("jdoe@example.com").first()

// Calls `update()` on the `Customer` collection document.
// `?.` safely calls `update()` only if `customer` contains
// a non-null value.
customer?.update({
  // Updates the existing `firstName` field value.
  firstName: "Jonathan",
  // Adds new `age` field.
  age: 42
})

To remove a field, set its value to null:

let customer = Customer.byEmail("jdoe@example.com").first()

customer?.update({
  // Removes the `age` field.
  age: null
})

Replace a document

Use replace() to replace a document:

let customer = Customer.byEmail("jdoe@example.com").first()

// Calls `replace()` on the `Customer` collection document.
customer?.replace({
  firstName: "Jane",
  lastName: "Doe",
  email: "jane.doe@example.com"
})

Delete a document

Use delete() to delete a document:

let customer = Customer.byEmail("jdoe@example.com").first()

// Calls `delete()` on the `Customer` collection document.
customer?.delete()

The query returns a NullDoc, which indicates the document no longer exists:

Customer("<DOCUMENT_ID>") /* deleted */

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.

Document relationships

A document relationship establishes associations between documents. Fauna supports one-to-one, one-to-many, and many-to-many relationships between documents in different collections.

Create a relationship between documents

To create a document relationship, include the document as a field value:

// Uses the `Store` collection's `byName()`
// index to get the first store named `DC Fruits`.
let store = Store.byName("DC Fruits").first()

// 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
})

Traverse document relationships

You can project a field that contains a document to dynamically traverse the document relationship:

// Get product names, descriptions, and prices
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"
        }
      }
    },
    ...
  ]
}

Create a key

Next, you’ll connect to Fauna using a client. To do this, you need a secret to authenticate with Fauna.

Fauna supports several secret types. For this quick start, create a key:

  1. In the upper left pane of Dashboard’s Explorer page, click the demo database, and click the Keys tab.

  2. Click Create Key.

  3. Choose a Role of Server.

  4. Click Save.

  5. Copy the Secret Key, which is the key’s secret. The secret is scoped to the database.

Build an application

Next, create a basic application that integrates with Fauna using a Fauna client driver.

A client driver sends FQL queries and receives responses using your preferred programming language. The client deserializes query responses into the language’s corresponding data types.

JavaScriptPythonGoC#

 

  1. Set the FAUNA_SECRET environment variable to your key’s secret. Fauna’s client drivers can access the secret from this variable.

    export FAUNA_SECRET=<KEY_SECRET>
  2. Create a directory for the app and install the driver.

    mkdir app
    cd app
    go mod init app
    go get github.com/fauna/fauna-go
    mkdir app
    cd app
    npm install fauna
    mkdir app
    cd app
    pip install fauna

    The C# client library is currently in beta.

    Navigate to your .NET or C# project directory and add the Fauna package to your project.

    mkdir app
    cd app
    dotnet new console
    dotnet add package Fauna --prerelease
  3. Create an app.go file and add the following code:

    Create an app.mjs file and add the following code:

    Create an app.py file and add the following code:

    Edit the Program.cs file and replace the code with the following:

    import { Client, fql } from "fauna";
    
    const client = new Client();
    
    // Build a query using the `fql` function
    const query = fql`
      Product.sortedByPriceLowToHigh().pageSize(2) {
        name,
        description,
        price
      }`;
    
    // Run the query
    const pages = client.paginate(query);
    const products = [];
    for await (const product of pages.flatten()) {
      products.push(product)
    }
    console.log(products)
    client.close();
    from fauna import fql
    from fauna.client import Client
    from fauna.errors import FaunaException
    
    client = Client()
    
    try:
      # Build a query using the `fql` function
      query = fql("""
        Product.sortedByPriceLowToHigh().pageSize(2) {
          name,
          description,
          price
      }""")
    
      # Run the query
      pages = client.paginate(query);
    
      products = []
      for product in pages.flatten():
          products.append(product)
      print(products)
    except FaunaException as e:
        print(e)
    finally:
        client.close();
    using Fauna;
    using Fauna.Exceptions;
    using static Fauna.Query;
    using System.Text.Json;
    
    try
    {
        var secret = Environment.GetEnvironmentVariable("FAUNA_SECRET");
        if (string.IsNullOrEmpty(secret))
        {
            Console.WriteLine("Fauna secret is not valid");
            return;
        }
    
        var cfg = new Configuration(secret);
        // Initialize the client to connect to Fauna
        var client = new Client(cfg);
    
        // Compose a query
        var query = FQL($@"Product.sortedByPriceLowToHigh().pageSize(2) {{
          name,
          description,
          price
        }}");
    
        // Run the query
        // PaginateAsync returns an IAsyncEnumerable of pages
        var response = client.PaginateAsync<Dictionary<string, object?>>(query);
    
        var allProducts = new List<Dictionary<string, object?>>();
    
        await foreach (var page in response)
        {
            allProducts.AddRange(page.Data);
        }
    
        // Serialize the list of products to JSON
        var jsonOptions = new JsonSerializerOptions { WriteIndented = true };
        string jsonString = JsonSerializer.Serialize(allProducts, jsonOptions);
    
        // Print the JSON array
        Console.WriteLine(jsonString);
    }
    catch (FaunaException e)
    {
        Console.WriteLine(e);
    }
    using Fauna;
    using Fauna.Exceptions;
    using static Fauna.Query;
    using System.Text.Json;
    
    try
    {
        var secret = Environment.GetEnvironmentVariable("FAUNA_SECRET");
        if (string.IsNullOrEmpty(secret))
        {
            Console.WriteLine("Fauna secret is not valid");
            return;
        }
    
        var cfg = new Configuration(secret);
        var client = new Client(cfg);
    
        // Build a query using the `FQL` function
        var query = FQL($@"Product.sortedByPriceLowToHigh().pageSize(2) {{
          name,
          description,
          price
        }}");
    
        // Run the query
        var response = client.PaginateAsync<Dictionary<string, object?>>(query);
    
        var allProducts = new List<Dictionary<string, object?>>();
    
        await foreach (var page in response)
        {
            allProducts.AddRange(page.Data);
        }
    
        var jsonOptions = new JsonSerializerOptions { WriteIndented = true };
        string jsonString = JsonSerializer.Serialize(allProducts, jsonOptions);
    
        Console.WriteLine(jsonString);
    }
    catch (FaunaException e)
    {
        Console.WriteLine(e);
    }

    The application prints product data from the demo database.

  4. Run the application:

    go run app.go
    node app.mjs
    python app.py
    dotnet run

    The application prints the following:

    [
      { name: 'limes',
        description: 'Conventional, 1 ct',
        price: 0.35
      },
      ...
      {
        name: 'pinata',
        description: 'Original Classic Donkey Pinata',
        price: 24.99
      }
    ]
    [
        {"name": "clear cups", "description": "Translucent 9 Oz, 100 ct", "price": 6.98},
        ...
        {"name": "pinata", "description": "Giant Taco Pinata", "price": 23.99},
    ]
    [
      { name: 'limes',
        description: 'Conventional, 1 ct',
        price: 0.35
      },
      ...
      {
        name: 'pinata',
        description: 'Original Classic Donkey Pinata',
        price: 24.99
      }
    ]
    [
      {
        "name": "limes",
        "description": "Conventional, 1 ct",
        "price": 0.35
      },
      ...
      {
        "name": "pinata",
        "description": "Original Classic Donkey Pinata",
        "price": 24.99
      }
    ]

Next steps

Congratulations! You’ve created a database, run some queries, and integrated Fauna with an application.

As a next step, try one of the following:

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!