← Tilbage til databaser

ArangoDB

NoSQL

En native multi-model database der kombinerer dokument-, graf- og nøgle-værdi-datamodeller i ét samlet forespørgselssprog.

Beskrivelse

ArangoDB er unik fordi den er en native multi-model database - i stedet for at vælge mellem dokument-, graf- eller nøgle-værdi-database, får du alle tre i én. Data gemmes som JSON-dokumenter i collections, men du kan også definere edges (forbindelser) mellem dokumenter for at lave property graphs. Dette betyder at du kan køre dokumentforespørgsler, graftravereringer og nøgle-værdi-opslag alt sammen i samme database med samme forespørgselssprog (AQL - ArangoDB Query Language). AQL ligner SQL men med udvidelser til graftravereringer og dokumentmanipulation. ArangoDB understøtter ACID-transaktioner, sekundære indekser, fuldtekstsøgning og geospatiale forespørgsler. Den kan deployes som single-server eller distribueret cluster med automatisk sharding og replikering. Foxx er microservices der kører direkte i databasen og giver dig mulighed for at skrive brugerdefinerede API'er i JavaScript. ArangoDB's multi-model tilgang er perfekt til komplekse domæner hvor data naturligt har både hierarkiske (dokumenter) og relationelle/netværks- (grafer) strukturer.

Features

  • Multi-model (dokument, graf, nøgle-værdi)
  • AQL-forespørgselssprog
  • ACID-transaktioner
  • Graftravereringer
  • Fuldtekstsøgning
  • Geospatiale forespørgsler
  • Foxx microservices
  • Distribueret clustering

Query Eksempel

// ArangoDB Query Language (AQL)

// 1. Opret collections
db._create("users");
db._createEdgeCollection("follows");
db._create("posts");

// 2. Indsæt documents
db.users.insert({
  _key: "peter",
  name: "Peter Hansen",
  email: "peter@email.dk",
  age: 30
});

db.users.insert({
  _key: "maria",
  name: "Maria Nielsen",
  email: "maria@email.dk",
  age: 28
});

// 3. Opret edge (graph relation)
db.follows.insert({
  _from: "users/peter",
  _to: "users/maria",
  since: "2024-01-01"
});

// 4. Document query (like MongoDB)
FOR user IN users
  FILTER user.age > 25
  SORT user.name ASC
  RETURN user

// 5. Graph traversal
FOR vertex, edge, path IN 1..3 OUTBOUND "users/peter" follows
  RETURN {
    user: vertex.name,
    connection: edge,
    depth: LENGTH(path.edges)
  }

// 6. Find friends of friends
FOR user IN users
  FILTER user._key == "peter"
  FOR friend IN 2..2 OUTBOUND user follows
    FILTER friend._key != user._key
    RETURN DISTINCT friend.name

// 7. JOIN-like query
FOR post IN posts
  LET author = FIRST(
    FOR user IN users
      FILTER user._key == post.authorId
      RETURN user
  )
  RETURN {
    title: post.title,
    authorName: author.name
  }

// 8. Aggregation
FOR user IN users
  COLLECT ageGroup = FLOOR(user.age / 10) * 10
  AGGREGATE count = LENGTH(1)
  RETURN {
    ageGroup: ageGroup,
    count: count
  }

// 9. Shortest path (graph algorithm)
FOR path IN OUTBOUND SHORTEST_PATH
  "users/peter" TO "users/anders"
  follows
  RETURN path

// 10. Full-text search
FOR doc IN FULLTEXT(posts, "content", "database")
  RETURN doc

// JavaScript Driver
const { Database, aql } = require('arangojs');

const db = new Database({
  url: 'http://localhost:8529'
});
db.useDatabase('mydb');
db.useBasicAuth('root', 'password');

// Insert document
const users = db.collection('users');
await users.save({
  _key: 'john',
  name: 'John Doe',
  email: 'john@email.com'
});

// Query with AQL
const cursor = await db.query(aql`
  FOR user IN users
    FILTER user.age > ${25}
    RETURN user
`);

const result = await cursor.all();
console.log(result);

// Create edge
const follows = db.collection('follows');
await follows.save({
  _from: 'users/peter',
  _to: 'users/john',
  since: new Date().toISOString()
});

// Graph traversal
const traversal = await db.query(aql`
  FOR vertex IN 1..2 OUTBOUND ${'users/peter'} follows
    RETURN vertex.name
`);

const friends = await traversal.all();
console.log(friends);

// Transaction
const trx = await db.beginTransaction({
  write: ['users', 'posts']
});

try {
  await trx.step(() => 
    users.save({ name: 'Transaction User' })
  );
  
  await trx.step(() => 
    db.collection('posts').save({ title: 'Post' })
  );
  
  await trx.commit();
} catch (err) {
  await trx.abort();
}

// Named graph creation
const graph = db.graph('social_network');
await graph.create({
  edgeDefinitions: [{
    collection: 'follows',
    from: ['users'],
    to: ['users']
  }]
});

// Foxx microservice (runs in database)
// manifest.json
{
  "name": "my-api",
  "version": "1.0.0",
  "engines": {
    "arangodb": "^3.0.0"
  }
}

// index.js
const { context } = require('@arangodb/locals');
const router = context.createRouter();

router.get('/users', (req, res) => {
  const users = db._query(
    'FOR user IN users RETURN user'
  ).toArray();
  res.json(users);
});

Anvendelsesområder

  • Sociale netværk (brugere som dokumenter, forbindelser som grafer)
  • Anbefalingsmotorer
  • Svindelregistrering (grafanalyse)
  • Indholdsstyring med komplekse relationer
  • Videngrafer

Fordele

  • Én database for flere datamodeller
  • Kraftfulde graftravererings-kapabiliteter
  • Fleksibelt forespørgselssprog (AQL)
  • ACID-transaktioner på tværs af modeller
  • God ydeevne til både dokument- og grafforespørgsler

Ulemper

  • Mindre community end MongoDB eller Neo4j
  • Indlæringskurve for AQL
  • Overhead fra multi-model support
  • Færre managed cloud-tilbud
  • Dokumentation kan være fragmenteret

Bedst til

  • Sociale netværk med grafrelationer
  • Svindeldetekteringssystemer
  • Anbefalingsmotorer
  • Vidensstyringssystemer
  • Master data management

Ikke anbefalet til

  • Simple CRUD-apps (overkill)
  • Rene nøgle-værdi-arbejdsbyrder (brug Redis)
  • Ren dokumentlagring (brug MongoDB)
  • Rene grafer (brug Neo4j hvis kun graf)
  • Teams uden grafdatabase-erfaring

Relaterede databaser

MongoDBNeo4jOrientDBDgraphJanusGraph