Graph - Graph Database

Managed graph database powered by ArangoDB for modeling relationships, knowledge graphs, and interconnected data.

Overview

Graph provides a managed graph database optimized for:

  • Knowledge graphs and ontologies
  • Social networks and relationships
  • Recommendation engines
  • Fraud detection
  • Network analysis

Quick Start

import { Tenzro } from '@tenzro/cloud';
const client = new Tenzro({
apiKey: process.env.TENZRO_API_KEY,
projectId: 'your-project-id',
});
// Get graph database by name
const graph = await client.graph.db('knowledge-graph');
// Create nodes
const alice = await graph.createNode(['Person'], {
name: 'Alice',
age: 30
});
const bob = await graph.createNode(['Person'], {
name: 'Bob',
age: 25
});
// Create edges (relationships)
await graph.createEdge(alice.id, bob.id, 'KNOWS', {
since: 2020
});
// Find connected nodes
const friends = await graph.findConnected(alice.id, 'out', 'KNOWS');
console.log(friends.nodes); // [{ id: '...', labels: ['Person'], properties: { name: 'Bob', ... } }]
// Execute raw graph queries (AQL)
const result = await graph.query(`
FOR person IN Person
FILTER person.age >= 25
RETURN person
`);
console.log(result.data);

SDK Reference

Get Database

// Get existing graph database by name
const graph = await client.graph.db('knowledge-graph');

Node Operations

Create Node

const node = await graph.createNode(
['Person', 'Employee'], // Labels
{ name: 'Alice', age: 30 } // Properties
);

Find Nodes

// Find all nodes with label
const people = await graph.findNodes('Person');
// Find nodes with filters
const adults = await graph.findNodes('Person', {
age: { $gte: 18 }
});

Delete Node

await graph.deleteNode(nodeId);

Edge Operations

Create Edge

const edge = await graph.createEdge(
startNodeId,
endNodeId,
'KNOWS', // Edge type
{ since: 2020 } // Properties
);

Find Connected Nodes

const result = await graph.findConnected(
nodeId,
'out', // 'in', 'out', or 'both'
'KNOWS', // Optional: edge type filter
2 // Optional: traversal depth
);
// Returns: { nodes: GraphNode[], edges: GraphEdge[] }

Delete Edge

await graph.deleteEdge(edgeId);

Raw Query

const result = await graph.query(
'FOR p IN Person FILTER p.age > @minAge RETURN p',
{ minAge: 18 } // Bind variables
);
// Returns: { data: any, executionTimeMs: number }

AQL Query Language

ArangoDB uses AQL (ArangoDB Query Language), similar to SQL but designed for graphs:

Basic Queries

// Get all documents
FOR doc IN users
RETURN doc
// Filter documents
FOR user IN users
FILTER user.age >= 18
RETURN user
// Sort and limit
FOR user IN users
SORT user.created_at DESC
LIMIT 10
RETURN user
// Project specific fields
FOR user IN users
RETURN { name: user.name, email: user.email }

Graph Traversals

// Find direct connections (1 hop)
FOR vertex IN 1..1 OUTBOUND 'users/user1' follows
RETURN vertex
// Find all connections (up to 3 hops)
FOR vertex, edge, path IN 1..3 OUTBOUND 'users/user1' follows
RETURN { user: vertex.name, distance: LENGTH(path.edges) }
// Bidirectional traversal
FOR vertex IN 1..2 ANY 'users/user1' knows
RETURN DISTINCT vertex
// Shortest path
FOR path IN OUTBOUND SHORTEST_PATH 'users/user1' TO 'users/user100' follows
RETURN path.vertices[*].name

Aggregations

// Count and group
FOR user IN users
COLLECT city = user.city WITH COUNT INTO count
RETURN { city, count }
// Sum and average
FOR order IN orders
COLLECT user = order.user_id AGGREGATE total = SUM(order.amount)
RETURN { user, total }

Use Cases

Knowledge Graph

const graph = await client.graph.db('knowledge-graph');
// Create entities
const apple = await graph.createNode(['Company'], {
name: 'Apple Inc.',
industry: 'Technology'
});
const tech = await graph.createNode(['Industry'], {
name: 'Technology',
sector: 'IT'
});
// Create relationship
await graph.createEdge(apple.id, tech.id, 'BELONGS_TO', {
since: 1976
});
// Query: Find all companies in technology
const result = await graph.query(`
FOR industry IN Industry
FILTER industry.name == 'Technology'
FOR company IN 1..1 INBOUND industry BELONGS_TO
RETURN company.name
`);
console.log(result.data); // ['Apple Inc.', ...]

Recommendation Engine

// Find products bought by similar users
const { data } = await tenzro.graph.query(graphDbId, `
LET userProducts = (
FOR product IN 1..1 OUTBOUND @userId purchases
RETURN product._key
)
FOR similarUser IN users
FILTER similarUser._key != @userId
LET commonProducts = (
FOR product IN 1..1 OUTBOUND similarUser purchases
FILTER product._key IN userProducts
RETURN 1
)
FILTER LENGTH(commonProducts) >= 3
FOR recommendation IN 1..1 OUTBOUND similarUser purchases
FILTER recommendation._key NOT IN userProducts
COLLECT product = recommendation WITH COUNT INTO score
SORT score DESC
LIMIT 10
RETURN { product: product.name, score }
`, { userId: 'users/user1' });

Social Network

// Find friends of friends (not already connected)
const { data } = await tenzro.graph.query(graphDbId, `
LET directFriends = (
FOR friend IN 1..1 ANY @userId follows
RETURN friend._key
)
FOR fof IN 2..2 ANY @userId follows
FILTER fof._key != @userId
FILTER fof._key NOT IN directFriends
COLLECT person = fof WITH COUNT INTO mutualCount
SORT mutualCount DESC
LIMIT 20
RETURN {
name: person.name,
mutualFriends: mutualCount
}
`, { userId: 'users/user1' });

Bind Variables

Always use bind variables for user input to prevent injection:

// Good - using bind variables
const { data } = await tenzro.graph.query(graphDbId, `
FOR user IN users
FILTER user.email == @email
RETURN user
`, { email: userInput });
// Bad - string interpolation (vulnerable)
// Don't do this:
// `FOR user IN users FILTER user.email == '${userInput}' RETURN user`

Best Practices

  • Use document collections for nodes: Store entity data in document collections
  • Use edge collections for relationships: Edges must have _from and _to fields
  • Index traversal start points: Create indexes on _from and _to for edge collections
  • Limit traversal depth: Use specific depths (1..3) instead of unbounded traversals
  • Use bind variables: Always parameterize user input
  • Batch mutations: Group multiple inserts/updates in single queries

Limits

ResourceLimit
Max collections per database1000
Max documents per collection100 million
Max traversal depth10
Query timeout60 seconds
Max result size100 MB