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.

\