01 Tutorials

Languages:

Introduction

This tutorial connects your code to FaunaDB in the language of your choice, and gives an overview of driver usage. Once you have your workbench running, you’ll be ready for the basics tutorial. If you don’t see the language you’d like, send us a message via the chat tool in the bottom right of the page. We may already be working on a driver.

You can also find the drivers on GitHub: Ruby, Java, Scala, Android, JavaScript, C#, Python, Go, and Swift

TL;DR

Skip to the Getting Started section if you want detailed step-by-step information. Otherwise you may be able to copy and paste what you need from this TLDR.

Here is an example HTTP request. Note the : appended to the secret.


curl https://db.fauna.com/ \
    -u YOUR_FAUNADB_SECRET: \
    -d '{ "concat": ["Hello", "World"] }'

JavaScript

Install the driver from NPM and add it to your package.json.


npm install --save faunadb

Create a client and issue a query.


var faunadb = require('faunadb'),
  q = faunadb.query;

var client = new faunadb.Client({ secret: 'YOUR_FAUNADB_SECRET' });

client.query(q.Concat(["Hello", "World"], " ")).then(function(response) {
  console.log(response);
})

Go

Get the driver.


go get github.com/fauna/faunadb-go/faunadb

Create a client and issue a query.


package main

import (
        "fmt"

        f "github.com/fauna/faunadb-go/faunadb"
)

func main() {
        client := f.NewFaunaClient("YOUR_FAUNADB_SECRET")

        res, err := client.Query(f.Concat(f.Arr{"Hello", "World"}, " "))
        if err != nil {
                panic(err)
        }

        fmt.Println(res)
}

Ruby

Install the driver with Ruby Gems.


gem install fauna

Create a client and issue a query.


$fauna = Fauna::Client.new(secret: "YOUR_FAUNADB_SECRET")

$fauna.query { concat(["Hello", "World"], " ") }

C#

Here is an example on how to execute a simple query on FaunaDB:


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FaunaDB.Client;
using FaunaDB.Types;

using static FaunaDB.Query.Language;

namespace FaunaDBProject
{
    class FaunaDBHelloWorld
    {
        static readonly string DOMAIN = "db.fauna.com";
        static readonly string SCHEME = "https";
        static readonly int PORT = 443;
        static readonly string SECRET = "<<YOUR-SECRET-HERE>>";

        static void ProcessData(IReadOnlyList<Value> values)
        {
            foreach (Value value in values)
            {
                //do something
            }
        }
        static async Task DoQuery(FaunaClient client)
        {
            Value result = await client.Query(Paginate(Match(Ref("indexes/spells"))));
            IResult<IReadOnlyList<Value>> data = result.At("data").To(Codec.ARRAY);

            data.Match(
                Success: value => ProcessData(value),
                Failure: reason => Console.WriteLine($"Something went wrong: {reason}")
            );
        }

        public static void Main(string[] args)
        {
            var client = new FaunaClient(domain: DOMAIN, scheme: SCHEME, port: PORT, secret: SECRET);

            DoQuery(client).Wait();
        }
    }
}

This small example shows how to use pretty much every aspect of the library.

Swift

Create a client and issue a query.


import FaunaDB

let client = FaunaDB.Client(secret: "your-key-secret-here")

try! client.query(
  Concat("Hello ", "World")
).await(timeout: .now() + 5)

Java

Download from the Maven central repository:

faunadb-java/pom.xml:

 <dependencies>
  ...
  <dependency>
    <groupId>com.faunadb</groupId>
    <artifactId>faunadb-java</artifactId>
    <version>1.0.0</version>
    <scope>compile</scope>
  </dependency>
  ...
</dependencies>

Create a client and issue a query.


import com.faunadb.client.*;
import com.faunadb.client.types.*;
import com.faunadb.client.types.Value.*;
import com.google.common.collect.*;

import static com.faunadb.client.query.Language.*;

public class Main {
  public static void main(String[] args) throws Exception {
    FaunaClient client = FaunaClient.builder()
      .withSecret("your-secret-here")
      .build();

    ImmutableList<RefV> indexes = client.query(Paginate(Ref("indexes"))).get()
      .at("data").collect(Field.as(Codec.REF));

    System.out.println(indexes);

    client.close();
  }
}

Scala

faunadb-scala/sbt

Declare the dependency:


libraryDependencies += ("com.faunadb" %% "faunadb-scala" % "1.0.0")

Create a client and issue a query.


