TOPICS
LANGUAGE

How to Create, Retrieve, Update, and Delete Objects in FaunaDB

FaunaDB allows you to store objects and query them in a relational fashion. Below, we’ll walk through a basic example of creating, retrieving, updating, and deleting (CRUD) objects in FaunaDB.

We’ll be talking about instances, classes, and objects throughout this page. If you’re new to FaunaDB, make sure to check out our Glossary for definitions.

Introduction

To demonstrate how to perform CRUD operations in FaunaDB, we will use the example of blog posts: creating blog posts, updating them with additional attributes, and querying for specific posts.

Our basic steps will be:

  1. Making sure our prerequisites are met.
  2. Creating a database.
  3. Setting up our schema.
  4. Creating posts in our database.
  5. Retrieving posts.
  6. Updating posts.
  7. And finally, deleting posts.

We’ve set up this example so you can follow along from start to finish. Feel free to skip straight to creating data if you are just looking for examples of the create, retrieve, update, and delete process.

Prerequisites

This section will walk you through setting up your environment, installing a driver, importing the driver, obtaining an admin API key, and instantiating the client.

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

Compatible with:

  • .NET Standard 1.5 and 2.0
  • .NET Framework 4.5, 4.5.1, 4.6, 4.6.1, 4.7
  • 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

Install the Driver

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/2.0/faunadb.js"></script>

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

<script src="//cdn.jsdelivr.net/faunadb/2.0/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 adding the package reference to your MSBuild project:

<PackageReference Include="FaunaDB.Client" Version="2.0.0" />

or by using your IDE and searching for FaunaDB.Client.

CocoaPods:

pod 'FaunaDB', '~> 2.0.0'

Carthage:

github 'fauna/faunadb-swift'

SwiftPM:

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

Download from the Maven central repository:

faunadb-java/pom.xml:

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

faunadb-android/pom.xml:

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

faunadb-scala/sbt

libraryDependencies += ("com.faunadb" %% "faunadb-scala" % "2.1.0")
pip install faunadb

Import the Driver

The curl command should be in your 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 (
  "fmt"
  f "github.com/fauna/faunadb-go/faunadb"
)

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

Obtain an Admin API Key

To follow along you will need an admin API key.

  • For FaunaDB Serverless Cloud: create an admin key using the admin keys interface.
  • For FaunaDB Enterprise: use the configured root key for your cluster.

Instantiate the Client

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")
$fauna = Fauna::Client.new(secret: YOUR_FAUNADB_SECRET)

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: YOUR_FAUNADB_SECRET,
  observer: observer)
var client = new FaunaClient(secret: YOUR_FAUNADB_SECRET);
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")

Create a Database

Create a database in FaunaDB:


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

client.Query(CreateDatabase(Obj("name", "my_app")));

System.out.println(
      client.query(CreateDatabase(Obj("name", Value("my_app")))
   ).get());

result, _ := client.Query(f.CreateDatabase(f.Obj{"name": "my_app"}))

fmt.Println(result)

client.query(CreateDatabase(Obj("name" -> "my_app")))

client.query(q.create_database({"name": "my_app"}))

$client.query do
  create_database name: 'my_app'
end

client.query(CreateDatabase(Obj("name" => "my_app")))

client.query(q.CreateDatabase({ name: "my_app" }))
  .then((ret) => console.log(ret))

=> HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "databases/my_app" },
    "class": { "@ref": "databases" },
    "ts": 1520225686389954,
    "name": "my_app"
  }
}

=> {
  "ref": { "@ref": "databases/my_app" },
  "class": { "@ref": "databases" },
  "ts": 1520225686389954,
  "name": "my_app"
}

=> {
  ref: ref(id = "my_app", class = ref(id = "databases")),
  ts: 1527146032847201,
  name: "my_app"
}

=> map[ref:{my_app 0xc420126220 <nil>} ts:1520225686389954 name:my_app]

=> {
  "ref": { "@ref": "databases/my_app" },
  "class": { "@ref": "databases" },
  "ts": 1520225686389954,
  "name": "my_app"
}

=> {
  "ref": { "@ref": "databases/my_app" },
  "class": { "@ref": "databases" },
  "ts": 1520225686389954,
  "name": "my_app"
}

=> {
  "ref": { "@ref": "databases/my_app" },
  "class": { "@ref": "databases" },
  "ts": 1520225686389954,
  "name": "my_app"
}

=> {
  "ref": { "@ref": "databases/my_app" },
  "class": { "@ref": "databases" },
  "ts": 1520225686389954,
  "name": "my_app"
}

=> { ref: Ref(id=my_app, class=Ref(id=databases)),
  ts: 1528127545620042,
  name: 'my_app' }

Accessing the Database

Create an initial server key by using an admin key. The server key has unrestricted access to a single database; in this case, the server key will only access the blog post database we just created.


curl https://db.fauna.com/ \
    -u fnACrVRyZhACAOvXOTRzOpg1Qqq5oPHKMfOLgcHQ: \
    -d '{
          "create_key": {
            "object": { "database": { "database": "my_app" }, "role": "server" }
          }
        }'

client.Query(
  CreateKey(
    Obj("database", Database("my_app"), "role", "server")));

System.out.println(
   client.query(
      CreateKey(
         Obj(
            "database", Database(Value("my_app")),
            "role", Value("server")
         )
      )
   ).get());

result, _ := client.Query(
    f.CreateKey(
        f.Obj{"database": f.Database("my_app"), "role": "server"},
    ),
)

fmt.Println(result)

