Check out v4 of the Fauna CLI

v4 of the Fauna CLI is now GA.

The new version introduces enhancements to the developer experience, including an improved authentication workflow. To get started, check out the CLI v4 quick start.

Migrating from v3 of the CLI? See the CLI migration guide.

Connect Fauna to an app

This tutorial is the third and final part of a series that shows you how to quickly set up and run a Fauna database using the Fauna Dashboard. For an overview of the series, see Get started with the Fauna Dashboard.

In the previous tutorial, you created a collection and added documents to it using an FQL query. In this tutorial, you’ll create a basic app that connects to your database using a Fauna client driver. The drivers let you pass FQL queries to Fauna using an FQL template string.

Create an authentication secret

Fauna supports several types of authentication secrets. Create a key, which is one type of secret, with the built-in server-readonly role:

  1. In the Dashboard’s Explorer page, select your demo database.

  2. In the database’s Keys tab, click Create Key.

  3. Choose a Role of server (read-only).

  4. Click Save.

  5. Copy the Key Secret.

Create a key

Set the FAUNA_SECRET environment variable

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>

Set up a project

Create a directory for the app and install the Fauna client driver for your preferred programming language.

JavaScriptPythonGo.NET/C#Java

 

mkdir app
cd app
npm install fauna
mkdir app
cd app
pip install fauna
mkdir app
cd app
go mod init app
go get github.com/fauna/fauna-go/v3
mkdir app
cd app
dotnet new console
dotnet add package Fauna

Initialize a Gradle project:

mkdir example
cd example
gradle init \
  --type java-application \
  --dsl groovy \
  --test-framework junit \
  --project-name app \
  --package app \
  --java-version 17 \
  --no-incubating \
  --no-split-project

In the example directory, edit example/app/build.gradle and add the JVM driver as a dependency:

dependencies {
    ...
    implementation "com.fauna:fauna-jvm:1.0.0"
    ...
}

Create a basic app

In the app directory, create an app.mjs file and add the following code:

In the app directory, create an app.py file and add the following code:

In the app directory, create an app.go file and add the following code:

In the app directory, edit the Program.cs file and replace the code with the following:

In the example directory, edit the example/app/src/main/java/app/App.java file and replace the code with the following:

import { Client, fql, FaunaError } from "fauna";
// Use `require` for CommonJS:
// const { Client, fql, FaunaError } = require('fauna');

// Initialize the client to connect to Fauna
// using the `FAUNA_SECRET` environment variable.
const client = new Client();

try {
  // Compose a query using an FQL template string.
  // The query calls the `Review` collection's
  // `sortedByRating()` index. It projects
  // fields covered by the index.
  const query = fql`
    Review.sortedByRating() {
      title,
      rating,
      comment,
      customer {
        email
      },
      product {
        name
      }
    }`;

  // Run the query.
  const pages = await client.paginate(query);

  // Iterate through the results.
  const reviews = [];
  for await (const review of pages.flatten()) {
    reviews.push(review);
  }
  console.log(reviews);

} catch (error) {
  if (error instanceof FaunaError) {
    console.log(error);
  }
} finally {
  client.close();
}
from fauna import fql
from fauna.client import Client
from fauna.encoding import QuerySuccess
from fauna.errors import FaunaException

# Initialize the client to connect to Fauna
# using the `FAUNA_SECRET` environment variable.
client = Client()

try:
    # Compose a query using an FQL template string.
    # The query calls the `Review` collection's
    # `sortedByRating()` index. It projects
    #  fields covered by the index.
    query = fql(
        """
        Review.sortedByRating() {
          title,
          rating,
          comment,
          customer {
            email
          },
          product {
            name
          }
        }"""
    )

    # Run the query.
    pages = client.paginate(query)

    # Iterate through the results.
    for reviews in pages:
        for review in reviews:
            print(review)

except FaunaException as e:
    print(e)
finally:
    client.close()
package main

import (
	"encoding/json"
	"fmt"

	"github.com/fauna/fauna-go/v3"
)

func main() {
	// Initialize the client to connect to Fauna
	// using the `FAUNA_SECRET` environment variable.
	client, clientErr := fauna.NewDefaultClient()
	if clientErr != nil {
		panic(clientErr)
	}

	// Compose a query using an FQL template string.
	// The query calls the `Review` collection's
	// `sortedByRating()` index. It projects
	//  fields covered by the index.
	query, _ := fauna.FQL(`
		Review.sortedByRating() {
			title,
			rating,
			comment,
			customer {
				email
			},
			product {
				name
			}
		}
	`, nil)

	// Run the query.
	paginator := client.Paginate(query)

	// Iterate through the results.
	for {
		page, _ := paginator.Next()
		var pageItems []any
		page.Unmarshal(&pageItems)
		for _, item := range pageItems {
			jsonData, _ := json.Marshal(item)
			fmt.Println(string(jsonData))
		}
		if !paginator.HasNext() {
			break
		}
	}
}
using Fauna;
using Fauna.Exceptions;
using static Fauna.Query;