import faunadb.FaunaClient
import faunadb.query._
import faunadb.values._
import scala.concurrent._
import scala.concurrent.duration._

object Main extends App {
  import ExecutionContext.Implicits._

  val client = FaunaClient(secret = "your-secret-here")

  val indexes = client
    .query(Paginate(Ref("indexes")))
    .map(value => value("data").to[Seq[RefV]].get)

  println(
    Await.result(indexes, Duration.Inf)
  )

  client.close()
}

Python

Install the driver from pip.


pip install faunadb

Create a client and issue a query.


from faunadb import query as q
from faunadb.objects import Ref
from faunadb.client import FaunaClient

client = FaunaClient(secret="your-secret-here")

indexes = client.query(q.paginate(Ref("indexes")))

print(indexes)

Getting Started

Before issuing queries, let’s set up our environment and install the driver.

Supported Runtimes

Before you install the driver, it’s important to ensure you’re running a compatible version of the language runtime and have satisfied other dependencies.

FaunaDB’s wire protocol is HTTP, so you can use tools like curl to inspect the API. However, we recommend using an official driver whenever possible.

The JavaScript driver supports and is tested on:

  • Node.js
  • LTS (v4)
  • Stable (v6)
  • v0.12.x
  • Chrome
  • Firefox
  • Safari
  • Internet Explorer 11

Currently, the driver is tested on Go versions:

  • 1.5
  • 1.6
  • 1.7
  • 1.8

Tested and compatible with the following ruby versions:

  • MRI 1.9.3
  • MRI 2.2.3
  • Jruby 1.7.19

Developed for .NET 4.5

  • iOS 9.0+ | OSX 10.10+ | tvOS 9.0+ | watchOS 2.0+
  • Xcode 8
  • Swift 3

Shared

Android

Java

  • Java 7
  • Google Guava, for collections and ListenableFutures.

Shared

Scala

  • Scala 2.11.x

The following versions of Python are supported:

  • Python 2.7
  • Python 3.3
  • Python 3.4
  • Python 3.5
  • Python 3.6

Installation

Consult your operating system package manager if the curl command is not available on your machine, or use a different HTTP client.

Node.js

To install the JavaScript driver, run this in the terminal:


npm install --save faunadb

See faunadb on NPM for more information.

Browsers

The browser release can be found in the fauna/faunadb-js-release repository.

This release can be installed via bower:


bower install faunadb

Or via CDN:


<script src="//cdn.jsdelivr.net/faunadb/1.1/faunadb.js"></script>

The minified version of the driver can also be used via CDN:


<script src="//cdn.jsdelivr.net/faunadb/1.1/faunadb-min.js"></script>

To install the Go driver, run this in the terminal:


go get github.com/fauna/faunadb-go

The FaunaDB ruby driver is distributed as a gem. Install it via:


gem install fauna

Or if you use Bundler, add it to your application’s Gemfile:


gem 'fauna'

And then execute:


bundle

First install the Nuget package by editing your packages.config


<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="FaunaDB.Client" version="1.0.0" targetFramework="net45" />
</packages>

And then update your dependencies with nuget restore faunadb-csharp.sln

CocoaPods:


pod 'FaunaDB', '~> 1.0.0'

Carthage:


github 'fauna/faunadb-swift'

SwiftPM:


.Package(url: "https://github.com/fauna/faunadb-swift.git", Version(1, 0, 0))

Download from the Maven central repository:

faunadb-java/pom.xml:

 <dependencies>
  ...
  <dependency>
    <groupId>com.faunadb</groupId>
    <artifactId>faunadb-java</artifactId>
    <version>1.0.0</version>
    <scope>compile</scope>
  </dependency>
  ...
</dependencies>

faunadb-android/pom.xml:

 <dependencies>
  ...
  <dependency>
    <groupId>com.faunadb</groupId>
    <artifactId>faunadb-android</artifactId>
    <version>1.0.0</version>
    <scope>compile</scope>
  </dependency>
  ...
</dependencies>

faunadb-scala/sbt

libraryDependencies += ("com.faunadb" %% "faunadb-scala" % "1.0.0")


pip install faunadb

Hello World

It’s time to create some code. First we import the driver, then we issue a query.

Import the Driver

The curl command should be in you shell path.


var faunadb = require("faunadb"),
  q = faunadb.query;

This is the recommended require stanza. The faunadb.query module contains all of the functions to create FaunaDB Query expressions.

Similarly with es6 modules:


import faunadb, { query as q } from "faunadb"

The CDN package exposes a global faunadb variable.