client.query(
  CreateKey(
    Obj("database" -> Database("my_app"), "role" -> "server")))

client.query(
  q.create_key(
    {"database": q.database("my_app"), "role": "server"}
  ))

$client.query do
  create_key database: database('my_app'), role: 'server'
end

client.query(
    CreateKey(
        Obj(
            "database" => Database("my_app"),
            "role" => "server"
        )
    )
)

client.query(
  q.CreateKey(
    { database: q.Database("my_app"), role: "server" }))
.then((ret) => console.log(ret))

=> HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "keys/192903209473278464" },
    "class": { "@ref": "keys" },
    "ts": 1520225686419239,
    "database": { "@ref": "databases/my_app" },
    "role": "server",
    "secret": "fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq",
    "hashed_secret": "$2a$05$k9x7YbL5CYY9KIMhW6RaIOILyEwY3IHuX0NWvK9iUMWk8TJ7k1H8O"
  }
}

=> {
  "ref": { "@ref": "keys/192903209473278464" },
  "class": { "@ref": "keys" },
  "ts": 1520225686419239,
  "database": { "@ref": "databases/my_app" },
  "role": "server",
  "secret": "fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq",
  "hashed_secret": "$2a$05$k9x7YbL5CYY9KIMhW6RaIOILyEwY3IHuX0NWvK9iUMWk8TJ7k1H8O"
}

=> {
  ref: ref(id = "200313471592563200", class = ref(id = "keys")),
  ts: 1536604026291379,
  database: ref(id = "my_app", class = ref(id = "databases")),
  role: "server",
  secret: "fnAC6lgMjxACAFGhYyPLmQGQD3tCZkXWklDs1L6k",
  hashed_secret: "$2a$05$yQwmJEw4GrJViCqIDi0fa.4yz.dEDi3voIqAb6f7z3tvOHe4VZuHG"
}

=> map[
  ref:{192903209473278464 0xc42011ca60 <nil>}
  ts:1520225686419239
  database:{my_app 0xc42011cc00 <nil>}
  role:server
  secret:fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq
  hashed_secret:$2a$05$k9x7YbL5CYY9KIMhW6RaIOILyEwY3IHuX0NWvK9iUMWk8TJ7k1H8O
]

=> {
  "ref": { "@ref": "keys/192903209473278464" },
  "class": { "@ref": "keys" },
  "ts": 1520225686419239,
  "database": { "@ref": "databases/my_app" },
  "role": "server",
  "secret": "fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq",
  "hashed_secret": "$2a$05$k9x7YbL5CYY9KIMhW6RaIOILyEwY3IHuX0NWvK9iUMWk8TJ7k1H8O"
}

=> {
  "ref": { "@ref": "keys/192903209473278464" },
  "class": { "@ref": "keys" },
  "ts": 1520225686419239,
  "database": { "@ref": "databases/my_app" },
  "role": "server",
  "secret": "fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq",
  "hashed_secret": "$2a$05$k9x7YbL5CYY9KIMhW6RaIOILyEwY3IHuX0NWvK9iUMWk8TJ7k1H8O"
}

=> {
  "ref": { "@ref": "keys/192903209473278464" },
  "class": { "@ref": "keys" },
  "ts": 1520225686419239,
  "database": { "@ref": "databases/my_app" },
  "role": "server",
  "secret": "fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq",
  "hashed_secret": "$2a$05$k9x7YbL5CYY9KIMhW6RaIOILyEwY3IHuX0NWvK9iUMWk8TJ7k1H8O"
}

=> {
  "ref": { "@ref": "keys/192903209473278464" },
  "class": { "@ref": "keys" },
  "ts": 1520225686419239,
  "database": { "@ref": "databases/my_app" },
  "role": "server",
  "secret": "fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq",
  "hashed_secret": "$2a$05$k9x7YbL5CYY9KIMhW6RaIOILyEwY3IHuX0NWvK9iUMWk8TJ7k1H8O"
}

=> { ref: Ref(id=201188951594107392, class=Ref(id=keys)),
  ts: 1528127585813144,
  database: Ref(id=my_app, class=Ref(id=databases)),
  role: 'server',
  secret: 'fnACysRJGIACAHiL_5f0UxHlPFIZgq876ptMNJ72',
  hashed_secret: '$2a$05$wm6Zwl8dhlY3hFbJj0JrHuSt4YszzsDRd9KdxVbxg98yVOMJiEp0i' }

Set Up a Schema

FaunaDB stores data in the form of nested objects. Each instance object belongs to a specific class. So in order to create an instance for a post, we need to first create a posts class.

Create a class using the create_class function with a parameters object containing the name of the class. We’ll name our class “posts”:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{ "create_class": { "object": { "name": "posts" } } }'

client.Query(CreateClass(Obj("name", "posts")));

System.out.println(
        client.query(CreateClass(Obj("name", Value("posts"))))
        .get());

result, _ := client.Query(f.CreateClass(f.Obj{"name": "posts"}))

fmt.Println(result)

client.query(CreateClass(Obj("name" -> "posts")))

client.query(q.create_class({"name": "posts"}))

$client.query do
  create_class name: 'posts'
end

client.query(CreateClass(Obj("name" => "posts")))

client.query(q.CreateClass({ name: "posts" }))
  .then((ret) => console.log(ret))

=> HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "classes/posts" },
    "class": { "@ref": "classes" },
    "ts": 1520225686488810,
    "history_days": 30,
    "name": "posts"
  }
}

=> {
  "ref": { "@ref": "classes/posts" },
  "class": { "@ref": "classes" },
  "ts": 1520225686488810,
  "history_days": 30,
  "name": "posts"
}

