← Tilbage til databaser

Fauna

Cloud

En distribueret dokument-relationel database med global konsistens, GraphQL API og serverløs arkitektur.

Beskrivelse

Fauna er en moderne cloud-database der kombinerer dokumenternes fleksibilitet med relationelle databasers konsistens og forespørgselsevner. Den er helt serverløs - ingen servere at administrere, automatisk skalering og pay-per-use prissætning. Fauna bruger Calvin-protokollen til at opnå distribuerede ACID-transaktioner uden koordineringsoverhead, hvilket giver både stærk konsistens og lav latenstid globalt. Data modelleres som JSON-lignende dokumenter organiseret i collections, men du kan definere relationer, indekser og constraints ligesom i relationelle databaser. Fauna tilbyder flere forespørgselsgrænseflader: FQL (Fauna Query Language - funktionel programmeringsstil), GraphQL (auto-genereret eller brugerdefineret) og en GraphQL-kompatibel API. En unik funktion er temporale forespørgsler - du kan forespørge data som det så ud på et hvilket som helst tidspunkt i fortiden (tidsrejse-forespørgsler). Fauna's sikkerhedsmodel bruger attributbaseret adgangskontrol (ABAC) med brugerdefinerede funktioner, hvilket giver granulære tilladelser. Den kører på flere clouds og regioner for høj tilgængelighed.

Features

  • Distribuerede ACID-transaktioner
  • GraphQL og FQL-forespørgselssprog
  • Temporale forespørgsler (tidsrejse)
  • Global replikering med stærk konsistens
  • Attributbaseret adgangskontrol (ABAC)
  • Automatisk indeksering
  • Serverløs arkitektur
  • Multi-tenancy support

Query Eksempel

// Fauna Query Language (FQL)

// 1. Opret collection
CreateCollection({ name: "users" })
CreateCollection({ name: "posts" })

// 2. Opret indexes
CreateIndex({
  name: "users_by_email",
  source: Collection("users"),
  terms: [{ field: ["data", "email"] }],
  unique: true
})

CreateIndex({
  name: "posts_by_user",
  source: Collection("posts"),
  terms: [{ field: ["data", "userId"] }]
})

// 3. Opret document
Create(
  Collection("users"),
  {
    data: {
      email: "peter@email.dk",
      name: "Peter Hansen",
      createdAt: Time("now")
    }
  }
)

// 4. Find document
Get(
  Match(Index("users_by_email"), "peter@email.dk")
)

// 5. Update document
Update(
  Ref(Collection("users"), "12345"),
  {
    data: {
      name: "Peter H. Hansen"
    }
  }
)

// 6. Query med relations
Let(
  {
    userRef: Match(Index("users_by_email"), "peter@email.dk"),
    user: Get(Var("userRef")),
    posts: Map(
      Paginate(Match(Index("posts_by_user"), Select(["ref"], Var("user")))),
      Lambda("postRef", Get(Var("postRef")))
    )
  },
  {
    user: Var("user"),
    posts: Var("posts")
  }
)

// 7. Transaction
Do(
  Create(
    Collection("users"),
    { data: { email: "new@email.dk", name: "New User" } }
  ),
  Create(
    Collection("posts"),
    { data: { userId: "123", title: "First Post" } }
  )
)

// JavaScript Driver
import faunadb from 'faunadb'

const q = faunadb.query
const client = new faunadb.Client({
  secret: 'your-secret-key'
})

// Create
const result = await client.query(
  q.Create(
    q.Collection('users'),
    {
      data: {
        email: 'js@email.dk',
        name: 'JavaScript User'
      }
    }
  )
)

// Read
const user = await client.query(
  q.Get(
    q.Match(q.Index('users_by_email'), 'js@email.dk')
  )
)

// Update
await client.query(
  q.Update(
    q.Ref(q.Collection('users'), user.ref.id),
    { data: { name: 'Updated Name' } }
  )
)

// Delete
await client.query(
  q.Delete(q.Ref(q.Collection('users'), user.ref.id))
)

// Temporal query (time-travel!)
const historicalData = await client.query(
  q.At(
    q.Time('2024-01-01T00:00:00Z'),
    q.Get(q.Ref(q.Collection('users'), '12345'))
  )
)

// GraphQL Schema
type User {
  email: String! @unique
  name: String!
  posts: [Post!] @relation
}

type Post {
  title: String!
  content: String
  author: User!
  published: Boolean!
}

type Query {
  allUsers: [User!]
  userByEmail(email: String!): User
}

// GraphQL Query
query {
  userByEmail(email: "peter@email.dk") {
    name
    email
    posts {
      data {
        title
        published
      }
    }
  }
}

// GraphQL Mutation
mutation {
  createUser(data: {
    email: "graphql@email.dk"
    name: "GraphQL User"
  }) {
    _id
    email
    name
  }
}

// React eksempel
import { useQuery, useMutation } from '@apollo/client'
import { gql } from '@apollo/client'

const GET_USERS = gql`
  query GetUsers {
    allUsers {
      data {
        _id
        name
        email
      }
    }
  }
`

function UserList() {
  const { loading, error, data } = useQuery(GET_USERS)

  if (loading) return <p>Loading...</p>
  if (error) return <p>Error: {error.message}</p>

  return (
    <ul>
      {data.allUsers.data.map(user => (
        <li key={user._id}>{user.name} - {user.email}</li>
      ))}
    </ul>
  )
}

Anvendelsesområder

  • Jamstack-websites og static site generators
  • Serverløse applikationer
  • Globale multi-region apps
  • Realtids-samarbejdsapplikationer
  • E-handel med lagerstyring

Fordele

  • Stærk konsistens globalt
  • Ingen servere at administrere
  • Native GraphQL-support
  • Temporale forespørgsler (indbygget versionering)
  • Fleksibel datamodel (dokument + relationel)

Ulemper

  • FQL har stejl indlæringskurve
  • Kan blive dyrt ved høj volumen
  • Leverandørbinding
  • Mindre community end etablerede databaser
  • Fejlfinding af forespørgsler kan være udfordrende

Bedst til

  • Jamstack-sites (Next.js, Gatsby)
  • Serverløse funktioner
  • Globale applikationer med konsistenskrav
  • GraphQL-first applikationer
  • Apps der har brug for revisionsspor (temporale)

Ikke anbefalet til

  • Budgetbevidste projekter
  • Simple CRUD-apps (overkill)
  • Teams uden funktionel programmeringserfaring
  • Applikationer med meget høj skrivevolumen
  • Realtidsspil (latenstidsbegrænsninger)

Relaterede databaser

MongoDBDynamoDBSupabaseFirebaseCockroachDB