We recommend that you import this driver with an alias import such as:


import f "github.com/fauna/faunadb-go/faunadb"

First, require the gem:


require 'fauna'

Import the client and the query language helpers.


using FaunaDB.Client;
using FaunaDB.Types;

using static FaunaDB.Query.Language;


import FaunaDB


import com.faunadb.client.*;
import com.faunadb.client.types.*;
import com.faunadb.client.types.Value.*;


import faunadb.FaunaClient
import faunadb.query._
import faunadb.values._


from faunadb import query as q
from faunadb.objects import Ref
from faunadb.client import FaunaClient

Instantiate the Client

You can obtain a FaunaDB secret via your account page. Typically you’ll want to use your root keys to create per-database server access keys. And then have your code access the data with the server key secret. Learn more about keys and access control here, or continue through the tutorials for examples.

HTTP is stateless, so the only initialization is providing your FaunaDB key secret as part of the basic authentication headers. In curl you do that with the -u flag.


var client = new faunadb.Client({ secret: 'YOUR_FAUNADB_SECRET' });


client := f.NewFaunaClient("YOUR_FAUNADB_SECRET")

All API requests pass through a Fauna::Client. Creating a client requires either an admin key, server key, client key, or a token.


server_key = 'ls8AkXLdakAAAALPAJFy3LvQAAGwDRAS_Prjy6O8VQBfQAlZzwAA'

Now we can make a database-level client:


$fauna = Fauna::Client.new(secret: server_key)

You can optionally configure an observer on the client. To ease debugging, we provide a simple logging observer at Fauna::ClientLogger.logger, which you can configure as such:


require 'logger'
logger = Logger.new(STDERR)
observer = Fauna::ClientLogger.logger { |log| logger.debug(log) }

$fauna = Fauna::Client.new(
  secret: server_key,
  observer: observer)


var client = new FaunaClient(domain: DOMAIN, scheme: SCHEME, port: PORT, secret: SECRET);

Except secret all other arguments are optional.


let client = FaunaDB.Client(secret: "YOUR_FAUNADB_SECRET")


FaunaClient client = FaunaClient.builder()
      .withSecret("YOUR_FAUNADB_SECRET")
      .build();


val client = FaunaClient(secret = "YOUR_FAUNADB_SECRET")


client = FaunaClient(secret="YOUR_FAUNADB_SECRET")

Basic Usage

You’ll get to do even more exciting things in the next tutorial. This query is enough to prove you are connected to the server, with a working client.

Here is an example HTTP request. Note the : appended to the secret.


curl https://db.fauna.com/ \
    -u YOUR_FAUNADB_SECRET: \
    -d '{ "create_database": { "object": { "name": "my_app" } } }'

Once the client has been instantiated, it can be used to issue queries. For example, to create an instance in an existing class named test with the data: { testField: 'testValue' }:


var createP = client.query(q.Create(q.Class('test'), { testField: 'testValue' }));

All methods on faunadb.Client return ES6 Promises. So, if we wanted to handle the Promise to access the Ref of the newly created instance:


createP.then(function(response) {
  console.log(response.ref); // Would log the ref to console.
});

response is a JSON object containing the FaunaDB response. See the JSDocs for faunadb.Client, and the FaunaDB Developer Guide for more information on responses.

Pagination Helpers

This driver contains helpers to provide a simpler API for consuming paged responses from FaunaDB. See the FaunaDB Developer Guide and the Paginate Function Reference for a description of paged responses.

Using the helper to page over sets lets the driver handle cursoring and pagination state. For example, client.paginate:


var helper = client.paginate(q.Match(q.Index('test_index'), 'example-term'));

The return value, helper, is an instance of PageHelper. The each method will execute a callback function on each consumed page.


helper.each(function(page) {
  console.log(page); // Will log the page's contents, for example: [ Ref("classes/test/1234"), ... ]
});

Note that each returns a Promise<void> that is fulfilled on the completion of pagination.

The pagination can be transformed server-side via the FaunaDB query language via the map and filter functions.

For example, to retrieve the matched instances:


helper.map(function(ref) { return q.Get(ref); }).each(function(page) {
  console.log(page); // Will now log the retrieved instances.
});

See the JSDocs for more information on the pagination helper.


package main

import (
        "fmt"

        f "github.com/fauna/faunadb-go/faunadb"
)

type User struct {
        Name string `fauna:"name"`
}