=> {
  ref: ref(id = "posts", class = ref(id = "classes")),
  ts: 1536604026446481,
  history_days: 30,
  name: "posts"
}

=> map[ref:{posts 0xc4203068e0 <nil>} ts:1520225686488810 history_days:30 name:posts]

=> {
  "ref": { "@ref": "classes/posts" },
  "class": { "@ref": "classes" },
  "ts": 1520225686488810,
  "history_days": 30,
  "name": "posts"
}

=> {
  "ref": { "@ref": "classes/posts" },
  "class": { "@ref": "classes" },
  "ts": 1520225686488810,
  "history_days": 30,
  "name": "posts"
}

=> {
  "ref": { "@ref": "classes/posts" },
  "class": { "@ref": "classes" },
  "ts": 1520225686488810,
  "history_days": 30,
  "name": "posts"
}

=> {
  "ref": { "@ref": "classes/posts" },
  "class": { "@ref": "classes" },
  "ts": 1520225686488810,
  "history_days": 30,
  "name": "posts"
}

=> { ref: Ref(id=posts, class=Ref(id=classes)),
  ts: 1527349751848648,
  history_days: 30,
  name: 'posts' }

Preparing Schema for Queries

Before we create instance objects, let’s ensure we can easily access them. We’ll do this by creating an index using the create_index function. We’re creating this index now to help make the examples clear; in production, you can create an index at any time.

The customary way to access instances of a class is by specifying a criteria for one of the fields. To enable criteria-based searches, we need to first create an index using the position of the field within the instance.

We’ll create an index on the post’s title:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{
          "create_index": {
            "object": {
              "name": "posts_by_title",
              "source": { "class": "posts" },
              "terms": [ { "object": { "field": [ "data", "title" ] } } ]
            }
          }
        }'

client.Query(
  CreateIndex(
    Obj(
      "name", "posts_by_title",
      "source", Class("posts"),
      "terms", Arr(Obj("field", Arr("data", "title")))
    )));

System.out.println(
        client.query(
        CreateIndex(
          Obj(
          "name", Value("posts_by_title"),
          "source", Class(Value("posts")),
          "terms", Arr(Obj("field", Arr(Value("data"), Value("title"))))
          )
       )).get());

result, _ := client.Query(
    f.CreateIndex(
        f.Obj{
            "name": "posts_by_title",
            "source": f.Class("posts"),
            "terms": f.Arr{f.Obj{"field": f.Arr{"data", "title"}}},
        },
    ),
)

fmt.Println(result)

client.query(
  CreateIndex(
    Obj(
      "name" -> "posts_by_title",
      "source" -> Class("posts"),
      "terms" -> Arr(Obj("field" -> Arr("data", "title")))
    )))

client.query(
  q.create_index(
    {
      "name": "posts_by_title",
      "source": q.class_expr("posts"),
      "terms": [{"field": ["data", "title"]}]
    }
  ))

$client.query do
  create_index name: 'posts_by_title',
               source: class_('posts'),
               terms: [{ field: ['data', 'title'] }]
end

client.query(
    CreateIndex(
        Obj(
            "name" => "posts_by_title",
            "source" => Class("posts"),
            "terms" => Arr(Obj("field" => Arr("data", "title")))
        )
    )
)

client.query(
  q.CreateIndex(
    { name: "posts_by_title",
      source: q.Class("posts"),
      terms: [{ field: ["data", "title"] }] }))
.then((ret) => console.log(ret))

=> HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "indexes/posts_by_title" },
    "class": { "@ref": "indexes" },
    "ts": 1520225686568953,
    "active": false,
    "partitions": 1,
    "name": "posts_by_title",
    "source": { "@ref": "classes/posts" },
    "terms": [ { "field": [ "data", "title" ] } ]
  }
}

