Graph Database: Graph Patterns
Graph Database: Graph Patterns
Part of: Graph Database User Guide
Graph patterns describe the structure you’re looking for. HeliosDB supports various pattern types.
Simple Paths: (a)-[r]->(b)
Find direct connections between two nodes.
Example 14: Direct Friendship
// Pattern: (person1)-[FRIEND_OF]->(person2)let pattern = Pattern { nodes: vec![ NodePattern { variable: "person1".to_string(), labels: vec!["Person".to_string()], properties: HashMap::new(), }, NodePattern { variable: "person2".to_string(), labels: vec!["Person".to_string()], properties: HashMap::new(), }, ], relationships: vec![RelationshipPattern { variable: Some("friendship".to_string()), types: vec!["FRIEND_OF".to_string()], direction: Direction::Outgoing, properties: HashMap::new(), length: PathLength::Fixed(1), }],};Example 15: Bidirectional Relationship
// Pattern: (a)-[KNOWS]-(b) (either direction)let pattern = Pattern { nodes: vec![ NodePattern { variable: "a".to_string(), labels: vec!["Person".to_string()], properties: HashMap::new(), }, NodePattern { variable: "b".to_string(), labels: vec!["Person".to_string()], properties: HashMap::new(), }, ], relationships: vec![RelationshipPattern { variable: None, types: vec!["KNOWS".to_string()], direction: Direction::Both, // Either direction properties: HashMap::new(), length: PathLength::Fixed(1), }],};Variable Length: (a)-[*1..5]->(b)
Match paths of varying lengths.
Example 16: Friends Within 3 Hops
// Pattern: (alice)-[FRIEND_OF*1..3]->(friend)let pattern = Pattern { nodes: vec![ NodePattern { variable: "alice".to_string(), labels: vec!["Person".to_string()], properties: HashMap::from([ ("name".to_string(), json!("Alice")), ]), }, NodePattern { variable: "friend".to_string(), labels: vec!["Person".to_string()], properties: HashMap::new(), }, ], relationships: vec![RelationshipPattern { variable: None, types: vec!["FRIEND_OF".to_string()], direction: Direction::Outgoing, properties: HashMap::new(), length: PathLength::Range(1, 3), // 1 to 3 hops }],};
// Alternative: Use BFS for better performancelet options = BfsOptions { max_depth: 3, max_nodes: 10000, enable_early_termination: false, target: None,};
let result = bfs(&storage, alice_id, options).await?;Example 17: Unlimited Path Length
// Pattern: (start)-[CONNECTED_TO*]->(end)let pattern = Pattern { nodes: vec![ NodePattern { variable: "start".to_string(), labels: vec!["Node".to_string()], properties: HashMap::new(), }, NodePattern { variable: "end".to_string(), labels: vec!["Node".to_string()], properties: HashMap::new(), }, ], relationships: vec![RelationshipPattern { variable: None, types: vec!["CONNECTED_TO".to_string()], direction: Direction::Outgoing, properties: HashMap::new(), length: PathLength::Unbounded, // Any length }],};Shortest Path: shortestPath((a)-[*]->(b))
Find the shortest path between two nodes.
Example 18: Shortest Path Between Two People
use heliosdb_graph::traversal::dijkstra;
// Find shortest path from Alice to Charlielet result = dijkstra(&storage, alice_id, charlie_id).await?;
if let Some(path) = result { println!("Shortest path found:"); println!(" Length: {} hops", path.path.len() - 1); println!(" Cost: {}", path.cost); println!(" Path: {:?}", path.path);} else { println!("No path found");}Example 19: Weighted Shortest Path
// When edges have weights representing distance, cost, etc.// Dijkstra automatically uses edge weights
let result = dijkstra(&storage, source_id, target_id).await?;
if let Some(path) = result { println!("Cheapest path:"); println!(" Total cost: {}", path.cost);
for (i, node_id) in path.path.iter().enumerate() { if let Some(node) = storage.get_vertex(*node_id).await? { println!(" Step {}: {}", i + 1, node.properties.get("name").unwrap()); } }}Multiple Patterns
Combine multiple patterns in one query.
Example 20: Complex Pattern
// Find people who bought the same product// Pattern: (p1)-[:PURCHASED]->(product)<-[:PURCHASED]-(p2)
let query = CypherQuery { match_clause: Some(MatchClause { patterns: vec![Pattern { nodes: vec![ NodePattern { variable: "p1".to_string(), labels: vec!["Person".to_string()], properties: HashMap::new(), }, NodePattern { variable: "product".to_string(), labels: vec!["Product".to_string()], properties: HashMap::new(), }, NodePattern { variable: "p2".to_string(), labels: vec!["Person".to_string()], properties: HashMap::new(), }, ], relationships: vec![ RelationshipPattern { variable: None, types: vec!["PURCHASED".to_string()], direction: Direction::Outgoing, properties: HashMap::new(), length: PathLength::Fixed(1), }, RelationshipPattern { variable: None, types: vec!["PURCHASED".to_string()], direction: Direction::Incoming, properties: HashMap::new(), length: PathLength::Fixed(1), }, ], }], }), where_clause: Some(WhereClause { condition: Condition::Comparison { left: Expression::Property { variable: "p1".to_string(), property: "id".to_string(), }, op: ComparisonOp::Ne, right: Expression::Property { variable: "p2".to_string(), property: "id".to_string(), }, }, }), return_clause: ReturnClause { items: vec![ ReturnItem { expression: Expression::Property { variable: "p1".to_string(), property: "name".to_string(), }, alias: Some("person1".to_string()), }, ReturnItem { expression: Expression::Property { variable: "p2".to_string(), property: "name".to_string(), }, alias: Some("person2".to_string()), }, ReturnItem { expression: Expression::Property { variable: "product".to_string(), property: "name".to_string(), }, alias: Some("product".to_string()), }, ], distinct: true, }, order_by: None, limit: None, skip: None,};Optional Matches
Handle cases where relationships might not exist (planned feature).
Navigation
- Previous: Cypher Query Language
- Next: Graph Algorithms
- Index: Graph Database User Guide
Version: 6.5 Last Updated: November 17, 2025