func main() {
        client := f.NewFaunaClient("YOUR_FAUNADB_SECRET")

        res, err := client.Query(f.Get(f.Ref("classes/users/42")))
        if err != nil {
                panic(err)
        }

        var user User

        if err := res.Get(&user); err != nil {
                panic(err)
        }

        fmt.Println(user)
}

Now that we have a client, we can start performing queries:


# Create a class
$fauna.query { create ref('classes'), name: 'users' }

# Create an instance of the class
taran = $fauna.query do
  create ref('classes/users'), data: { email: 'taran@example.com' }
end

# Update the instance
taran = $fauna.query do
  update taran[:ref], data: {
    name: 'Taran',
    profession: 'Pigkeeper'
  }
end

# Page through a set
pigkeepers = Fauna::Query.expr { match(ref('indexes/users_by_profession'), 'Pigkeeper') }
oracles = Fauna::Query.expr { match(ref('indexes/users_by_profession'), 'Oracle') }

$fauna.query { paginate(union(pigkeepers, oracles)) }

# Delete the user
$fauna.query { delete taran[:ref] }


Value result = client.Query(Paginate(Match(Ref("indexes/spells"))));

Query methods receives an Expr object. Expr objects can be composed with others Expr to create complex query objects. FaunaDB.Query.Language is a helper class where you can find all available expressions in the library.

How to access objects fields and convert to primitive values

Objects fields are accessed through At methods of Value class. It’s possible to access fields by names if the value represents an object or by index if it represents an array. Also it’s possible to convert Value class to its primitive correspondent using To methods specifying a Codec.


IResult<IReadOnlyList<Value>> data = result.At("data").To(Codec.ARRAY);

How work with IResult<T> objects

This object represents the result of an operation and it might be success or a failure. All operations on Codec return an object like this. This way it’s possible to avoid check for nullability everywhere in the code.


data.Match(
    Success: value => ProcessData(value),
    Failure: reason => Console.WriteLine($"Something went wrong: {reason}")
);

Optionally it’s possible transform one IResult<T> into another IResult<U> of different type using Map and FlatMap.


IResult<int> result = <<...>>;
IResult<string> result.Map(value => value.toString());

If result represents as failure all calls to Map and FlatMap are ignored. See FaunaDB.Types.Result.


import FaunaDB

struct Post {
    let title: String
    let body: String?
}

extension Post: FaunaDB.Encodable {
    func encode() -> Expr {
        return Obj(
            "title" => title,
            "body" => body
        )
    }
}

extension Post: FaunaDB.Decodable {
    init?(value: Value) throws {
        try self.init(
            title: value.get("title") ?? "Untitled",
            body: value.get("body")
        )
    }
}

let client = FaunaDB.Client(secret: "your-key-secret-here")

// Creating a new post
try! client.query(
    Create(
        at: Class("posts")
        Obj("data" => Post("My swift app", nil))
    )
).await(timeout: .now() + 5)

// Retrieve a saved post
let getPost = client.query(Get(Ref(class: Class("posts"), id: "42")))
let post: Post = try! getPost.map { dbEntry in dbEntry.get("data") }
    .await(timeout: .now() + 5)

For more examples, check our online documentation and our example project.


import com.faunadb.client.*;
import com.faunadb.client.types.*;
import com.faunadb.client.types.Value.*;
import com.google.common.collect.*;

import static com.faunadb.client.query.Language.*;

public class Main {
  public static void main(String[] args) throws Exception {
    FaunaClient client = FaunaClient.builder()
      .withSecret("your-secret-here")
      .build();

    ImmutableList<RefV> indexes = client.query(Paginate(Ref("indexes"))).get()
      .at("data").collect(Field.as(Codec.REF));

    System.out.println(indexes);
  }
}

Javadocs are hosted on GitHub:


import faunadb.FaunaClient
import faunadb.query._
import faunadb.values._
import scala.concurrent._
import scala.concurrent.duration._

object Main extends App {
  import ExecutionContext.Implicits._

  val client = FaunaClient(secret = "your-secret-here")

  val indexes = client
    .query(Paginate(Ref("indexes")))
    .map(value => value("data").to[Seq[RefV]].get)

  println(
    Await.result(indexes, Duration.Inf)
  )
}

Scaladocs are hosted on GitHub:


from faunadb import query as q
from faunadb.objects import Ref
from faunadb.client import FaunaClient

client = FaunaClient(secret="your-secret-here")

indexes = client.query(q.paginate(Ref("indexes")))

print(indexes)

Congratulations, you achieved hello world! To start learning about FaunaDB, jump to the Basics Tutorial.

Further Reading