=> {
  "ref": { "@ref": "indexes/posts_by_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686568953,
  "active": false,
  "partitions": 1,
  "name": "posts_by_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "title" ] } ]
}

=> {
  ref: ref(id = "posts_by_title", class = ref(id = "indexes")), 
  ts: 1527206084051852, 
  active: false,
  partitions: 1, 
  name: "posts_by_title", 
  source: ref(id = "posts", class = ref(id = "classes")), 
  terms: [ {field: ["data", "title"]} ]
}

=> map[ref:{posts_by_title 0xc4203663e0 <nil>} ts:1520225686568953 active:false partitions:1 name:posts_by_title source:{posts 0xc420366640 <nil>} terms:[map[field:[data title]]]]

=> {
  "ref": { "@ref": "indexes/posts_by_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686568953,
  "active": false,
  "partitions": 1,
  "name": "posts_by_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "title" ] } ]
}

=> {
  "ref": { "@ref": "indexes/posts_by_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686568953,
  "active": false,
  "partitions": 1,
  "name": "posts_by_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "title" ] } ]
}

=> {
  "ref": { "@ref": "indexes/posts_by_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686568953,
  "active": false,
  "partitions": 1,
  "name": "posts_by_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "title" ] } ]
}

=> {
  "ref": { "@ref": "indexes/posts_by_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686568953,
  "active": false,
  "partitions": 1,
  "name": "posts_by_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "title" ] } ]
}

=> { ref: Ref(id=posts_by_title, class=Ref(id=indexes)),
  ts: 1527350163658503,
  active: false,
  partitions: 1,
  name: 'posts_by_title',
  source: Ref(id=posts, class=Ref(id=classes)),
  terms: [ { field: [Array] } ] }

It is also possible to specify the values of the object that should be returned when querying the index. We’ll also create an index for a post’s tags:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{
          "create_index": {
            "object": {
              "name": "posts_by_tags_with_title",
              "source": { "class": "posts" },
              "terms": [ { "object": { "field": [ "data", "tags" ] } } ],
              "values": [ { "object": { "field": [ "data", "title" ] } } ]
            }
          }
        }'

client.Query(
  CreateIndex(
    Obj(
      "name", "posts_by_tags_with_title",
      "source", Class("posts"),
      "terms", Arr(Obj("field", Arr("data", "tags"))),
      "values", Arr(Obj("field", Arr("data", "title")))
    )));

System.out.println(
        client.query(
                CreateIndex(
                  Obj(
                   "name", Value("posts_by_tags_with_title"),
                   "source", Class(Value("posts")),
                   "terms", Arr(Obj("field", Arr(Value("data"), Value("tags")))),
                   "values", Arr(Obj("field", Arr(Value("data"), Value("title"))))
                  )
                )).get());

result, _ := client.Query(
    f.CreateIndex(
        f.Obj{
            "name": "posts_by_tags_with_title",
            "source": f.Class("posts"),
            "terms": f.Arr{f.Obj{"field": f.Arr{"data", "tags"}}},
            "values": f.Arr{f.Obj{"field": f.Arr{"data", "title"}}},
        },
    ),
)

fmt.Println(result)

client.query(
  CreateIndex(
    Obj(
      "name" -> "posts_by_tags_with_title",
      "source" -> Class("posts"),
      "terms" -> Arr(Obj("field" -> Arr("data", "tags"))),
      "values" -> Arr(Obj("field" -> Arr("data", "title")))
    )))

client.query(
  q.create_index(
    {
      "name": "posts_by_tags_with_title",
      "source": q.class_expr("posts"),
      "terms": [{"field": ["data", "tags"]}],
      "values": [{"field": ["data", "title"]}]
    }
  ))

$client.query do
  create_index name: 'posts_by_tags_with_title',
               source: class_('posts'),
               terms: [{ field: ['data', 'tags'] }],
               values: [{ field: ['data', 'title'] }]
end

client.query(
    CreateIndex(
        Obj(
            "name" => "posts_by_tags_with_title",
            "source" => Class("posts"),
            "terms" => Arr(Obj("field" => Arr("data", "tags"))),
            "values" => Arr(Obj("field" => Arr("data", "title")))
        )
    )
)

client.query(
  q.CreateIndex(
    { name: "posts_by_tags_with_title",
      source: q.Class("posts"),
      terms: [{ field: ["data", "tags"] }],
      values: [{ field: ["data", "title"] }] }))
.then((ret) => console.log(ret))

=> HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "indexes/posts_by_tags_with_title" },
    "class": { "@ref": "indexes" },
    "ts": 1520225686587489,
    "active": false,
    "partitions": 1,
    "name": "posts_by_tags_with_title",
    "source": { "@ref": "classes/posts" },
    "terms": [ { "field": [ "data", "tags" ] } ],
    "values": [ { "field": [ "data", "title" ] } ]
  }
}

=> {
  "ref": { "@ref": "indexes/posts_by_tags_with_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686587489,
  "active": false,
  "partitions": 1,
  "name": "posts_by_tags_with_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "tags" ] } ],
  "values": [ { "field": [ "data", "title" ] } ]
}

=> {
  ref: ref(id = "posts_by_tags_with_title", class = ref(id = "indexes")), 
  ts: 1527206084101804, 
  active: false, 
  partitions: 1, 
  name: "posts_by_tags_with_title", 
  source: ref(id = "posts", class = ref(id = "classes")), 
  terms: [ {field: ["data", "tags"]} ], 
  values: [ {field: ["data", "title"]} ]
}

=> map[
  ref:{posts_by_tags_with_title 0xc42031ccc0 <nil>}
  ts:1520225686587489
  active:false
  partitions:1
  name:posts_by_tags_with_title
  source:{posts 0xc42031cf20 <nil>}
  terms:[map[field:[data tags]]]
  values:[map[field:[data title]]]
]

=> {
  "ref": { "@ref": "indexes/posts_by_tags_with_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686587489,
  "active": false,
  "partitions": 1,
  "name": "posts_by_tags_with_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "tags" ] } ],
  "values": [ { "field": [ "data", "title" ] } ]
}

=> {
  "ref": { "@ref": "indexes/posts_by_tags_with_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686587489,
  "active": false,
  "partitions": 1,
  "name": "posts_by_tags_with_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "tags" ] } ],
  "values": [ { "field": [ "data", "title" ] } ]
}

=> {
  "ref": { "@ref": "indexes/posts_by_tags_with_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686587489,
  "active": false,
  "partitions": 1,
  "name": "posts_by_tags_with_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "tags" ] } ],
  "values": [ { "field": [ "data", "title" ] } ]
}

=> {
  "ref": { "@ref": "indexes/posts_by_tags_with_title" },
  "class": { "@ref": "indexes" },
  "ts": 1520225686587489,
  "active": false,
  "partitions": 1,
  "name": "posts_by_tags_with_title",
  "source": { "@ref": "classes/posts" },
  "terms": [ { "field": [ "data", "tags" ] } ],
  "values": [ { "field": [ "data", "title" ] } ]
}

=> { ref: Ref(id=posts_by_tags_with_title, class=Ref(id=indexes)),
  ts: 1527350198235760,
  active: false,
  partitions: 1,
  name: 'posts_by_tags_with_title',
  source: Ref(id=posts, class=Ref(id=classes)),
  terms: [ { field: [Array] } ],
  values: [ { field: [Array] } ] }

Creating a Post

Posts are created by calling the create function with the ref of the posts class and a params object. The post’s data is included in the params object’s “data” field.


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{
          "create": { "class": "posts" },
          "params": {
            "object": {
              "data": { "object": { "title": "What I had for breakfast .." } }
            }
          }
        }'

client.Query(
  Create(
    Class("posts"),
    Obj("data", Obj("title", "What I had for breakfast .."))));

System.out.println(
        client.query(
          Create(
            Class(Value("posts")),
            Obj(
                "data", Obj(
                        "title", Value("What I had for breakfast ..")
                )
            )
          )
        ).get());

result, _ := client.Query(
    f.Create(
        f.Class("posts"),
        f.Obj{"data": f.Obj{"title": "What I had for breakfast .."}},
    ),
)

fmt.Println(result)

client.query(
  Create(
    Class("posts"),
    Obj("data" -> Obj("title" -> "What I had for breakfast .."))))

client.query(
  q.create(
    q.class_expr("posts"),
    {"data": {"title": "What I had for breakfast .."}}
  ))

$client.query do
  create class_('posts'),
         data: { title: 'What I had for breakfast ..' }
end

client.query(
    Create(
        at: Class("posts"),
        Obj(
            "data" => Obj("title" => "What I had for breakfast ..")
        )
    )
)

client.query(
  q.Create(
    q.Class("posts"),
    { data: { title: "What I had for breakfast .." } }))
.then((ret) => console.log(ret))

=> HTTP/1.1 201 Created
{
  "resource": {
    "ref": { "@ref": "classes/posts/192903209680896512" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686617873,
    "data": { "title": "What I had for breakfast .." }
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209680896512" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686617873,
  "data": { "title": "What I had for breakfast .." }
}

=> {
  ref: ref(id = "210077143904813568", class = ref(id = "posts", class = ref(id = "classes"))),
  ts: 1536604026594000,
  data: {title: "What I had for breakfast .."}
}

=> map[ref:{192903209680896512 0xc420370a40 <nil>} ts:1520225686617873 data:map[title:What I had for breakfast ..]]

=> {
  "ref": { "@ref": "classes/posts/192903209680896512" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686617873,
  "data": { "title": "What I had for breakfast .." }
}

=> {
  "ref": { "@ref": "classes/posts/192903209680896512" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686617873,
  "data": { "title": "What I had for breakfast .." }
}

=> {
  "ref": { "@ref": "classes/posts/192903209680896512" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686617873,
  "data": { "title": "What I had for breakfast .." }
}

=> {
  "ref": { "@ref": "classes/posts/192903209680896512" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686617873,
  "data": { "title": "What I had for breakfast .." }
}

=> { ref:
   Ref(id=200372984285757952, class=Ref(id=posts, class=Ref(id=classes))),
  ts: 1527349418742172,
  data: { title: 'What I had for breakfast ..' } }

The create function returns the post instance just created. The ref of the instance is an automatically generated identifier that is unique to the instance within its database.

Create Several Posts

It can quickly become tedious to repeat the create function for multiple posts.

This is where FaunaDB’s transaction language really shines. Let’s use a map function to create several posts at once:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{
          "map": {
            "lambda": "post_title",
            "expr": {
              "create": { "class": "posts" },
              "params": {
                "object": {
                  "data": { "object": { "title": { "var": "post_title" } } }
                }
              }
            }
          },
          "collection": [
            "My cat and other marvels",
            "Pondering during a commute",
            "Deep meanings in a latte"
          ]
        }'

client.Query(
  Map(
    Arr(
      "My cat and other marvels",
      "Pondering during a commute",
      "Deep meanings in a latte"
    ),
    post_title => Create(
      Class("posts"),
      Obj("data", Obj("title", post_title)))));

System.out.println(
       client.query(
          Map(
             Arr(
               Value("My cat and other marvels"),
               Value("Pondering during a commute"),
               Value("Deep meanings in a latte")
             ),
             Lambda(
               Value("post_title"),
               Create(
                 Class(Value("posts")),
                 Obj("data",
                         Obj(
                         "title", Var("post_title")
                         )
                 )
               )
             )
          )
       ).get());

result, _ := client.Query(
    f.Map(
        f.Arr{
            "My cat and other marvels",
            "Pondering during a commute",
            "Deep meanings in a latte",
        },
        f.Lambda(
            "post_title",
            f.Create(
                f.Class("posts"),
                f.Obj{"data": f.Obj{"title": f.Var("post_title")}},
            ),
        ),
    ),
)

fmt.Println(result)

client.query(
  Map(
    Arr(
      "My cat and other marvels",
      "Pondering during a commute",
      "Deep meanings in a latte"
    ),
    Lambda { post_title =>
      Create(
        Class("posts"),
        Obj("data" -> Obj("title" -> post_title)))
    }))

client.query(
  q.map_expr(
    lambda post_title: q.create(
      q.class_expr("posts"),
      {"data": {"title": post_title}}
    ),
    [
      "My cat and other marvels",
      "Pondering during a commute",
      "Deep meanings in a latte"
    ]
  ))

$client.query do
  map [
    'My cat and other marvels',
    'Pondering during a commute',
    'Deep meanings in a latte'
  ] do |post_title|
    create(class_('posts'), data: { title: post_title })
  end
end

client.query(
    Map(
        collection: Arr(
            "My cat and other marvels",
            "Pondering during a commute",
            "Deep meanings in a latte"
        ),
        to: { postTitle in
            Create(
                at: Class("posts"),
                Obj("data" => Obj("title" => postTitle))
            )
        }
    )
)

client.query(
  q.Map(
    [ "My cat and other marvels",
      "Pondering during a commute",
      "Deep meanings in a latte" ],
    q.Lambda("post_title", q.Create(
      q.Class("posts"), { data: { title: q.Var("post_title") } } ))))
.then((ret) => console.log(ret))

=> HTTP/1.1 200 OK
{
  "resource": [
    {
      "ref": { "@ref": "classes/posts/192903209792046592" },
      "class": { "@ref": "classes/posts" },
      "ts": 1520225686723969,
      "data": { "title": "My cat and other marvels" }
    },
    {
      "ref": { "@ref": "classes/posts/192903209792047616" },
      "class": { "@ref": "classes/posts" },
      "ts": 1520225686723969,
      "data": { "title": "Pondering during a commute" }
    },
    {
      "ref": { "@ref": "classes/posts/192903209792045568" },
      "class": { "@ref": "classes/posts" },
      "ts": 1520225686723969,
      "data": { "title": "Deep meanings in a latte" }
    }
  ]
}

=> [
  {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "My cat and other marvels" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792047616" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Pondering during a commute" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792045568" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Deep meanings in a latte" }
  }
]

=> [
  {
    ref: ref(id = "192903209792046592", class = ref(id = "posts", class = ref(id = "classes"))), 
    ts: 1536604026800813, 
    data: {title: "My cat and other marvels"}
  },
  {
    ref: ref(id = "192903209792047616", class = ref(id = "posts", class = ref(id = "classes"))), 
    ts: 1536604026800813, 
    data: {title: "Pondering during a commute"}
  },
  {
    ref: ref(id = "192903209792045568", class = ref(id = "posts", class = ref(id = "classes"))), 
    ts: 1536604026800813, 
    data: {title: "Deep meanings in a latte"}
  }
]

=> [
  map[ref:{192903209792046592 0xc420339c20 <nil>} ts:1520225686723969 data:map[title:My cat and other marvels]]
  map[ref:{192903209792047616 0xc420339f00 <nil>} ts:1520225686723969 data:map[title:Pondering during a commute]]
  map[ref:{192903209792045568 0xc420380200 <nil>} ts:1520225686723969 data:map[title:Deep meanings in a latte]]
]

=> [
  {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "My cat and other marvels" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792047616" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Pondering during a commute" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792045568" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Deep meanings in a latte" }
  }
]

=> [
  {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "My cat and other marvels" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792047616" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Pondering during a commute" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792045568" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Deep meanings in a latte" }
  }
]

=> [
  {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "My cat and other marvels" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792047616" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Pondering during a commute" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792045568" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Deep meanings in a latte" }
  }
]

=> [
  {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "My cat and other marvels" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792047616" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Pondering during a commute" }
  },
  {
    "ref": { "@ref": "classes/posts/192903209792045568" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Deep meanings in a latte" }
  }
]

=> [ { ref:
     Ref(id=200373080062689792, class=Ref(id=posts, class=Ref(id=classes))),
    ts: 1527349510087794,
    data: { title: 'My cat and other marvels' } },
  { ref:
     Ref(id=200373080062690816, class=Ref(id=posts, class=Ref(id=classes))),
    ts: 1527349510087794,
    data: { title: 'Pondering during a commute' } },
  { ref:
     Ref(id=200373080062691840, class=Ref(id=posts, class=Ref(id=classes))),
    ts: 1527349510087794,
    data: { title: 'Deep meanings in a latte' } } ]

Using the map function, we can restructure the data as a collection and wrap the create in a Lisp-style lambda function, which then runs over each object in the collection. The anonymous lambda function specifies a variable post_title which is used as a placeholder in the parameters sent to the create function. This way, multiple instances of a class can be created using a single query.

Retrieving Posts

The easiest way to retrieve an instance is using its reference value:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{ "get": { "@ref": "classes/posts/192903209792046592" } }'

client.Query(Get(Ref("classes/posts/192903209792046592")));

System.out.println(
        client.query(Get(Ref(Class("posts"),Value(192903209792046592L))))
        .get());

result, _ := client.Query(f.Get(f.RefClass(f.Class("posts"), "192903209792046592")))

fmt.Println(result)

client.query(Get(Ref("classes/posts/192903209792046592")))

client.query(q.get(Ref("classes/posts/192903209792046592")))

$client.query do
  get ref('classes/posts/192903209792046592')
end

client.query(Get(Ref("classes/posts/192903209792046592")))

client.query(q.Get(q.Ref(q.Class("posts"), "192903209792046592")))
  .then((ret) => console.log(ret))

=> HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "My cat and other marvels" }
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  ref: ref(id = "192903209792046592", class = ref(id = "posts", class = ref(id = "classes"))),
  ts: 1527206084284540,
  data: {title: "My cat and other marvels"}
}

=> map[ref:{192903209792046592 0xc420338e80 <nil>} ts:1520225686723969 data:map[title:My cat and other marvels]]

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> { ref:
   Ref(id=192903209792046592, class=Ref(id=posts, class=Ref(id=classes))),
  ts: 1527350638301882,
  data: { title: 'My cat and other marvels' } }

You can query for posts with a specific title using the match function and the index we created earlier:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{
          "get": {
            "match": { "index": "posts_by_title" },
            "terms": "My cat and other marvels"
          }
        }'

client.Query(
  Get(
    Match(Index("posts_by_title"), "My cat and other marvels")));

System.out.println(
   client.query(
    Get(
      Match(
        Index(Value("posts_by_title")),
        Value("My cat and other marvels")))).get());

result, _ := client.Query(
    f.Get(
        f.MatchTerm(
            f.Index("posts_by_title"),
            "My cat and other marvels",
        ),
    ),
)

fmt.Println(result)

client.query(
  Get(
    Match(Index("posts_by_title"), "My cat and other marvels")))

client.query(
  q.get(
    q.match(
      q.index("posts_by_title"),
      "My cat and other marvels"
    )
  ))

$client.query do
  get match(index('posts_by_title'), 'My cat and other marvels')
end

client.query(
    Get(
        Match(
            index: Index("posts_by_title"),
            terms: "My cat and other marvels"
        )
    )
)

client.query(
  q.Get(
    q.Match(q.Index("posts_by_title"), "My cat and other marvels")))
.then((ret) => console.log(ret))

=> HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "My cat and other marvels" }
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  ref: ref(id = "192903209792046592", class = ref(id = "posts", class = ref(id = "classes"))), 
  ts: 1527206084284540, 
  data: {title: "My cat and other marvels"}
}

=> map[ref:{192903209792046592 0xc420338e80 <nil>} ts:1520225686723969 data:map[title:My cat and other marvels]]

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "My cat and other marvels" }
}

=> { ref:
   Ref(id=192903209792046592, class=Ref(id=posts, class=Ref(id=classes))),
  ts: 1527088583491065,
  data: { title: 'My cat and other marvels' } }

The match function returns a logical set of elements, which can be combined with other sets with set-operations like join, intersect, subtract, etc.

Updating Posts

You can easily modify instances by supplying the new data along with the reference to the instance. For example, we want to add tags to each of our blog posts:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{
          "update": { "@ref": "classes/posts/192903209792046592" },
          "params": {
            "object": { "data": { "object": { "tags": [ "pet", "cute" ] } } }
          }
        }'

client.Query(
  Update(
    Ref("classes/posts/192903209792046592"),
    Obj("data", Obj("tags", Arr("pet", "cute")))));

System.out.println(
      client.query(
        Update(
      Ref(Class("posts"),Value(192903209792046592L)),
          Obj("data", Obj("tags", Arr(Value("pet"), Value("cute"))))))
      .get());

result, _ := client.Query(
    f.Update(
        f.RefClass(f.Class("posts"), "192903209792046592"),
        f.Obj{"data": f.Obj{"tags": f.Arr{"pet", "cute"}}},
    ),
)

fmt.Println(result)

client.query(
  Update(
    Ref("classes/posts/192903209792046592"),
    Obj("data" -> Obj("tags" -> Arr("pet", "cute")))))

client.query(
  q.update(
    Ref("classes/posts/192903209792046592"),
    {"data": {"tags": ["pet", "cute"]}}
  ))

$client.query do
  update ref('classes/posts/192903209792046592'),
         data: { tags: ['pet', 'cute'] }
end

client.query(
    Update(
        ref: Ref("classes/posts/192903209792046592"),
        to: Obj("data" => Obj("tags" => Arr("pet", "cute")))
    )
)

client.query(
  q.Update(
    q.Ref(q.Class("posts"), "192903209792046592"),
    { data: { tags: ["pet", "cute"] } }))
.then((ret) => console.log(ret))

=> HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686763243,
    "data": {
      "title": "My cat and other marvels",
      "tags": [ "pet", "cute" ]
    }
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686763243,
  "data": {
    "title": "My cat and other marvels",
    "tags": [ "pet", "cute" ]
  }
}

=> {
  ref: ref(id = "192903209792046592", class = ref(id = "posts", class = ref(id = "classes"))), 
  ts: 1527206084367212, 
  data: {
    title: "My cat and other marvels", 
    tags: ["pet", "cute"]
  }
}

=> map[ref:{192903209792046592 0xc42036fc00 <nil>} ts:1520225686763243 data:map[title:My cat and other marvels tags:[pet cute]]]

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686763243,
  "data": {
    "title": "My cat and other marvels",
    "tags": [ "pet", "cute" ]
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686763243,
  "data": {
    "title": "My cat and other marvels",
    "tags": [ "pet", "cute" ]
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686763243,
  "data": {
    "title": "My cat and other marvels",
    "tags": [ "pet", "cute" ]
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686763243,
  "data": {
    "title": "My cat and other marvels",
    "tags": [ "pet", "cute" ]
  }
}

=> { ref:
   Ref(id=192903209792046592, class=Ref(id=posts, class=Ref(id=classes))),
  ts: 1527350534706104,
  data:
   { title: 'My cat and other marvels', tags: [ 'pet', 'cute' ] } }

The update function updates specific fields on an instance. It preserves the old fields if they are not specified in params. In the case of objects, the old and the new values are merged. If null is specified as a value for a field, it is removed.

Replacing Posts

The replace function, on the other hand, replaces the instance data with the fields provided in params. Therefore, old fields not mentioned in params are removed.


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{
          "replace": { "@ref": "classes/posts/192903209792046592" },
          "params": {
            "object": {
              "data": { "object": { "title": "My dog and other marvels" } }
            }
          }
        }'

client.Query(
  Replace(
    Ref("classes/posts/192903209792046592"),
    Obj("data", Obj("title", "My dog and other marvels"))));

System.out.println(
      client.query(
        Replace(
          Ref(Class("posts"),Value(192903209792046592L)),
          Obj("data", Obj("title", Value("My dog and other marvels")))))
      .get());

result, _ := client.Query(
    f.Replace(
        f.RefClass(f.Class("posts"), "192903209792046592"),
        f.Obj{"data": f.Obj{"title": "My dog and other marvels"}},
    ),
)

fmt.Println(result)

client.query(
  Replace(
    Ref("classes/posts/192903209792046592"),
    Obj("data" -> Obj("title" -> "My dog and other marvels"))))

client.query(
  q.replace(
    Ref("classes/posts/192903209792046592"),
    {"data": {"title": "My dog and other marvels"}}
  ))

$client.query do
  replace ref('classes/posts/192903209792046592'),
          data: { title: 'My dog and other marvels' }
end

client.query(
    Replace(
        ref: Ref("classes/posts/192903209792046592"),
        with: Obj(
            "data" => Obj("title" => "My dog and other marvels")
        )
    )
)

client.query(
  q.Replace(
    q.Ref(q.Class("posts"), "192903209792046592"),
    { data: { title: "My dog and other marvels" } }))
.then((ret) => console.log(ret))

=> HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/posts/192903209792046592" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686781061,
    "data": { "title": "My dog and other marvels" }
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686781061,
  "data": { "title": "My dog and other marvels" }
}

=> {
  ref: ref(id = "192903209792046592", class = ref(id = "posts", class = ref(id = "classes"))), 
  ts: 1527206084395803, 
  data: { title: "My dog and other marvels" }
}

=> map[ref:{192903209792046592 0xc42035c0c0 <nil>} ts:1520225686781061 data:map[title:My dog and other marvels]]

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686781061,
  "data": { "title": "My dog and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686781061,
  "data": { "title": "My dog and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686781061,
  "data": { "title": "My dog and other marvels" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792046592" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686781061,
  "data": { "title": "My dog and other marvels" }
}

=> { ref:
   Ref(id=192903209792046592, class=Ref(id=posts, class=Ref(id=classes))),
  ts: 1527350638301882,
  data: { title: 'My dog and other marvels' } }

Note that the title has been updated, but tags has been deleted.

Deleting a Post

Lastly, a post can be removed using the delete function:


curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{ "delete": { "@ref": "classes/posts/192903209792045568" } }'

client.Query(Delete(Ref("classes/posts/192903209792045568")));

System.out.println(
      client.query(
         Delete(Ref(Class("posts"),Value(192903209792045568L))))
      .get());

result, _ := client.Query(
    f.Delete(f.RefClass(f.Class("posts"), "192903209792045568")),
)

fmt.Println(result)

client.query(Delete(Ref("classes/posts/192903209792045568")))

client.query(q.delete(Ref("classes/posts/192903209792045568")))

$client.query do
  delete ref('classes/posts/192903209792045568')
end

client.query(
    Delete(ref: Ref("classes/posts/192903209792045568"))
)

client.query(q.Delete(q.Ref(q.Class("posts"),"192903209792045568")))
  .then((ret) => console.log(ret))

=> HTTP/1.1 200 OK
{
  "resource": {
    "ref": { "@ref": "classes/posts/192903209792045568" },
    "class": { "@ref": "classes/posts" },
    "ts": 1520225686723969,
    "data": { "title": "Deep meanings in a latte" }
  }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792045568" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "Deep meanings in a latte" }
}

=> {
  ref: ref(id = "192903209792045568", class = ref(id = "posts", class = ref(id = "classes"))),
  ts: 1536604026800813,
  data: {title: "Deep meanings in a latte"}
}

=> map[ref:{192903209792045568 0xc420341060 <nil>} ts:1520225686723969 data:map[title:Deep meanings in a latte]]

=> {
  "ref": { "@ref": "classes/posts/192903209792045568" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "Deep meanings in a latte" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792045568" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "Deep meanings in a latte" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792045568" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "Deep meanings in a latte" }
}

=> {
  "ref": { "@ref": "classes/posts/192903209792045568" },
  "class": { "@ref": "classes/posts" },
  "ts": 1520225686723969,
  "data": { "title": "Deep meanings in a latte" }
}

=> { ref:
   Ref(id=192903209792045568, class=Ref(id=posts, class=Ref(id=classes))),
  ts: 1527349510087794,
  data: { title: 'Deep meanings in a latte' } }

curl https://db.fauna.com/ \
    -u fnACrVRybLACAOytRXDMleFgdUZKXcJfMdzyjsRq: \
    -d '{ "get": { "@ref": "classes/posts/192903209792045568" } }'

client.Query(Get(Ref("classes/posts/192903209792045568")));

System.out.println(
        client.query(Get(Ref(Class("posts"),Value(192903209792045568L))))
        .get());

_, err := client.Query(f.Get(f.RefClass(f.Class("posts"), "192903209792045568")))

fmt.Println(err)

client.query(Get(Ref("classes/posts/192903209792045568")))

client.query(q.get(Ref("classes/posts/192903209792045568")))

$client.query do
  get ref('classes/posts/192903209792045568')
end

client.query(Get(Ref("classes/posts/192903209792045568")))

client.query(q.Get(q.Ref(q.Class("posts"), "192903209792045568")))
  .then((ret) => console.log(ret))
  .catch((ret) => console.log(ret))

=> HTTP/1.1 404 Not Found
{
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> ERROR java.util.concurrent.ExecutionException: com.faunadb.client.errors.NotFoundException: instance not found: Instance not found.

=> Response error 404. Errors: [](instance not found): Instance not found.

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> {
  "errors": [
    {
      "position": [  ],
      "code": "instance not found",
      "description": "Instance not found."
    }
  ]
}

=> [NotFound: instance not found]