Modernizing from PostgreSQL to Serverless with Fauna (Part 1)

Introduction

How different is Fauna from Postgres?

The similarities:

The differences:

Terminology mapping:

From DVD rental business to the next Netflix

Creating a new database

Sign up

Create the database

Multiple databases or single database?

One-to-Many relations

Creating the language collection

CreateCollection({name: "language"})

Creating a language document

Create(
Collection("language"),
{
data: {
name: "English"
}
}
)

Creating the film documents

CreateCollection({name: "film"})
Create(
Collection("film"),
{
data: {
title: "Academy Dinosaur",
language: {
spoken: Ref(Collection("language"), "288878259769180673"),
subtitles: Ref(Collection("language"), "288878259769180673")
}
}
}
)
Create(
Collection("film"),
{
data: {
title: "Academy Dinosaur",
language: {
spoken: { name: "English" },
subtitles: { name: "English" }
}
}
}
)

Embedding vs normalized data

Denormalization is not a workaround. It’s a choice.

Indexing works equally well on nested values and arrays

{
data: {
title: "Academy Dinosaur",
language: {
spoken: [{ name: "English" }, { name: "French" }],
subtitles: { name: "English" }
}
}
}

Querying one collection

Select IDs

SELECT id FROM film
Documents(Collection("film"))
{
"@set": {
documents: Collection("film")
}
}

What is FQL?

var a = Documents(Collection("film"))
a

Pagination

Paginate(Documents(Collection("film")))
{
data: [
Ref(Collection("film"), "288801457307648519"),
Ref(Collection("film"), "288877928042725889")
]
}
Paginate(Documents(Collection("film")), {size: 1})

{
{
after: [Ref(Collection("film"), "288877928042725889")],
data: [Ref(Collection("film"), "288801457307648519")]
}
}
Paginate(Documents(Collection("film")), {
size: 1,
after: [Ref(Collection("film"), "288877928042725889")]
})
SELECT * FROM film
LIMIT 64

Select *

Map(
Paginate(Documents(Collection("film"))),
Lambda(["ref"], Get(Var("ref")))
)
function SelectAll(name) {
return Map(
Paginate(Documents(Collection(name))),
Lambda(["ref"], Get(Var("ref")))
)
}

SelectAll("film")

Querying a one-to-many relation

Querying embedded documents

Map(
Paginate(Documents(Collection("film"))),
Lambda(["ref"], Get(Var("ref")))
)
{
ref: Ref(Collection("film"), "289321621957640705"),
ts: 1612177450050000,
data: {
title: "Academy Dinosaur",
language: {
spoken: {
name: "English"
},
subtitles: {
name: "English"
}
}
}
}

Querying normalized data with native references

{
data: {
title: "Academy Dinosaur",
language: {
spoken: Ref(Collection("language"), "288878259769180673"),
subtitles: Ref(Collection("language"), "288878259769180673")
}
}
}
SELECT * FROM film 
JOIN "language" as spol ON spol.language_id = film.spoken_language_id
JOIN "language" as subl ON subl.language_id = film.subtitles_language_id
LIMIT 64
Map(
Paginate(Documents(Collection("film"))),
Lambda(["ref"], Get(Var("ref")))
)
Map(
Paginate(Documents(Collection("film"))),
Lambda(["filmRef"],
Let({
film: Get(Var("filmRef"))
},
// for now, we just return the film variable.
Var("film")
))
)
Map(
Paginate(Documents(Collection("film"))),
Lambda(["filmRef"],
Let({
film: Get(Var("filmRef")),
spokenLang: Get(Select(['data', 'language', 'spoken'], Var("film"))),
subLang: Get(Select(['data', 'language', 'subtitles'], Var("film")))
},
// todo
)
)
)
Map(
Paginate(Documents(Collection("film"))),
Lambda(["filmRef"],
Let({
film: Get(Var("filmRef")),
spokenLang: Get(Select(['data', 'language', 'spoken'], Var("film"))),
subLang: Get(Select(['data', 'language', 'subtitles'], Var("film")))
},
// return a JSON object
{
film: Var("film"),
language: {
spoken: Var("spokenLang"),
subtitles: Var("subLang")
}
})
)
)
{
data: [
{
film: {
ref: Ref(Collection("film"), "288980003744383489"),
ts: 1611851657590000,
data: {
title: "Academy Dinosaur",
language: {
spoken: Ref(Collection("language"), "288878259769180673"),
subtitles: Ref(Collection("language"), "288878259769180673")
}
}
},
language: {
spoken: {
ref: Ref(Collection("language"), "288878259769180673"),
ts: 1611754626915000,
data: {
name: "English"
}
},
subtitles: {
ref: Ref(Collection("language"), "288878259769180673"),
ts: 1611754626915000,
data: {
name: "English"
}
}
}
}
]
}

Querying normalized data with regular IDs

Create(
Collection("film"),
{
data: {
title: "Academy Dinosaur",
language: {
spoken: 6,
subtitles: 6
}
}
}
)

Create(
Collection("language"),
{
data: {
id: 6,
name: "English"
}
}
)
CreateIndex({
name: "language_by_id",
source: Collection("language"),
terms: [
{
field: ["data", "id"]
}
],
values: [
{
field: ["ref"]
}
]
})
Map(
Paginate(Documents(Collection("film"))),
Lambda(["filmRef"],
Let({
film: Get(Var("filmRef")),
spokenLangId: Select(['data', 'language', 'spoken'], Var("film")),
subLangId: Select(['data', 'language', 'subtitles'], Var("film")),
spokenLang: Get(Match(Index("language_by_id"), Var("spokenLangId"))),
subLang: Get(Match(Index("language_by_id"), Var("subLangId"))),
},
// and return the values however you want.
)
)
)

Native Fauna references or user-defined IDs?

Create(
Ref(Collection('language'), '6'),
{ name: { title: 'English' } },
)

Conclusion

Note

--

--

Fauna is a distributed document-relational database delivered as a cloud API. Build new or migrate existing applications to Fauna and scale without worrying about operations.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Fauna Inc

Fauna is a distributed document-relational database delivered as a cloud API.