Basic Operations
Overview
Once you've defined your graph model, you can perform basic operations like adding vertices and edges, querying the graph, and modifying elements. This guide covers the fundamental operations available in Graph API.
Creating a Graph
To start working with graphs, first create a new graph instance:
// Import the standard model and create a new graph
let mut graph = SimpleGraph::<Vertex, Edge>::new();
Adding Vertices
Once you have a graph instance, you can add vertices to it:
// Add a person vertex
let bryn = graph.add_vertex(Vertex::Person {
name: "Bryn".to_string(),
username: "bryn123".to_string(),
biography: "Graph enthusiast".to_string(),
age: 28,
});
// Add a project vertex
let project = graph.add_vertex(Vertex::Project {
name: "GraphAPI".to_string(),
});
// Add a comment vertex
let comment = graph.add_vertex(Vertex::Comment {
text: "Great project!".to_string(),
date: "2023-05-15".to_string(),
});
Adding Edges
Edges connect vertices in your graph:
// Add simple edges
graph.add_edge(bryn, project, Edge::Created);
graph.add_edge(julia, bryn, Edge::Follows);
// Add edges with properties
graph.add_edge(
bryn,
project,
Edge::Liked {
timestamp: "2023-01-15".to_string(),
},
);
Querying Vertices
You can query vertices using the walker API. Here are some examples:
Full Scan
When you need to find all vertices in the graph:
// Get all vertices in the graph
let all_vertices = graph
.walk()
.vertices() // Start with all vertices
.collect::<Vec<_>>();
// Count vertices by type using type-safe filters
let person_count = graph
.walk()
.vertices()
.filter_person() // Use generated helper method
.count();
let project_count = graph
.walk()
.vertices()
.filter_project() // Use generated helper method
.count();
Label-Based Lookup
For more efficient queries, use label-based indexes:
// Find all Person vertices using label index
let all_people = graph
.walk()
.vertices()
.filter_person() // Use generated helper for label filtering
.collect::<Vec<_>>();
// Find all Project vertices using label index
let all_projects = graph
.walk()
.vertices()
.filter_project() // Use generated helper for label filtering
.collect::<Vec<_>>();
Property Filtering
Filter vertices based on their properties:
// Find people over 30 years old
let older_people = graph
.walk()
.vertices()
.filter_by_person(|person, _| {
// Type-safe access to Person properties
person.age() > 30
})
.map(|v, _| {
// Use type-safe projection and accessor methods
let person = v.project::<Person<_>>().unwrap();
format!("{} ({})", person.name(), person.age())
})
.collect::<Vec<_>>();
// Find people with "programmer" in their biography
let programmers = graph
.walk()
.vertices()
.filter_by_person(|person, _| {
// Type-safe access to Person properties
person.biography().contains("programmer")
})
.map(|v, _| {
// Use type-safe projection and accessor methods
v.project::<Person<_>>().unwrap().name().to_string()
})
.collect::<Vec<_>>();
Working with Edges
The walker API also provides powerful tools for working with edges:
Finding Connected Edges
Get all edges connected to a vertex:
// Get all edges connected to a specific vertex
let connected_edges = graph
.walk()
.vertices_by_id(vec![person_id])
.edges(EdgeSearch::scan()) // Get all connected edges
.collect::<Vec<_>>();
Directional Edge Queries
Specify whether you want incoming or outgoing edges:
// Get only outgoing edges
let outgoing_edges = graph
.walk()
.vertices_by_id(vec![person_id])
.edges(EdgeSearch::scan().outgoing()) // Only outgoing edges
.collect::<Vec<_>>();
// Get only incoming edges
let incoming_edges = graph
.walk()
.vertices_by_id(vec![person_id])
.edges(EdgeSearch::scan().incoming()) // Only incoming edges
.collect::<Vec<_>>();
Label-Based Edge Filtering
Filter edges by their label:
// Find all "Created" edges in the graph
let creation_edges = graph
.walk()
.edges(EdgeSearch::scan())
.filter_created() // Type-safe filter using generated helper
.collect::<Vec<_>>();
// Find all "Follows" edges in the graph
let follow_edges = graph
.walk()
.edges(EdgeSearch::scan())
.filter_follows() // Type-safe filter using generated helper
.collect::<Vec<_>>();
// Find all edges with timestamp properties
let timestamped_edges = graph
.walk()
.edges(EdgeSearch::scan())
.filter(|e, _| match e.weight() {
Edge::Liked { timestamp } => true,
Edge::Commented { timestamp } => true,
_ => false,
})
.collect::<Vec<_>>();
Modifying the Graph
You can modify the graph during traversal using the mutation API:
Updating Vertex Properties
// Update all Person vertices to increment their age
let updated_count = graph
.walk_mut()
.vertices()
.filter_person() // Type-safe filter using generated helper
.mutate(|v| {
// Type-safe mutation using projection
if let Some(mut person) = v.project_mut::<Person<_>>() {
// Update the age property
let current_age = person.age();
person.set_age(current_age + 1);
true // Indicate that we modified the vertex
} else {
false // No modification
}
});
// Add a property to a specific person
graph
.walk_mut()
.vertices()
.filter_by_person(|p, _| p.username() == "bryn123")
.mutate(|v| {
// Type-safe mutation using projection
if let Some(mut person) = v.project_mut::<Person<_>>() {
// Update the biography property
person.set_biography("Updated biography: Graph API expert");
true // Indicate that we modified the vertex
} else {
false // No modification
}
});
Verifying Changes
After modification, you can verify the changes:
// Check that Bryn's biography was updated
let updated_bio = graph
.walk()
.vertices()
.filter_by_person(|p, _| p.username() == "bryn123")
.map(|v, _| {
// Type-safe access using projection
v.project::<Person<_>>().unwrap().biography().to_string()
})
.first();
// Verify all people are now older
let all_ages = graph
.walk()
.vertices()
.filter_person() // Type-safe filter using generated helper
.map(|v, _| {
// Type-safe access using projection
let person = v.project::<Person<_>>().unwrap();
(person.name().to_string(), person.age())
})
.collect::<Vec<_>>();
Next Steps
Now that you understand the basic operations, you can:
- Learn about Advanced Traversals using the Walker API
- Explore Context and State in graph traversals
- See Examples of Walker Steps to build more complex queries