Mutate Step
The mutate
step iterates over elements in the traversal, applying a callback function to each one. This callback receives mutable access to the graph, allowing for in-place modification of vertices or edges. mutate
is a terminal step that consumes the walker and returns the total count (usize
) of elements processed.
In this diagram:
- Input Elements: The walker starts with elements A, B, C, each having an initial value (e.g.,
val=1
). - The
.mutate(callback)
step processes each element. The callback function has access to modify the graph. - Mutated Elements (In Graph): The diagram shows the state of the elements after the mutation callback has been applied (e.g., A' with
val=10
). This highlights the in-place nature of the operation. - Returns: usize: The step completes and returns the count of elements processed (3 in this case), terminating the walker chain.
Syntax
walker.mutate(|element, context, graph| {
// mutation logic using graph access
})
Parameters
callback
: A function that takes:- A reference to the current element (vertex or edge) - Note: Direct mutable access to the element itself might vary; mutation often happens via the
graph
reference using the element's ID. - The element's context
- A mutable reference to the graph (
&mut G
) - Performs modifications using the mutable graph reference (e.g.,
graph.vertex_mut(element.id())
).
- A reference to the current element (vertex or edge) - Note: Direct mutable access to the element itself might vary; mutation often happens via the
Return Value
Returns a usize
representing the number of elements processed by the mutate
step.
Example
// Example 1: Update all person vertices to increment their age
println!("Incrementing age of all people:");
// Print original ages
graph
.walk()
.vertices(Vertex::person())
.probe(|vertex, _| {
if let Some(person) = vertex.project::<Person<_>>() {
println!(" Before: {} is {} years old", person.name(), person.age());
}
})
.count();
// Perform the mutation - increment everyone's age by 1
let updated_count = graph
.walk_mut() // Must use walk_mut() for mutations
.vertices(Vertex::person())
.mutate(|graph, vertex_id, _| {
// Note: updating requires cloning and replacing due to Rust's ownership model
if let Some(mut vertex) = graph.vertex_mut(vertex_id) {
if let Some(mut person) = vertex.project_mut::<PersonMut<_, _>>() {
// Increment the person age
person.set_age(person.age() + 1);
}
}
});
println!(" Updated {} person vertices", updated_count);
Best Practices
- Use
mutate
specifically for modifying graph elements based on traversal results. - Access mutable elements via the provided
graph
reference and the element's ID (e.g.,graph.vertex_mut(id)
). - Be mindful that mutations are applied directly and immediately to the graph state.
- Consider using
filter
orcontrol_flow
beforemutate
to precisely target which elements should be modified. - Understand the graph implementation's behavior regarding mutations during iteration (e.g., adding/removing elements might invalidate iterators in some graph types).
Common Use Cases
- Updating properties: Modifying attributes of vertices or edges (e.g., incrementing age, changing status).
- Graph cleaning: Standardizing data or fixing inconsistencies found during traversal.
- State transitions: Updating element states based on workflow logic during traversal.
- Bulk updates: Applying a change to a set of elements identified by prior traversal steps.