try
{
    // Initialize the client to connect to Fauna
    // using the `FAUNA_SECRET` environment variable.
    var client = new Client();

    // Compose a query using an FQL template string.
    // The query calls the `Review` collection's
    // `sortedByRating()` index. It projects
    //  fields covered by the index.
    var query = FQL($@"
      Review.sortedByRating() {{
        title,
        rating,
        comment,
        customer {{
          email
        }},
        product {{
          name
        }}
      }}
    ");

    // Run the query.
    var response = client.PaginateAsync<Dictionary<string, object?>>(query);

    await foreach (var page in response)
    {
        // Ensure page.Data is iterable
        foreach (var review in page.Data)
        {
            Console.WriteLine("Title: " + review["title"]);
            Console.WriteLine("Rating: " + review["rating"]);
            Console.WriteLine("Comment: " + review["comment"]);

            // Safely access nested dictionaries
            if (review["customer"] is Dictionary<string, object?> customer)
            {
                Console.WriteLine("Customer: " + customer["email"]);
            }

            if (review["product"] is Dictionary<string, object?> product)
            {
                Console.WriteLine("Product: " + product["name"]);
            }

            Console.WriteLine("--------");
        }
    }
}
catch (FaunaException e)
{
    Console.WriteLine(e);
}
package app;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import com.fauna.client.Fauna;
import com.fauna.client.FaunaClient;
import com.fauna.exception.FaunaException;
import com.fauna.query.builder.Query;
import com.fauna.response.QuerySuccess;
import com.fauna.types.Page;

import static com.fauna.codec.Generic.pageOf;
import static com.fauna.query.builder.Query.fql;

public class App {

    // Define class for `Review` documents
    // in expected results.
    public static class Review {
        public String title;
        public Integer rating;
        public String comment;
        public Customer customer;
        public Product product;
    }

    public static class Customer {
        public String email;
    }

    public static class Product {
        public String name;
    }

    public static void main(String[] args) {
        try {
            // Initialize the client to connect to Fauna
            // using the `FAUNA_SECRET` environment variable.
            FaunaClient client = Fauna.client();

            // Compose a query using an FQL template string.
            // The query calls the `Review` collection's
            // `sortedByRating()` index. It projects
            //  fields covered by the index.
            Query query = fql("""
                Review.sortedByRating() {
                  title,
                  rating,
                  comment,
                  customer {
                    email
                  },
                  product {
                    name
                  }
                }
            """);

            // Run the query.
            runSynchronousQuery(client, query);
        } catch (FaunaException e) {
            System.err.println("Fauna error occurred: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private static void runSynchronousQuery(FaunaClient client, Query query) throws FaunaException {
        // Use `query()` to run a synchronous query.
        // Synchronous queries block the current thread until the query completes.
        // Accepts the query, expected result class, and a nullable set of query options.
        QuerySuccess<Page<Review>> result = client.query(query, pageOf(Review.class));
        printResults(result.getData());
    }

    // Iterate through the reviews in the page.
    private static void printResults(Page<Review> page) {
        for (Review review : page.getData()) {
            System.out.println("Title: " + review.title);
            System.out.println("Rating: " + review.rating);
            System.out.println("Comment: " + review.comment);
            System.out.println("Customer: " + review.customer.email);
            System.out.println("Product: " + review.product.name);
            System.out.println("--------");
        }
        // Print the `after` cursor to paginate through results.
        System.out.println("After: " + page.getAfter());
    }
}

Run the app

Run the script from the app directory.

node app.mjs

The script prints a list of review data from your database in the terminal:

[
  {
    title: 'Great NYC-style pizza',
    rating: 4,
    comment: null,
    customer: { email: 'alice.appleseed@example.com' },
    product: { name: 'pizza' }
  },
  {
    title: 'Delicious limes!',
    rating: 5,
    comment: 'Incredibly ripe and juicy.',
    customer: { email: 'alice.appleseed@example.com' },
    product: { name: 'limes' }
  }
]

Run the script from the app directory.

python app.py

The script prints a list of review data from your database in the terminal:

{
  'title': 'Great NYC-style pizza',
  'rating': 4,
  'comment': None,
  'customer': {
    'email': 'alice.appleseed@example.com'
  },
  'product': {
    'name': 'pizza'
  }
}
{
  'title': 'Delicious limes!',
  'rating': 5,
  'comment': 'Incredibly ripe and juicy.',
  'customer': {
    'email': 'alice.appleseed@example.com'
  },
  'product': {
    'name': 'limes'
  }
}

Run the script from the app directory.

go run app.go

The script prints a list of review data from your database in the terminal:

{
  "comment": null,
  "customer": {
    "email": "alice.appleseed@example.com"
  },
  "product": {
    "name": "pizza"
  },
  "rating": 4,
  "title": "Great NYC-style pizza"
}
{
  "comment": "Incredibly ripe and juicy.",
  "customer": {
    "email": "alice.appleseed@example.com"
  },
  "product": {
    "name": "limes"
  },
  "rating": 5,
  "title": "Delicious limes!"
}

Run the script from the app directory. The script prints a list of review data from your database in the terminal.

dotnet run
Title: Great NYC-style pizza
Rating: 4
Comment:
Customer: alice.appleseed@example.com
Product: pizza
--------
Title: Delicious limes!
Rating: 5
Comment: Incredibly ripe and juicy.
Customer: alice.appleseed@example.com
Product: limes
--------

Run the script from the example directory.

./gradlew run

The script prints a list of review data from your database in the terminal:

Title: Great NYC-style pizza
Rating: 4
Comment: null
Customer: alice.appleseed@example.com
Product: pizza
--------
Title: Delicious limes!
Rating: 5
Comment: Incredibly ripe and juicy.
Customer: alice.appleseed@example.com
Product: limes
--------
After: Optional.empty

Next steps

Congratulations — You’ve completed the Dashboard tutorial series! 🏆

If you’re ready to dig deeper, check out the resources below.

 

A quick reference for FQL methods, grouped by functionality.

Learn how to use Fauna through a sample application.

Build solutions with Fauna following best practices.

Create a project for an app using the Fauna CLI and FSL.

Set up access control in Fauna using RBAC and ABAC.

Learn about common FQL query patterns, including basic CRUD operations.

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!