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';const tenzro = new Tenzro({ apiKey: 'your-api-key' });// Create a graph databaseconst db = await tenzro.graph.create({projectId: 'project-id',db_name: 'knowledge-graph',backend: 'arangodb',});// Create collections (nodes)await tenzro.graph.mutate(db.graph_db_id, `db._createDocumentCollection('users');db._createDocumentCollection('products');db._createEdgeCollection('purchases');`);// Insert nodesawait tenzro.graph.mutate(db.graph_db_id, `db.users.insert({ _key: 'user1', name: 'Alice', age: 30 });db.users.insert({ _key: 'user2', name: 'Bob', age: 25 });db.products.insert({ _key: 'prod1', name: 'Widget', price: 29.99 });`);// Create relationships (edges)await tenzro.graph.mutate(db.graph_db_id, `db.purchases.insert({_from: 'users/user1',_to: 'products/prod1',date: '2024-01-15',quantity: 2});`);// Query the graphconst { data } = await tenzro.graph.query(db.graph_db_id, `FOR user IN usersFOR product IN 1..1 OUTBOUND user purchasesRETURN { user: user.name, bought: product.name }`);console.log(data); // [{ user: 'Alice', bought: 'Widget' }]
SDK Reference
Create Database
const db = await tenzro.graph.create({projectId: string,db_name: string,backend: 'arangodb', // Currently supported backenddescription?: string,});
Query
const result = await tenzro.graph.query(graphDbId,query: string, // AQL queryvariables?: Record<string, any> // Bind variables);// Returns: { data: any, backend: 'arangodb' }
Mutate
const result = await tenzro.graph.mutate(graphDbId,mutation: string, // AQL mutationvariables?: Record<string, any>);
AQL Query Language
ArangoDB uses AQL (ArangoDB Query Language), similar to SQL but designed for graphs:
Basic Queries
// Get all documentsFOR doc IN usersRETURN doc// Filter documentsFOR user IN usersFILTER user.age >= 18RETURN user// Sort and limitFOR user IN usersSORT user.created_at DESCLIMIT 10RETURN user// Project specific fieldsFOR user IN usersRETURN { name: user.name, email: user.email }
Graph Traversals
// Find direct connections (1 hop)FOR vertex IN 1..1 OUTBOUND 'users/user1' followsRETURN vertex// Find all connections (up to 3 hops)FOR vertex, edge, path IN 1..3 OUTBOUND 'users/user1' followsRETURN { user: vertex.name, distance: LENGTH(path.edges) }// Bidirectional traversalFOR vertex IN 1..2 ANY 'users/user1' knowsRETURN DISTINCT vertex// Shortest pathFOR path IN OUTBOUND SHORTEST_PATH 'users/user1' TO 'users/user100' followsRETURN path.vertices[*].name
Aggregations
// Count and groupFOR user IN usersCOLLECT city = user.city WITH COUNT INTO countRETURN { city, count }// Sum and averageFOR order IN ordersCOLLECT user = order.user_id AGGREGATE total = SUM(order.amount)RETURN { user, total }
Use Cases
Knowledge Graph
// Create schema for knowledge graphawait tenzro.graph.mutate(graphDbId, `db._createDocumentCollection('entities');db._createDocumentCollection('concepts');db._createEdgeCollection('relations');`);// Add entities and relationshipsawait tenzro.graph.mutate(graphDbId, `LET apple = (INSERT { name: 'Apple Inc.', type: 'company' } INTO entities RETURN NEW)LET tech = (INSERT { name: 'Technology', type: 'industry' } INTO concepts RETURN NEW)INSERT { _from: apple[0]._id, _to: tech[0]._id, type: 'belongs_to' } INTO relations`);// Query: Find all companies in technologyconst { data } = await tenzro.graph.query(graphDbId, `FOR concept IN conceptsFILTER concept.name == 'Technology'FOR entity IN 1..1 INBOUND concept relationsFILTER entity.type == 'company'RETURN entity.name`);
Recommendation Engine
// Find products bought by similar usersconst { data } = await tenzro.graph.query(graphDbId, `LET userProducts = (FOR product IN 1..1 OUTBOUND @userId purchasesRETURN product._key)FOR similarUser IN usersFILTER similarUser._key != @userIdLET commonProducts = (FOR product IN 1..1 OUTBOUND similarUser purchasesFILTER product._key IN userProductsRETURN 1)FILTER LENGTH(commonProducts) >= 3FOR recommendation IN 1..1 OUTBOUND similarUser purchasesFILTER recommendation._key NOT IN userProductsCOLLECT product = recommendation WITH COUNT INTO scoreSORT score DESCLIMIT 10RETURN { 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 followsRETURN friend._key)FOR fof IN 2..2 ANY @userId followsFILTER fof._key != @userIdFILTER fof._key NOT IN directFriendsCOLLECT person = fof WITH COUNT INTO mutualCountSORT mutualCount DESCLIMIT 20RETURN {name: person.name,mutualFriends: mutualCount}`, { userId: 'users/user1' });
Bind Variables
Always use bind variables for user input to prevent injection:
// Good - using bind variablesconst { data } = await tenzro.graph.query(graphDbId, `FOR user IN usersFILTER user.email == @emailRETURN 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
| Resource | Limit |
|---|---|
| Max collections per database | 1000 |
| Max documents per collection | 100 million |
| Max traversal depth | 10 |
| Query timeout | 60 seconds |
| Max result size | 100 MB |