5-minute quick start

Fauna has two main APIs: GraphQL and FQL (Fauna Query Language). This quick start provides a brief intro to both since you can use them together.

  1. Sign up for a free account

    When you first log in, you are greeted with a Welcome tutorial. Click anywhere (other than the tutorial panel) to close it. You can return to the tutorial at any time by clicking the question mark ? button at the top right.

    The Fauna Dashboard home screen with tutorial prompt

  2. Create a database

    1. Click NEW DATABASE.

      The Fauna Dashboard new database screen

    2. Enter my_db into the "Database Name" field.

    3. Check the "Pre-populate with demo data" checkbox.

    4. Click SAVE.

    You have created your first Fauna database!

  3. Browse your database

    The Overview page for the my_db database is displayed. The database has been populated with some collections, indexes, and the corresponding GraphQL schema for a grocery delivery app.

    The Fauna Dashboard database overview screen

    1. Collections

      Click COLLECTIONS in the left sidebar to browse your collections. You’ll see the documents for each collection on the right. If you are familiar with SQL, collections are like tables and documents are like rows in a table, except that each document can contain its own, distinct fields.

      The Fauna Dashboard collections screen

    2. Indexes

      Click the INDEXES tab in the left sidebar. If you are familiar with SQL, Fauna’s indexes are like SQL views. Most Fauna queries require a companion index to help avoid performing full scans of collections (which could get expensive), but you can have hundreds of indexes without affecting overall performance.

      The Fauna Dashboard indexes screen

    3. Functions

      Click the FUNCTIONS tab in the left sidebar. User-defined functions (UDFs) contain custom business logic that runs on the server, similar to "stored procedures".

      The Fauna Dashboard functions screen

      This UDF might look weird if it’s your first time seeing FQL, the Fauna Query Language, but FQL is actually pretty easy and tons of fun to learn. FQL is also unique in how much power and precision it gives you with respect to predictable cost and performance as you scale.

  4. Try some FQL

    Now that we know some basic concepts, let’s query our data.

    1. Click on SHELL in the left sidebar to open the web shell.

      The Fauna Dashboard shell screen

    2. Copy the following FQL query:

      Get(Ref(Collection("products"),"202"))
    3. Replace the queries in the bottom panel of the shell by selecting them and then and pasting the copied query.

    4. Click RUN QUERY.

      This query simply gets a document identified by its Reference. A document Reference contains a reference to the document’s collection (in this case, "products") and a unique ID for the document in that collection (in this case, "202"). Fauna’s auto-generated Reference IDs are 18-digits long — you can set your own during document creation, as we have done with the pre-populated demo data to ease copy/pasting.

      The upper panel contains the result of the query:

      The Fauna Dashboard shell screen with the query result

    5. Hover your pointer over the i icon to the left of "Time elapsed" to see the query execution metrics. For example, here we can learn that this query resulted in one read operation.

      The Fauna Dashboard shell screen with the query result and query statistics tooltip

      You can reduce read operations by leveraging indexes and using them as views. Expand the following block to learn more.

      Using indexes as views

      Indexes can be configured to provide any number of document fields. Using indexes, you can often avoid using the Get function to retrieve the values that you need, which reduces the number of read operations required.

      While Get is used to a retrieve a single document, Paginate is required when you want to retrieve details about multiple documents.

      Try the following:

      Paginate(Documents(Collection("products")))

      When an index does not have terms and values defined, it only returns ref:ref[]s.

      What if you want the whole document? The most flexible option is the combination of the Map and Get functions.

      The following query takes the array of References from the previous query, then uses the Map function to repeatedly apply an anonymous function for each Reference in the result. The anonymous function (or Lambda) assigns each Reference in the array to the variable product_ref, then uses the Get function to retrieve the referenced document.

      Map(
        Paginate(Documents(Collection("products"))),
        Lambda('product_ref', Get(Var('product_ref')))
      )

      Now, hover over the i icon to see that this costs 17 read operations. During development, you might use many Map/Get queries, so the number of read operations can climb quickly. At some point, you might want to leverage an index for cost-efficiency. Let’s leverage an index to do this.

      Create an index defining which fields from the document that you want to return:

      CreateIndex(
        {
          name: 'product_details',
          source: Collection('products'),
          values: [
            { field: ['data', 'name'] },
            { field: ['data', 'description'] },
            { field: ['data', 'price'] }
          ],
        },
      )

      Now, paginate using the index:

      Paginate(Match(Index("product_details")))

      If you hover over the i icon, you can see that using the Index and Match functions together costs only eight read operations!

      Combining Map with Get might be inexpensive during development, but you should leverage indexes as your usage scales.

  5. Try some GraphQL

    Click GraphQL in the left sidebar to access the GraphQL Playground.

    The Fauna Dashboard GraphQL

    Next, copy/paste the following query into the left panel of the editor, then click the "play" button in the middle.

    query {
      findProductByID(id: "202") {
        name
        description
        price
      }
    }

    This query fetches a single document based on its Reference ID, just like the FQL example in Step #4:

    {
      "data": {
        "findProductByID": {
          "name": "pinata",
          "description": "Original Classic Donkey Pinata",
          "price": 24.99
        }
      }
    }

    Each GraphQL query is translated into a single FQL query, which means that the GraphQL API has completely solved the n+1 problem behind the scenes for you.

    How Fauna solved n+1, or why FQL + GraphQL = Emoji: heart rocket

    While GraphQL famously solves the over-fetching and under-fetching of traditional REST APIs, it sometimes causes another serious problem: too many round trips to the server, AKA the notorious "​n+1 problem". Typically, there are two approaches to solve this:

    • The first is query batching/caching with a data loader, but such tools introduce complexity and don’t solve the entire problem. You still end up with more than one round trip to the server.

    • The second is to generate one query from each GraphQL query, but this sometimes results in a monster join that can choke traditional SQL databases. Instead of relying on joins, Fauna uses a strategy more akin to what graph databases call index-free adjacency. By nesting Map/Get queries, FQL maps perfectly on the execution plan of a GraphQL query, efficiently walking down the GraphQL tree and retrieving nested documents.

    In other words, any given query you send to the GraphQL API always incurs only one single request to the database, and does so efficiently. For a more in-depth explanation, with examples, see our blog post.

    Practice more GraphQL queries and their FQL equivalents

    Run these queries using the GRAPHQL screen.

    Run these queries using the SHELL screen.

    Create a product

    mutation {
      createProduct(data: {
        name: "Lemon",
        description: "Organic, per each",
        price: 0.35,
        quantity: 100,
        store: { connect: "301" },
        backorderLimit: 10,
        backordered: false,
      }) {
        _id
      }
    }
    Create(
      Collection("products"),
      {
        data: {
          "name": "Apple",
          "description": "Gala, per each",
          "price": 0.89,
          "quantity": 1000,
          "storeId": Ref(Collection("stores"), "301"),
          "backorderLimit": 10,
          "backordered": false,
        }
      }
    )

    Read all products

    query {
      allProducts {
        data {
          _id
          name
          description
          price
          quantity
          backorderLimit
          backordered
        }
      }
    }
    Map(
      Paginate(
        Documents(Collection("products"))
      ),
      Lambda("each_ref", Get(Var("each_ref")))
    )

    Update a store

    mutation {
      updateStore(
        id: "301",
        data: {
          name: "DC Fruits R Us"
        }
      ){
        _id
      }
    }
    Update(
      Ref(Collection("stores"), "301"),
      {
        data: {
          "name": "DC Fruits FTW"
        }
      }
    )

    Read a store

    query {
      findStoreByID(id: "301") {
        _id
        name
        address {
          street
          city
          state
          zipCode
        }
      }
    }
    Get(Ref(Collection("stores"), "301"))

    Delete a product

    mutation {
      deleteProduct(id: "203") {
        _id
      }
    }
    Delete(Ref(Collection("products"), "208"))

    Call a UDF to submit an order

    mutation {
      submitOrder(
        customerId: "101",
        products: [
          {
            productId: "201",
            quantity: 1
          }
        ]
      ){
        _id
      }
    }
    Call(
      Function("submit_order"),
      "101",
      [
        {
          productId: "204",
          quantity: 1
        },
        {
          productId: "205",
          quantity: 1
        }
      ]
    )

Was this article helpful?

We're sorry to hear that.
Tell us how we can improve!
Visit Fauna's Discourse forums or email docs@fauna.com

Thank you for your feedback!