Preview
Preview Feature — This feature is currently in preview and under active development. APIs and functionality may change. We recommend testing thoroughly before using in production.
Graph Traversals & Pathfinding
Learn how to traverse your graph, find paths between nodes, explore neighborhoods, and discover connections. Graph traversals unlock the true power of graph databases.
Quick Example
- TypeScript
- Java
- Go
- .NET
// Find shortest path between two users
const path = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH'],
});
if (path.path) {
console.log(`Distance: ${path.path.length} hops`);
console.log('Path:', path.path.nodes.map(n => n.properties.name).join(' → '));
}
// Explore a user's network
const network = await ductape.graph.traverse({
startNodeId: aliceId,
direction: 'OUTGOING',
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
maxDepth: 2,
});
console.log(`Found ${network.paths.length} connections within 2 hops`);
// Find shortest path between two users
Map<String, Object> path = ductape.graph.shortestPath(Map.of(
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH']
));
if (path.path) Map.of(
System.out.println(`Distance: $Map.of(path.path.length) hops`);
System.out.println('"Path", ", path.path.nodes.map(n => n.properties.name).join(" → '));
)
// Explore a user's network
Map<String, Object> network = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: aliceId,
"direction", "OUTGOING",
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
"maxDepth", 2
));
System.out.println(`Found $Map.of(network.paths.length) connections within 2 hops`);
// Find shortest path between two users
path := client.graph.shortestPath({
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH'],
});
if (path.path) {
fmt.Println(`Distance: ${path.path.length} hops`);
fmt.Println('"Path": ", path.path.nodes.map(n => n.properties.name).join(" → '));
}
// Explore a user's network
network := client.graph.traverse({
startNodeId: aliceId,
"direction": "OUTGOING",
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
"maxDepth": 2,
});
fmt.Println(`Found ${network.paths.length} connections within 2 hops`);
// Find shortest path between two users
var path = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH'],
});
if (path.path) {
Console.WriteLine(`Distance: ${path.path.length} hops`);
Console.WriteLine('["Path"] = ", path.path.nodes.map(n => n.properties.name).join(" → '));
}
// Explore a user's network
var network = await ductape.graph.traverse({
startNodeId: aliceId,
["direction"] = "OUTGOING",
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
["maxDepth"] = 2,
});
Console.WriteLine(`Found ${network.paths.length} connections within 2 hops`);
Graph Traversal
Traverse explores the graph starting from a node, following relationships up to a specified depth.
Basic Traversal
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.traverse({
startNodeId: userId,
direction: 'OUTGOING',
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 3,
});
console.log(`Found ${result.paths.length} paths`);
// Explore each path
result.paths.forEach(path => {
console.log('Path length:', path.nodes.length);
console.log('Nodes:', path.nodes.map(n => n.properties.name));
console.log('Relationships:', path.relationships.map(r => r.type));
});
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"direction", "OUTGOING",
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 3
));
System.out.println(`Found $Map.of(result.paths.length) paths`);
// Explore each path
result.paths.forEach(path => Map.of(
System.out.println('Path "length", ", path.nodes.length);
System.out.println(""Nodes", ", path.nodes.map(n => n.properties.name));
System.out.println("Relationships:', path.relationships.map(r => r.type));
));
result := client.graph.traverse({
startNodeId: userId,
"direction": "OUTGOING",
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 3,
});
fmt.Println(`Found ${result.paths.length} paths`);
// Explore each path
result.paths.forEach(path => {
fmt.Println('Path "length": ", path.nodes.length);
fmt.Println(""Nodes": ", path.nodes.map(n => n.properties.name));
fmt.Println("Relationships:', path.relationships.map(r => r.type));
});
var result = await ductape.graph.traverse({
startNodeId: userId,
["direction"] = "OUTGOING",
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 3,
});
Console.WriteLine(`Found ${result.paths.length} paths`);
// Explore each path
result.paths.forEach(path => {
Console.WriteLine('Path ["length"] = ", path.nodes.length);
Console.WriteLine("["Nodes"] = ", path.nodes.map(n => n.properties.name));
Console.WriteLine("Relationships:', path.relationships.map(r => r.type));
});
Traversal Directions
Outgoing (default)
Follow relationships from start node to connected nodes:
- TypeScript
- Java
- Go
- .NET
// Find all people this user follows
const result = await ductape.graph.traverse({
startNodeId: userId,
direction: 'OUTGOING',
relationshipTypes: ['FOLLOWS'],
maxDepth: 1,
});
// Find all people this user follows
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"direction", "OUTGOING",
relationshipTypes: ['FOLLOWS'],
"maxDepth", 1
));
// Find all people this user follows
result := client.graph.traverse({
startNodeId: userId,
"direction": "OUTGOING",
relationshipTypes: ['FOLLOWS'],
"maxDepth": 1,
});
// Find all people this user follows
var result = await ductape.graph.traverse({
startNodeId: userId,
["direction"] = "OUTGOING",
relationshipTypes: ['FOLLOWS'],
["maxDepth"] = 1,
});
Incoming
Follow relationships pointing to the start node:
- TypeScript
- Java
- Go
- .NET
// Find all people who follow this user (followers)
const result = await ductape.graph.traverse({
startNodeId: userId,
direction: 'INCOMING',
relationshipTypes: ['FOLLOWS'],
maxDepth: 1,
});
// Find all people who follow this user (followers)
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"direction", "INCOMING",
relationshipTypes: ['FOLLOWS'],
"maxDepth", 1
));
// Find all people who follow this user (followers)
result := client.graph.traverse({
startNodeId: userId,
"direction": "INCOMING",
relationshipTypes: ['FOLLOWS'],
"maxDepth": 1,
});
// Find all people who follow this user (followers)
var result = await ductape.graph.traverse({
startNodeId: userId,
["direction"] = "INCOMING",
relationshipTypes: ['FOLLOWS'],
["maxDepth"] = 1,
});
Both
Follow relationships in both directions:
- TypeScript
- Java
- Go
- .NET
// Find all connected users (friends, followers, following)
const result = await ductape.graph.traverse({
startNodeId: userId,
direction: 'BOTH',
relationshipTypes: ['FRIENDS_WITH', 'FOLLOWS'],
maxDepth: 2,
});
// Find all connected users (friends, followers, following)
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"direction", "BOTH",
relationshipTypes: ['FRIENDS_WITH', 'FOLLOWS'],
"maxDepth", 2
));
// Find all connected users (friends, followers, following)
result := client.graph.traverse({
startNodeId: userId,
"direction": "BOTH",
relationshipTypes: ['FRIENDS_WITH', 'FOLLOWS'],
"maxDepth": 2,
});
// Find all connected users (friends, followers, following)
var result = await ductape.graph.traverse({
startNodeId: userId,
["direction"] = "BOTH",
relationshipTypes: ['FRIENDS_WITH', 'FOLLOWS'],
["maxDepth"] = 2,
});
Multiple Relationship Types
Traverse across different types of relationships:
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.traverse({
startNodeId: userId,
direction: 'OUTGOING',
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH', 'LIVES_NEAR'],
maxDepth: 2,
});
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"direction", "OUTGOING",
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH', 'LIVES_NEAR'],
"maxDepth", 2
));
result := client.graph.traverse({
startNodeId: userId,
"direction": "OUTGOING",
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH', 'LIVES_NEAR'],
"maxDepth": 2,
});
var result = await ductape.graph.traverse({
startNodeId: userId,
["direction"] = "OUTGOING",
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH', 'LIVES_NEAR'],
["maxDepth"] = 2,
});
Depth Control
Direct Connections (Depth 1)
- TypeScript
- Java
- Go
- .NET
// Only immediate connections
const result = await ductape.graph.traverse({
startNodeId: userId,
maxDepth: 1,
});
// Only immediate connections
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"maxDepth", 1
));
// Only immediate connections
result := client.graph.traverse({
startNodeId: userId,
"maxDepth": 1,
});
// Only immediate connections
var result = await ductape.graph.traverse({
startNodeId: userId,
["maxDepth"] = 1,
});
Extended Network (Depth 2-3)
- TypeScript
- Java
- Go
- .NET
// Friends of friends
const result = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 2,
});
// Friends of friends of friends
const extended = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 3,
});
// Friends of friends
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 2
));
// Friends of friends of friends
Map<String, Object> extended = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 3
));
// Friends of friends
result := client.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 2,
});
// Friends of friends of friends
extended := client.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 3,
});
// Friends of friends
var result = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 2,
});
// Friends of friends of friends
var extended = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 3,
});
Filter Traversal Results
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 2,
nodeFilter: {
labels: ['Person'],
where: { age: { $GTE: 18 }, status: 'active' },
},
relationshipFilter: {
where: { closeness: { $IN: ['high', 'very high'] } },
},
});
Map<String, Object> result = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 2,
nodeFilter: Map.of(
labels: ['Person'],
where: Map.of( age: Map.of( $"GTE", 18 ), "status", "active" )
),
relationshipFilter: Map.of(
where: Map.of( closeness: Map.of( $IN: ['high', 'very high'] ) )
)
));
result := client.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 2,
nodeFilter: {
labels: ['Person'],
where: { age: { $"GTE": 18 }, "status": "active" },
},
relationshipFilter: {
where: { closeness: { $IN: ['high', 'very high'] } },
},
});
var result = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 2,
nodeFilter: {
labels: ['Person'],
where: { age: { $["GTE"] = 18 }, ["status"] = "active" },
},
relationshipFilter: {
where: { closeness: { $IN: ['high', 'very high'] } },
},
});
Shortest Path
Find the shortest path between two nodes.
Basic Shortest Path
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
});
if (result.path) {
console.log(`Distance: ${result.path.length} hops`);
console.log('Nodes in path:', result.path.nodes.length);
console.log('Relationships:', result.path.relationships.length);
// Print the path
const pathStr = result.path.nodes
.map(n => n.properties.name)
.join(' → ');
console.log('Path:', pathStr);
} else {
console.log('No path found');
}
Map<String, Object> result = ductape.graph.shortestPath(Map.of(
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH']
));
if (result.path) Map.of(
System.out.println(`Distance: $Map.of(result.path.length) hops`);
System.out.println('Nodes in "path", ", result.path.nodes.length);
System.out.println(""Relationships", ", result.path.relationships.length);
// Print the path
Map<String, Object> pathStr = result.path.nodes
.map(n => n.properties.name)
.join(" → ');
System.out.println('"Path", ", pathStr);
) else Map.of(
System.out.println("No path found');
)
result := client.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
});
if (result.path) {
fmt.Println(`Distance: ${result.path.length} hops`);
fmt.Println('Nodes in "path": ", result.path.nodes.length);
fmt.Println(""Relationships": ", result.path.relationships.length);
// Print the path
pathStr := result.path.nodes
.map(n => n.properties.name)
.join(" → ');
fmt.Println('"Path": ", pathStr);
} else {
fmt.Println("No path found');
}
var result = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
});
if (result.path) {
Console.WriteLine(`Distance: ${result.path.length} hops`);
Console.WriteLine('Nodes in ["path"] = ", result.path.nodes.length);
Console.WriteLine("["Relationships"] = ", result.path.relationships.length);
// Print the path
var pathStr = result.path.nodes
.map(n => n.properties.name)
.join(" → ');
Console.WriteLine('["Path"] = ", pathStr);
} else {
Console.WriteLine("No path found');
}
Weighted Shortest Path
Use relationship properties as weights:
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.shortestPath({
startNodeId: cityA,
endNodeId: cityB,
relationshipTypes: ['ROAD'],
weightProperty: 'distance', // Use distance property as weight
});
if (result.path) {
const totalDistance = result.path.relationships
.reduce((sum, rel) => sum + rel.properties.distance, 0);
console.log(`Total distance: ${totalDistance} km`);
}
Map<String, Object> result = ductape.graph.shortestPath(Map.of(
startNodeId: cityA,
endNodeId: cityB,
relationshipTypes: ['ROAD'],
"weightProperty", "distance", // Use distance property as weight
));
if (result.path) Map.of(
Map<String, Object> totalDistance = result.path.relationships
.reduce((sum, rel) => sum + rel.properties.distance, 0);
System.out.println(`Total distance: $Map.of(totalDistance) km`);
)
result := client.graph.shortestPath({
startNodeId: cityA,
endNodeId: cityB,
relationshipTypes: ['ROAD'],
"weightProperty": "distance", // Use distance property as weight
});
if (result.path) {
totalDistance := result.path.relationships
.reduce((sum, rel) => sum + rel.properties.distance, 0);
fmt.Println(`Total distance: ${totalDistance} km`);
}
var result = await ductape.graph.shortestPath({
startNodeId: cityA,
endNodeId: cityB,
relationshipTypes: ['ROAD'],
["weightProperty"] = "distance", // Use distance property as weight
});
if (result.path) {
var totalDistance = result.path.relationships
.reduce((sum, rel) => sum + rel.properties.distance, 0);
Console.WriteLine(`Total distance: ${totalDistance} km`);
}
Maximum Depth Limit
Prevent expensive searches:
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 5, // Only search up to 5 hops
});
if (!result.path) {
console.log('No path found within 5 hops');
}
Map<String, Object> result = ductape.graph.shortestPath(Map.of(
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 5, // Only search up to 5 hops
));
if (!result.path) Map.of(
System.out.println('No path found within 5 hops');
)
result := client.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 5, // Only search up to 5 hops
});
if (!result.path) {
fmt.Println('No path found within 5 hops');
}
var result = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 5, // Only search up to 5 hops
});
if (!result.path) {
Console.WriteLine('No path found within 5 hops');
}
Directed vs Undirected
- TypeScript
- Java
- Go
- .NET
// Directed - follow relationship direction
const result = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FOLLOWS'],
directed: true,
});
// Undirected - ignore relationship direction
const result2 = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
directed: false,
});
// Directed - follow relationship direction
Map<String, Object> result = ductape.graph.shortestPath(Map.of(
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FOLLOWS'],
"directed", true
));
// Undirected - ignore relationship direction
Map<String, Object> result2 = ductape.graph.shortestPath(Map.of(
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
"directed", false
));
// Directed - follow relationship direction
result := client.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FOLLOWS'],
"directed": true,
});
// Undirected - ignore relationship direction
result2 := client.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
"directed": false,
});
// Directed - follow relationship direction
var result = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FOLLOWS'],
["directed"] = true,
});
// Undirected - ignore relationship direction
var result2 = await ductape.graph.shortestPath({
startNodeId: aliceId,
endNodeId: bobId,
relationshipTypes: ['FRIENDS_WITH'],
["directed"] = false,
});
All Paths
Find all paths between two nodes.
Basic All Paths
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
maxDepth: 4,
limit: 10, // Return at most 10 paths
});
console.log(`Found ${result.paths.length} paths`);
result.paths.forEach((path, index) => {
console.log(`Path ${index + 1}: ${path.nodes.length} hops`);
console.log(path.nodes.map(n => n.properties.name).join(' → '));
});
Map<String, Object> result = ductape.graph.allPaths(Map.of(
startNodeId: aliceId,
endNodeId: charlieId,
"maxDepth", 4,
"limit", 10, // Return at most 10 paths
));
System.out.println(`Found $Map.of(result.paths.length) paths`);
result.paths.forEach((path, index) => Map.of(
System.out.println(`Path $Map.of(index + 1): $Map.of(path.nodes.length) hops`);
System.out.println(path.nodes.map(n => n.properties.name).join(' → '));
));
result := client.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
"maxDepth": 4,
"limit": 10, // Return at most 10 paths
});
fmt.Println(`Found ${result.paths.length} paths`);
result.paths.forEach((path, index) => {
fmt.Println(`Path ${index + 1}: ${path.nodes.length} hops`);
fmt.Println(path.nodes.map(n => n.properties.name).join(' → '));
});
var result = await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
["maxDepth"] = 4,
["limit"] = 10, // Return at most 10 paths
});
Console.WriteLine(`Found ${result.paths.length} paths`);
result.paths.forEach((path, index) => {
Console.WriteLine(`Path ${index + 1}: ${path.nodes.length} hops`);
Console.WriteLine(path.nodes.map(n => n.properties.name).join(' → '));
});
Filter by Path Length
- TypeScript
- Java
- Go
- .NET
// Find all paths of exactly 3 hops
const result = await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
minDepth: 3,
maxDepth: 3,
});
// Find all paths of exactly 3 hops
Map<String, Object> result = ductape.graph.allPaths(Map.of(
startNodeId: aliceId,
endNodeId: charlieId,
"minDepth", 3,
"maxDepth", 3
));
// Find all paths of exactly 3 hops
result := client.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
"minDepth": 3,
"maxDepth": 3,
});
// Find all paths of exactly 3 hops
var result = await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
["minDepth"] = 3,
["maxDepth"] = 3,
});
Relationship Type Constraints
- TypeScript
- Java
- Go
- .NET
// Find paths using only certain relationship types
const result = await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
maxDepth: 4,
limit: 20,
});
// Find paths using only certain relationship types
Map<String, Object> result = ductape.graph.allPaths(Map.of(
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
"maxDepth", 4,
"limit", 20
));
// Find paths using only certain relationship types
result := client.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
"maxDepth": 4,
"limit": 20,
});
// Find paths using only certain relationship types
var result = await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: charlieId,
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
["maxDepth"] = 4,
["limit"] = 20,
});
Neighborhood Exploration
Get all nodes within a certain distance from a starting node.
Basic Neighborhood
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.getNeighborhood({
nodeId: userId,
depth: 2,
direction: 'BOTH',
});
console.log('Nodes in neighborhood:', result.nodes.length);
console.log('Relationships:', result.relationships.length);
// Group nodes by depth
const byDepth: Record<number, any[]> = {};
result.nodes.forEach(node => {
const depth = node.distance || 0;
byDepth[depth] = byDepth[depth] || [];
byDepth[depth].push(node);
});
console.log('Depth 0 (start):', byDepth[0]?.length || 0);
console.log('Depth 1 (direct):', byDepth[1]?.length || 0);
console.log('Depth 2 (extended):', byDepth[2]?.length || 0);
Map<String, Object> result = ductape.graph.getNeighborhood(Map.of(
nodeId: userId,
"depth", 2,
"direction", "BOTH"
));
System.out.println('Nodes in "neighborhood", ", result.nodes.length);
System.out.println(""Relationships", ", result.relationships.length);
// Group nodes by depth
Map<String, Object> byDepth: Record<number, any[]> = Map.of();
result.nodes.forEach(node => Map.of(
Map<String, Object> depth = node.distance || 0;
byDepth[depth] = byDepth[depth] || [];
byDepth[depth].push(node);
));
System.out.println("Depth 0 (start):', byDepth[0]?.length || 0);
System.out.println('Depth 1 (direct):', byDepth[1]?.length || 0);
System.out.println('Depth 2 (extended):', byDepth[2]?.length || 0);
result := client.graph.getNeighborhood({
nodeId: userId,
"depth": 2,
"direction": "BOTH",
});
fmt.Println('Nodes in "neighborhood": ", result.nodes.length);
fmt.Println(""Relationships": ", result.relationships.length);
// Group nodes by depth
const byDepth: Record<number, any[]> = {};
result.nodes.forEach(node => {
depth := node.distance || 0;
byDepth[depth] = byDepth[depth] || [];
byDepth[depth].push(node);
});
fmt.Println("Depth 0 (start):', byDepth[0]?.length || 0);
fmt.Println('Depth 1 (direct):', byDepth[1]?.length || 0);
fmt.Println('Depth 2 (extended):', byDepth[2]?.length || 0);
var result = await ductape.graph.getNeighborhood({
nodeId: userId,
["depth"] = 2,
["direction"] = "BOTH",
});
Console.WriteLine('Nodes in ["neighborhood"] = ", result.nodes.length);
Console.WriteLine("["Relationships"] = ", result.relationships.length);
// Group nodes by depth
var byDepth: Record<number, any[]> = {};
result.nodes.forEach(node => {
var depth = node.distance || 0;
byDepth[depth] = byDepth[depth] || [];
byDepth[depth].push(node);
});
Console.WriteLine("Depth 0 (start):', byDepth[0]?.length || 0);
Console.WriteLine('Depth 1 (direct):', byDepth[1]?.length || 0);
Console.WriteLine('Depth 2 (extended):', byDepth[2]?.length || 0);
Filtered Neighborhood
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.getNeighborhood({
nodeId: userId,
depth: 2,
relationshipTypes: ['FRIENDS_WITH'],
nodeFilter: {
labels: ['Person'],
where: {
city: 'San Francisco',
age: { $GTE: 25 },
},
},
});
console.log(`Found ${result.nodes.length} friends in SF over 25`);
Map<String, Object> result = ductape.graph.getNeighborhood(Map.of(
nodeId: userId,
"depth", 2,
relationshipTypes: ['FRIENDS_WITH'],
nodeFilter: Map.of(
labels: ['Person'],
where: Map.of(
"city", "San Francisco",
age: Map.of( $"GTE", 25 )
)
)
));
System.out.println(`Found $Map.of(result.nodes.length) friends in SF over 25`);
result := client.graph.getNeighborhood({
nodeId: userId,
"depth": 2,
relationshipTypes: ['FRIENDS_WITH'],
nodeFilter: {
labels: ['Person'],
where: {
"city": "San Francisco",
age: { $"GTE": 25 },
},
},
});
fmt.Println(`Found ${result.nodes.length} friends in SF over 25`);
var result = await ductape.graph.getNeighborhood({
nodeId: userId,
["depth"] = 2,
relationshipTypes: ['FRIENDS_WITH'],
nodeFilter: {
labels: ['Person'],
where: {
["city"] = "San Francisco",
age: { $["GTE"] = 25 },
},
},
});
Console.WriteLine(`Found ${result.nodes.length} friends in SF over 25`);
Neighborhood Statistics
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.getNeighborhood({
nodeId: userId,
depth: 2,
});
// Analyze the neighborhood
const nodesByLabel: Record<string, number> = {};
result.nodes.forEach(node => {
node.labels.forEach(label => {
nodesByLabel[label] = (nodesByLabel[label] || 0) + 1;
});
});
console.log('Node distribution:', nodesByLabel);
Map<String, Object> result = ductape.graph.getNeighborhood(Map.of(
nodeId: userId,
"depth", 2
));
// Analyze the neighborhood
Map<String, Object> nodesByLabel: Record<string, number> = Map.of();
result.nodes.forEach(node => Map.of(
node.labels.forEach(label => Map.of(
nodesByLabel[label] = (nodesByLabel[label] || 0) + 1;
));
));
System.out.println('Node distribution:', nodesByLabel);
result := client.graph.getNeighborhood({
nodeId: userId,
"depth": 2,
});
// Analyze the neighborhood
const nodesByLabel: Record<string, number> = {};
result.nodes.forEach(node => {
node.labels.forEach(label => {
nodesByLabel[label] = (nodesByLabel[label] || 0) + 1;
});
});
fmt.Println('Node distribution:', nodesByLabel);
var result = await ductape.graph.getNeighborhood({
nodeId: userId,
["depth"] = 2,
});
// Analyze the neighborhood
var nodesByLabel: Record<string, number> = {};
result.nodes.forEach(node => {
node.labels.forEach(label => {
nodesByLabel[label] = (nodesByLabel[label] || 0) + 1;
});
});
Console.WriteLine('Node distribution:', nodesByLabel);
Connected Components
Find groups of connected nodes in the graph.
Find Components
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.findConnectedComponents({
relationshipTypes: ['FRIENDS_WITH'],
labels: ['Person'],
});
console.log(`Found ${result.components.length} connected groups`);
result.components.forEach((component, index) => {
console.log(`Group ${index + 1}: ${component.nodes.length} people`);
});
Map<String, Object> result = ductape.graph.findConnectedComponents(Map.of(
relationshipTypes: ['FRIENDS_WITH'],
labels: ['Person']
));
System.out.println(`Found $Map.of(result.components.length) connected groups`);
result.components.forEach((component, index) => Map.of(
System.out.println(`Group $Map.of(index + 1): $Map.of(component.nodes.length) people`);
));
result := client.graph.findConnectedComponents({
relationshipTypes: ['FRIENDS_WITH'],
labels: ['Person'],
});
fmt.Println(`Found ${result.components.length} connected groups`);
result.components.forEach((component, index) => {
fmt.Println(`Group ${index + 1}: ${component.nodes.length} people`);
});
var result = await ductape.graph.findConnectedComponents({
relationshipTypes: ['FRIENDS_WITH'],
labels: ['Person'],
});
Console.WriteLine(`Found ${result.components.length} connected groups`);
result.components.forEach((component, index) => {
Console.WriteLine(`Group ${index + 1}: ${component.nodes.length} people`);
});
Largest Component
- TypeScript
- Java
- Go
- .NET
const result = await ductape.graph.findConnectedComponents({
relationshipTypes: ['FRIENDS_WITH'],
});
// Sort by size
const sorted = result.components.sort((a, b) => b.nodes.length - a.nodes.length);
const largest = sorted[0];
console.log(`Largest group has ${largest.nodes.length} members`);
Map<String, Object> result = ductape.graph.findConnectedComponents(Map.of(
relationshipTypes: ['FRIENDS_WITH']
));
// Sort by size
Map<String, Object> sorted = result.components.sort((a, b) => b.nodes.length - a.nodes.length);
Map<String, Object> largest = sorted[0];
System.out.println(`Largest group has $Map.of(largest.nodes.length) members`);
result := client.graph.findConnectedComponents({
relationshipTypes: ['FRIENDS_WITH'],
});
// Sort by size
sorted := result.components.sort((a, b) => b.nodes.length - a.nodes.length);
largest := sorted[0];
fmt.Println(`Largest group has ${largest.nodes.length} members`);
var result = await ductape.graph.findConnectedComponents({
relationshipTypes: ['FRIENDS_WITH'],
});
// Sort by size
var sorted = result.components.sort((a, b) => b.nodes.length - a.nodes.length);
var largest = sorted[0];
Console.WriteLine(`Largest group has ${largest.nodes.length} members`);
Use Case Examples
Social Network: Degrees of Separation
- TypeScript
- Java
- Go
- .NET
async function degreesOfSeparation(user1Id: string, user2Id: string) {
const path = await ductape.graph.shortestPath({
startNodeId: user1Id,
endNodeId: user2Id,
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 6, // Six degrees of separation
});
if (path.path) {
const degrees = path.path.length;
console.log(`${degrees} degree${degrees !== 1 ? 's' : ''} of separation`);
// Show the connection path
const names = path.path.nodes.map(n => n.properties.name);
console.log(names.join(' knows '));
return degrees;
} else {
console.log('Not connected within 6 degrees');
return null;
}
}
async function degreesOfSeparation(user1Id: string, user2Id: string) Map.of(
Map<String, Object> path = ductape.graph.shortestPath(Map.of(
startNodeId: user1Id,
endNodeId: user2Id,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 6, // Six degrees of separation
));
if (path.path) Map.of(
Map<String, Object> degrees = path.path.length;
System.out.println(`$Map.of(degrees) degree$Map.of(degrees !== 1 ? 's' : '') of separation`);
// Show the connection path
Map<String, Object> names = path.path.nodes.map(n => n.properties.name);
System.out.println(names.join(' knows '));
return degrees;
) else Map.of(
System.out.println('Not connected within 6 degrees');
return null;
)
)
async function degreesOfSeparation(user1Id: string, user2Id: string) {
path := client.graph.shortestPath({
startNodeId: user1Id,
endNodeId: user2Id,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 6, // Six degrees of separation
});
if (path.path) {
degrees := path.path.length;
fmt.Println(`${degrees} degree${degrees !== 1 ? 's' : ''} of separation`);
// Show the connection path
names := path.path.nodes.map(n => n.properties.name);
fmt.Println(names.join(' knows '));
return degrees;
} else {
fmt.Println('Not connected within 6 degrees');
return null;
}
}
async function degreesOfSeparation(user1Id: string, user2Id: string) {
var path = await ductape.graph.shortestPath({
startNodeId: user1Id,
endNodeId: user2Id,
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 6, // Six degrees of separation
});
if (path.path) {
var degrees = path.path.length;
Console.WriteLine(`${degrees} degree${degrees !== 1 ? 's' : ''} of separation`);
// Show the connection path
var names = path.path.nodes.map(n => n.properties.name);
Console.WriteLine(names.join(' knows '));
return degrees;
} else {
Console.WriteLine('Not connected within 6 degrees');
return null;
}
}
Recommendation: Friend Suggestions
- TypeScript
- Java
- Go
- .NET
async function suggestFriends(userId: string) {
// Find friends of friends
const network = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 2,
});
// Get direct friends
const directFriends = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
maxDepth: 1,
});
const directFriendIds = new Set(directFriends.paths.map(p => p.nodes[p.nodes.length - 1].id));
// Find friends of friends who aren't direct friends
const suggestions = network.paths
.map(p => p.nodes[p.nodes.length - 1])
.filter(node => node.id !== userId && !directFriendIds.has(node.id));
// Count mutual friends
const mutualCounts = new Map<string, number>();
suggestions.forEach(suggestion => {
const count = mutualCounts.get(suggestion.id as string) || 0;
mutualCounts.set(suggestion.id as string, count + 1);
});
// Sort by mutual friends
const sorted = Array.from(new Set(suggestions))
.sort((a, b) => {
const countA = mutualCounts.get(a.id as string) || 0;
const countB = mutualCounts.get(b.id as string) || 0;
return countB - countA;
});
return sorted.slice(0, 10); // Top 10 suggestions
}
async function suggestFriends(userId: string) Map.of(
// Find friends of friends
Map<String, Object> network = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 2
));
// Get direct friends
Map<String, Object> directFriends = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth", 1
));
Map<String, Object> directFriendIds = new Set(directFriends.paths.map(p => p.nodes[p.nodes.length - 1].id));
// Find friends of friends who aren't direct friends
Map<String, Object> suggestions = network.paths
.map(p => p.nodes[p.nodes.length - 1])
.filter(node => node.id !== userId && !directFriendIds.has(node.id));
// Count mutual friends
Map<String, Object> mutualCounts = new Map<string, number>();
suggestions.forEach(suggestion => Map.of(
Map<String, Object> count = mutualCounts.get(suggestion.id as string) || 0;
mutualCounts.set(suggestion.id as string, count + 1);
));
// Sort by mutual friends
Map<String, Object> sorted = Array.from(new Set(suggestions))
.sort((a, b) => Map.of(
Map<String, Object> countA = mutualCounts.get(a.id as string) || 0;
Map<String, Object> countB = mutualCounts.get(b.id as string) || 0;
return countB - countA;
));
return sorted.slice(0, 10); // Top 10 suggestions
)
async function suggestFriends(userId: string) {
// Find friends of friends
network := client.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 2,
});
// Get direct friends
directFriends := client.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
"maxDepth": 1,
});
directFriendIds := new Set(directFriends.paths.map(p => p.nodes[p.nodes.length - 1].id));
// Find friends of friends who aren't direct friends
suggestions := network.paths
.map(p => p.nodes[p.nodes.length - 1])
.filter(node => node.id !== userId && !directFriendIds.has(node.id));
// Count mutual friends
mutualCounts := new Map<string, number>();
suggestions.forEach(suggestion => {
count := mutualCounts.get(suggestion.id as string) || 0;
mutualCounts.set(suggestion.id as string, count + 1);
});
// Sort by mutual friends
sorted := Array.from(new Set(suggestions))
.sort((a, b) => {
countA := mutualCounts.get(a.id as string) || 0;
countB := mutualCounts.get(b.id as string) || 0;
return countB - countA;
});
return sorted.slice(0, 10); // Top 10 suggestions
}
async function suggestFriends(userId: string) {
// Find friends of friends
var network = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 2,
});
// Get direct friends
var directFriends = await ductape.graph.traverse({
startNodeId: userId,
relationshipTypes: ['FRIENDS_WITH'],
["maxDepth"] = 1,
});
var directFriendIds = new Set(directFriends.paths.map(p => p.nodes[p.nodes.length - 1].id));
// Find friends of friends who aren't direct friends
var suggestions = network.paths
.map(p => p.nodes[p.nodes.length - 1])
.filter(node => node.id !== userId && !directFriendIds.has(node.id));
// Count mutual friends
var mutualCounts = new Map<string, number>();
suggestions.forEach(suggestion => {
var count = mutualCounts.get(suggestion.id as string) || 0;
mutualCounts.set(suggestion.id as string, count + 1);
});
// Sort by mutual friends
var sorted = Array.from(new Set(suggestions))
.sort((a, b) => {
var countA = mutualCounts.get(a.id as string) || 0;
var countB = mutualCounts.get(b.id as string) || 0;
return countB - countA;
});
return sorted.slice(0, 10); // Top 10 suggestions
}
Organization: Reporting Chain
- TypeScript
- Java
- Go
- .NET
async function getReportingChain(employeeId: string) {
const path = await ductape.graph.traverse({
startNodeId: employeeId,
direction: 'OUTGOING',
relationshipTypes: ['REPORTS_TO'],
maxDepth: 10, // Prevent infinite loops
});
// Get the longest path (to top of org)
const chainToTop = path.paths
.sort((a, b) => b.nodes.length - a.nodes.length)[0];
if (chainToTop) {
console.log('Reporting chain:');
chainToTop.nodes.forEach((node, index) => {
const indent = ' '.repeat(index);
console.log(`${indent}${node.properties.name} - ${node.properties.title}`);
});
}
return chainToTop;
}
async function getReportingChain(employeeId: string) Map.of(
Map<String, Object> path = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: employeeId,
"direction", "OUTGOING",
relationshipTypes: ['REPORTS_TO'],
"maxDepth", 10, // Prevent infinite loops
));
// Get the longest path (to top of org)
Map<String, Object> chainToTop = path.paths
.sort((a, b) => b.nodes.length - a.nodes.length)[0];
if (chainToTop) Map.of(
System.out.println('Reporting "chain", ");
chainToTop.nodes.forEach((node, index) => Map.of(
Map<String, Object> indent = " '.repeat(index);
System.out.println(`$Map.of(indent)$Map.of(node.properties.name) - $Map.of(node.properties.title)`);
));
)
return chainToTop;
)
async function getReportingChain(employeeId: string) {
path := client.graph.traverse({
startNodeId: employeeId,
"direction": "OUTGOING",
relationshipTypes: ['REPORTS_TO'],
"maxDepth": 10, // Prevent infinite loops
});
// Get the longest path (to top of org)
chainToTop := path.paths
.sort((a, b) => b.nodes.length - a.nodes.length)[0];
if (chainToTop) {
fmt.Println('Reporting "chain": ");
chainToTop.nodes.forEach((node, index) => {
indent := " '.repeat(index);
fmt.Println(`${indent}${node.properties.name} - ${node.properties.title}`);
});
}
return chainToTop;
}
async function getReportingChain(employeeId: string) {
var path = await ductape.graph.traverse({
startNodeId: employeeId,
["direction"] = "OUTGOING",
relationshipTypes: ['REPORTS_TO'],
["maxDepth"] = 10, // Prevent infinite loops
});
// Get the longest path (to top of org)
var chainToTop = path.paths
.sort((a, b) => b.nodes.length - a.nodes.length)[0];
if (chainToTop) {
Console.WriteLine('Reporting ["chain"] = ");
chainToTop.nodes.forEach((node, index) => {
var indent = " '.repeat(index);
Console.WriteLine(`${indent}${node.properties.name} - ${node.properties.title}`);
});
}
return chainToTop;
}
Supply Chain: Find Suppliers
- TypeScript
- Java
- Go
- .NET
async function traceProductOrigin(productId: string) {
const supplyChain = await ductape.graph.traverse({
startNodeId: productId,
direction: 'INCOMING',
relationshipTypes: ['SUPPLIES', 'MANUFACTURES', 'PROVIDES'],
maxDepth: 5,
});
// Find all unique suppliers
const suppliers = new Set();
supplyChain.paths.forEach(path => {
path.nodes.forEach(node => {
if (node.labels.includes('Supplier')) {
suppliers.add(node);
}
});
});
console.log(`Product supplied by ${suppliers.size} entities`);
return Array.from(suppliers);
}
async function traceProductOrigin(productId: string) Map.of(
Map<String, Object> supplyChain = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: productId,
"direction", "INCOMING",
relationshipTypes: ['SUPPLIES', 'MANUFACTURES', 'PROVIDES'],
"maxDepth", 5
));
// Find all unique suppliers
Map<String, Object> suppliers = new Set();
supplyChain.paths.forEach(path => Map.of(
path.nodes.forEach(node => Map.of(
if (node.labels.includes('Supplier')) Map.of(
suppliers.add(node);
)
));
));
System.out.println(`Product supplied by $Map.of(suppliers.size) entities`);
return Array.from(suppliers);
)
async function traceProductOrigin(productId: string) {
supplyChain := client.graph.traverse({
startNodeId: productId,
"direction": "INCOMING",
relationshipTypes: ['SUPPLIES', 'MANUFACTURES', 'PROVIDES'],
"maxDepth": 5,
});
// Find all unique suppliers
suppliers := new Set();
supplyChain.paths.forEach(path => {
path.nodes.forEach(node => {
if (node.labels.includes('Supplier')) {
suppliers.add(node);
}
});
});
fmt.Println(`Product supplied by ${suppliers.size} entities`);
return Array.from(suppliers);
}
async function traceProductOrigin(productId: string) {
var supplyChain = await ductape.graph.traverse({
startNodeId: productId,
["direction"] = "INCOMING",
relationshipTypes: ['SUPPLIES', 'MANUFACTURES', 'PROVIDES'],
["maxDepth"] = 5,
});
// Find all unique suppliers
var suppliers = new Set();
supplyChain.paths.forEach(path => {
path.nodes.forEach(node => {
if (node.labels.includes('Supplier')) {
suppliers.add(node);
}
});
});
Console.WriteLine(`Product supplied by ${suppliers.size} entities`);
return Array.from(suppliers);
}
Knowledge Graph: Related Articles
- TypeScript
- Java
- Go
- .NET
async function findRelatedArticles(articleId: string, maxResults: number = 10) {
// Find articles connected through shared topics, authors, or references
const related = await ductape.graph.traverse({
startNodeId: articleId,
direction: 'BOTH',
relationshipTypes: ['HAS_TOPIC', 'WRITTEN_BY', 'CITES'],
maxDepth: 2,
});
// Score articles by number of connections
const scores = new Map<string, number>();
related.paths.forEach(path => {
const targetNode = path.nodes[path.nodes.length - 1];
if (targetNode.labels.includes('Article') && targetNode.id !== articleId) {
const score = scores.get(targetNode.id as string) || 0;
scores.set(targetNode.id as string, score + 1);
}
});
// Sort by score and return top results
const sorted = Array.from(scores.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, maxResults);
return sorted.map(([id, score]) => ({ id, score }));
}
async function findRelatedArticles(articleId: string, maxResults: number = 10) Map.of(
// Find articles connected through shared topics, authors, or references
Map<String, Object> related = ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: articleId,
"direction", "BOTH",
relationshipTypes: ['HAS_TOPIC', 'WRITTEN_BY', 'CITES'],
"maxDepth", 2
));
// Score articles by number of connections
Map<String, Object> scores = new Map<string, number>();
related.paths.forEach(path => Map.of(
Map<String, Object> targetNode = path.nodes[path.nodes.length - 1];
if (targetNode.labels.includes('Article') && targetNode.id !== articleId) Map.of(
Map<String, Object> score = scores.get(targetNode.id as string) || 0;
scores.set(targetNode.id as string, score + 1);
)
));
// Sort by score and return top results
Map<String, Object> sorted = Array.from(scores.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, maxResults);
return sorted.map(([id, score]) => (Map.of( id, score )));
)
async function findRelatedArticles(articleId: string, maxResults: number = 10) {
// Find articles connected through shared topics, authors, or references
related := client.graph.traverse({
startNodeId: articleId,
"direction": "BOTH",
relationshipTypes: ['HAS_TOPIC', 'WRITTEN_BY', 'CITES'],
"maxDepth": 2,
});
// Score articles by number of connections
scores := new Map<string, number>();
related.paths.forEach(path => {
targetNode := path.nodes[path.nodes.length - 1];
if (targetNode.labels.includes('Article') && targetNode.id !== articleId) {
score := scores.get(targetNode.id as string) || 0;
scores.set(targetNode.id as string, score + 1);
}
});
// Sort by score and return top results
sorted := Array.from(scores.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, maxResults);
return sorted.map(([id, score]) => ({ id, score }));
}
async function findRelatedArticles(articleId: string, maxResults: number = 10) {
// Find articles connected through shared topics, authors, or references
var related = await ductape.graph.traverse({
startNodeId: articleId,
["direction"] = "BOTH",
relationshipTypes: ['HAS_TOPIC', 'WRITTEN_BY', 'CITES'],
["maxDepth"] = 2,
});
// Score articles by number of connections
var scores = new Map<string, number>();
related.paths.forEach(path => {
var targetNode = path.nodes[path.nodes.length - 1];
if (targetNode.labels.includes('Article') && targetNode.id !== articleId) {
var score = scores.get(targetNode.id as string) || 0;
scores.set(targetNode.id as string, score + 1);
}
});
// Sort by score and return top results
var sorted = Array.from(scores.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, maxResults);
return sorted.map(([id, score]) => ({ id, score }));
}
Route Finding: Shortest Route
- TypeScript
- Java
- Go
- .NET
async function findShortestRoute(startCityId: string, endCityId: string) {
const result = await ductape.graph.shortestPath({
startNodeId: startCityId,
endNodeId: endCityId,
relationshipTypes: ['ROAD', 'HIGHWAY'],
weightProperty: 'distance',
});
if (result.path) {
// Calculate total distance and time
let totalDistance = 0;
let totalTime = 0;
result.path.relationships.forEach(road => {
totalDistance += road.properties.distance || 0;
totalTime += road.properties.travelTime || 0;
});
console.log('Route:', result.path.nodes.map(n => n.properties.name).join(' → '));
console.log(`Total distance: ${totalDistance} km`);
console.log(`Estimated time: ${Math.round(totalTime / 60)} hours`);
return {
path: result.path,
distance: totalDistance,
time: totalTime,
};
}
return null;
}
async function findShortestRoute(startCityId: string, endCityId: string) Map.of(
Map<String, Object> result = ductape.graph.shortestPath(Map.of(
startNodeId: startCityId,
endNodeId: endCityId,
relationshipTypes: ['ROAD', 'HIGHWAY'],
"weightProperty", "distance"
));
if (result.path) Map.of(
// Calculate total distance and time
Map<String, Object> totalDistance = 0;
Map<String, Object> totalTime = 0;
result.path.relationships.forEach(road => Map.of(
totalDistance += road.properties.distance || 0;
totalTime += road.properties.travelTime || 0;
));
System.out.println('"Route", ", result.path.nodes.map(n => n.properties.name).join(" → '));
System.out.println(`Total distance: $Map.of(totalDistance) km`);
System.out.println(`Estimated time: $Map.of(Math.round(totalTime / 60)) hours`);
return Map.of(
path: result.path,
distance: totalDistance,
time: totalTime
);
)
return null;
)
async function findShortestRoute(startCityId: string, endCityId: string) {
result := client.graph.shortestPath({
startNodeId: startCityId,
endNodeId: endCityId,
relationshipTypes: ['ROAD', 'HIGHWAY'],
"weightProperty": "distance",
});
if (result.path) {
// Calculate total distance and time
totalDistance := 0;
totalTime := 0;
result.path.relationships.forEach(road => {
totalDistance += road.properties.distance || 0;
totalTime += road.properties.travelTime || 0;
});
fmt.Println('"Route": ", result.path.nodes.map(n => n.properties.name).join(" → '));
fmt.Println(`Total distance: ${totalDistance} km`);
fmt.Println(`Estimated time: ${Math.round(totalTime / 60)} hours`);
return {
path: result.path,
distance: totalDistance,
time: totalTime,
};
}
return null;
}
async function findShortestRoute(startCityId: string, endCityId: string) {
var result = await ductape.graph.shortestPath({
startNodeId: startCityId,
endNodeId: endCityId,
relationshipTypes: ['ROAD', 'HIGHWAY'],
["weightProperty"] = "distance",
});
if (result.path) {
// Calculate total distance and time
var totalDistance = 0;
var totalTime = 0;
result.path.relationships.forEach(road => {
totalDistance += road.properties.distance || 0;
totalTime += road.properties.travelTime || 0;
});
Console.WriteLine('["Route"] = ", result.path.nodes.map(n => n.properties.name).join(" → '));
Console.WriteLine(`Total distance: ${totalDistance} km`);
Console.WriteLine(`Estimated time: ${Math.round(totalTime / 60)} hours`);
return {
path: result.path,
distance: totalDistance,
time: totalTime,
};
}
return null;
}
Performance Tips
1. Limit Traversal Depth
- TypeScript
- Java
- Go
- .NET
// Good - reasonable depth
await ductape.graph.traverse({
startNodeId: userId,
maxDepth: 3,
});
// Careful - may be expensive
await ductape.graph.traverse({
startNodeId: userId,
maxDepth: 10, // Can explore many nodes
});
// Good - reasonable depth
ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"maxDepth", 3
));
// Careful - may be expensive
ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"maxDepth", 10, // Can explore many nodes
));
// Good - reasonable depth
client.graph.traverse({
startNodeId: userId,
"maxDepth": 3,
});
// Careful - may be expensive
client.graph.traverse({
startNodeId: userId,
"maxDepth": 10, // Can explore many nodes
});
// Good - reasonable depth
await ductape.graph.traverse({
startNodeId: userId,
["maxDepth"] = 3,
});
// Careful - may be expensive
await ductape.graph.traverse({
startNodeId: userId,
["maxDepth"] = 10, // Can explore many nodes
});
2. Filter Early
- TypeScript
- Java
- Go
- .NET
// Filter at query time, not after
await ductape.graph.traverse({
startNodeId: userId,
maxDepth: 2,
nodeFilter: {
labels: ['Person'],
where: { status: 'active' },
},
});
// Filter at query time, not after
ductape.graphs().traverse(Map<String, Object>.of(
startNodeId: userId,
"maxDepth", 2,
nodeFilter: Map.of(
labels: ['Person'],
where: Map.of( "status", "active" )
)
));
// Filter at query time, not after
client.graph.traverse({
startNodeId: userId,
"maxDepth": 2,
nodeFilter: {
labels: ['Person'],
where: { "status": "active" },
},
});
// Filter at query time, not after
await ductape.graph.traverse({
startNodeId: userId,
["maxDepth"] = 2,
nodeFilter: {
labels: ['Person'],
where: { ["status"] = "active" },
},
});
3. Limit Results
- TypeScript
- Java
- Go
- .NET
// Use limit for allPaths
await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: bobId,
maxDepth: 4,
limit: 100, // Stop after finding 100 paths
});
// Use limit for allPaths
ductape.graph.allPaths(Map.of(
startNodeId: aliceId,
endNodeId: bobId,
"maxDepth", 4,
"limit", 100, // Stop after finding 100 paths
));
// Use limit for allPaths
client.graph.allPaths({
startNodeId: aliceId,
endNodeId: bobId,
"maxDepth": 4,
"limit": 100, // Stop after finding 100 paths
});
// Use limit for allPaths
await ductape.graph.allPaths({
startNodeId: aliceId,
endNodeId: bobId,
["maxDepth"] = 4,
["limit"] = 100, // Stop after finding 100 paths
});
4. Use Specific Relationship Types
- TypeScript
- Java
- Go
- .NET
// Better - specific types
await ductape.graph.traverse({
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
});
// Slower - all relationships
await ductape.graph.traverse({
// No relationship type filter
});
// Better - specific types
ductape.graphs().traverse(Map<String, Object>.of(
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH']
));
// Slower - all relationships
ductape.graphs().traverse(Map<String, Object>.of(
// No relationship type filter
));
// Better - specific types
client.graph.traverse({
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
});
// Slower - all relationships
client.graph.traverse({
// No relationship type filter
});
// Better - specific types
await ductape.graph.traverse({
relationshipTypes: ['FRIENDS_WITH', 'WORKS_WITH'],
});
// Slower - all relationships
await ductape.graph.traverse({
// No relationship type filter
});
Next Steps
- Advanced Querying - Pattern matching and complex queries
- Work with Relationships - Create and manage relationships
- Use Transactions - Ensure data consistency
- Best Practices - Performance optimization
See Also
- Graph Overview - Full API reference
- Best Practices - Performance tips