pub struct VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Walker: VertexWalker<'graph, Graph = Graph>,{ /* private fields */ }
Expand description
A builder for vertex-focused graph traversals.
This builder constructs walkers that navigate graphs by moving from vertex to vertex.
§Type Parameters
'graph
: The lifetime of the graph referenceMutability
: A marker type indicating whether graph mutations are allowedGraph
: The graph type being traversedWalker
: The vertex walker implementation that will perform the traversal
Implementations§
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn graph(&mut self) -> &'graph Graph
pub fn graph(&mut self) -> &'graph Graph
Returns an immutable reference to the graph being traversed.
This consumes the graph reference, leaving the builder in a state where the graph reference has been taken.
§Returns
An immutable reference to the graph.
Sourcepub fn graph_mut(&mut self) -> &'graph mut Graph
pub fn graph_mut(&mut self) -> &'graph mut Graph
Sourcepub fn walker(self) -> Walker
pub fn walker(self) -> Walker
Consumes the builder and returns the underlying walker.
This extracts the walker from the builder, allowing it to be used directly.
§Returns
The walker that was being built.
Sourcepub fn with_edge_walker<EdgeWalker: EdgeWalker<'graph>, WithFn: FnOnce(Walker) -> EdgeWalker>(
self,
step: WithFn,
) -> EdgeWalkerBuilder<'graph, Mutability, Graph, EdgeWalker>
pub fn with_edge_walker<EdgeWalker: EdgeWalker<'graph>, WithFn: FnOnce(Walker) -> EdgeWalker>( self, step: WithFn, ) -> EdgeWalkerBuilder<'graph, Mutability, Graph, EdgeWalker>
Transforms the current vertex walker into an edge walker.
This method allows for changing the traversal from vertex-oriented to edge-oriented by applying a transformation function to the current walker.
§Type Parameters
EdgeWalker
: The target edge walker typeWithFn
: A function type that converts the current walker to an edge walker
§Parameters
step
: The transformation function to apply
§Returns
A new edge walker builder containing the transformed walker
Sourcepub fn with_vertex_walker<VertexWalker: VertexWalker<'graph, Graph = Graph>, WithFn: FnOnce(Walker) -> VertexWalker>(
self,
step: WithFn,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexWalker>
pub fn with_vertex_walker<VertexWalker: VertexWalker<'graph, Graph = Graph>, WithFn: FnOnce(Walker) -> VertexWalker>( self, step: WithFn, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexWalker>
Transforms the current vertex walker into another vertex walker.
This method allows for changing or extending the traversal while remaining vertex-oriented by applying a transformation function to the current walker.
§Type Parameters
VertexWalker
: The target vertex walker typeWithFn
: A function type that converts the current walker to another vertex walker
§Parameters
step
: The transformation function to apply
§Returns
A new vertex walker builder containing the transformed walker
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn collect<T: FromIterator<Graph::VertexId>>(self) -> Twhere
Walker: VertexWalker<'graph>,
pub fn collect<T: FromIterator<Graph::VertexId>>(self) -> Twhere
Walker: VertexWalker<'graph>,
§Collect Step
The collect
step finalizes a traversal and gathers the results into a collection.
This is a terminal operation that ends the traversal and provides access to the traversed elements.
§Visual Diagram
Before collect step (with elements in traversal):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After collect step (all elements consumed and collected):
[A] --- edge1 ---> [B] --- edge2 ---> [C]
^
|
edge3
|
[D]
Collection: [A, B, C, D]
§Parameters
None - but the resulting collection type is determined by the type parameter provided to the collect call.
§Return Value
Returns a collection of the traversed elements. The exact type depends on what you’re collecting into, commonly:
Vec<ElementId>
for simple ID collectionVec<(ElementId, Context)>
when context is used- Custom types when implementing
FromIterator
§Example
// Collect vertex IDs into a vector
let vertex_ids = graph
.walk()
.vertices(VertexSearch::scan())
.collect::<Vec<_>>();
// Graph should have vertices
assert!(!vertex_ids.is_empty());
For more examples, see the collect example.
§Notes
- The
collect
step is a terminal operation - no further traversal steps can be added after it - When collecting with context, use
map
first to format the data for collection - The collect step fully consumes the traversal
- Most commonly used with
Vec<_>
, but can collect into any type that implementsFromIterator
- Consider using
limit
beforecollect
for large graphs to avoid excessive memory use - For single-element queries, consider using
first()
instead ofcollect
for efficiency
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn push_context<Callback, Context>(
self,
callback: Callback,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexContext<'graph, Walker, impl Fn(&Graph::VertexReference<'_>, &Walker::Context) -> ContextRef<Context, Walker::Context>, ContextRef<Context, Walker::Context>>>where
Callback: Fn(&Graph::VertexReference<'_>, &Walker::Context) -> Context + 'graph,
Context: Clone + 'static,
pub fn push_context<Callback, Context>(
self,
callback: Callback,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexContext<'graph, Walker, impl Fn(&Graph::VertexReference<'_>, &Walker::Context) -> ContextRef<Context, Walker::Context>, ContextRef<Context, Walker::Context>>>where
Callback: Fn(&Graph::VertexReference<'_>, &Walker::Context) -> Context + 'graph,
Context: Clone + 'static,
§Context Step
The push_context
step allows you to associate additional data with each element in the traversal.
This is useful for carrying information along as you traverse, preserving state between traversal steps,
or accumulating results.
§Visual Diagram
Before push_context step (traversal with regular elements):
[Person A]* --- created ---> [Project X]*
|
knows
|
[Person B]*
After push_context step (elements now have associated context data):
[Person A]* + {age: 30} --- created ---> [Project X]* + {name: "Graph API"}
|
knows
|
[Person B]* + {age: 25}
§Parameters
callback
: A function that takes the current element and its existing context, and returns a new context value to associate with that element
§Return Value
Returns a traversal with the same elements, but with additional context information attached to each element.
§Example
// Use push_default_context to make source vertex information available during traversal
let knows: Vec<_> = graph
.walk()
.vertices_by_id(vec![bryn_id, julia_id])
.push_default_context()
.edges(EdgeSearch::scan().outgoing())
.filter_knows()
.head()
.map(|target, ctx| {
if let Vertex::Person { name, .. } = ctx.vertex() {
format!(
"{} knows {}",
name,
target.project::<Person<_>>().unwrap().name()
)
} else {
"Not a person".to_string()
}
})
.collect::<Vec<_>>();
// Check the results - should have 2 person descriptions
assert_eq!(knows.len(), 2);
println!("Vertex Context Example - Relationships found:");
for relationship in &knows {
println!("- {}", relationship);
}
§Notes
- Context is carried through the entire traversal, even across different graph elements
- Each push_context call creates a new context layer, with the previous context available as
ctx.parent()
- For complex traversals, you can build a nested context structure
- The context is cloned for each element, so keep context objects relatively small for performance
- Use
push_default_context()
for common patterns like storing the element’s ID and data - Context persists even when traversing to different elements (e.g., from vertex to connected edge)
- When retrieving results, both the element and its context are returned in a tuple
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn control_flow<Predicate>(
self,
predicate: Predicate,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexControlFlow<'graph, Walker, Predicate>>where
Walker: 'graph,
for<'a> Predicate: Fn(&'a Graph::VertexReference<'graph>, &mut Walker::Context) -> ControlFlow<Option<&'a Graph::VertexReference<'graph>>, Option<&'a Graph::VertexReference<'graph>>> + 'graph,
pub fn control_flow<Predicate>(
self,
predicate: Predicate,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexControlFlow<'graph, Walker, Predicate>>where
Walker: 'graph,
for<'a> Predicate: Fn(&'a Graph::VertexReference<'graph>, &mut Walker::Context) -> ControlFlow<Option<&'a Graph::VertexReference<'graph>>, Option<&'a Graph::VertexReference<'graph>>> + 'graph,
§ControlFlow Step
The control_flow
step allows you to evaluate each vertex with a predicate function that returns a
std::ops::ControlFlow
value. This gives precise control over traversal - you can either:
- Continue and include the element (ControlFlow::Continue(Some(id)))
- Continue but skip the element (ControlFlow::Continue(None))
- Stop traversal with an optional final element (ControlFlow::Break(option))
§Visual Diagram
Before control_flow step (all vertices in traversal):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After control_flow step that only includes projects and breaks on “Graph” projects:
[A] --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]
§Parameters
predicate
: A function that takes a reference to a vertex and a mutable reference to its context, and returns astd::ops::ControlFlow<Option<VertexId>, Option<VertexId>>
value:- Return
ControlFlow::Continue(Some(vertex.id()))
to include the vertex and continue - Return
ControlFlow::Continue(None)
to skip the vertex and continue - Return
ControlFlow::Break(Some(vertex.id()))
to include the vertex and stop traversal - Return
ControlFlow::Break(None)
to stop traversal without including the vertex
- Return
§Return Value
A new walker that applies the control flow logic to the traversal.
§Example
// Use control_flow to either skip a vertex (None), include it (Some), or stop traversal (Break)
let project = graph
.walk()
.vertices(VertexSearch::scan())
.control_flow(|vertex, _| {
if let Vertex::Project(project) = vertex.weight() {
// If we find a project with "Graph" in the name, stop traversal
if project.name.contains("Graph") {
return ControlFlow::Break(Some(vertex));
}
// Include other project vertices
return ControlFlow::Continue(Some(vertex));
}
// Skip non-project vertices
ControlFlow::Continue(None)
})
.first();
match project {
Some(id) => println!("Found project with 'Graph' in the name: {:?}", id),
None => println!("No projects with 'Graph' in the name"),
}
§Notes
- This step is more powerful than
filter()
as it can both filter elements and control traversal flow - The predicate receives a mutable reference to the context, allowing you to update state during traversal
- Use this step when you need a combination of filtering and conditional stopping of traversal
- Only elements where the predicate returns
Some
will be included in the traversal - When
ControlFlow::Break
is returned, the entire traversal stops immediately
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn count(self) -> usizewhere
'graph: 'graph,
pub fn count(self) -> usizewhere
'graph: 'graph,
§Count Step
The count
step fully traverses the graph and returns the number of elements emitted by the traversal.
§Visual Diagram
Before count step (with elements in traversal):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After count step (consumed all elements, returned count 4):
[A] --- edge1 ---> [B] --- edge2 ---> [C]
^
|
edge3
|
[D]
§Parameters
None
§Return Value
Returns an integer representing the total number of elements in the traversal.
§Example
// Count all vertices in the graph
let vertex_count = graph.walk().vertices(VertexSearch::scan()).count();
assert!(vertex_count >= 4); // At least bryn, julia, graph_api, rust
// Count only Person vertices
let person_count = graph
.walk()
.vertices(VertexSearch::scan())
.filter_person()
.count();
assert_eq!(person_count, 2); // bryn and julia
// Count Project vertices
let project_count = graph.walk().vertices(Vertex::project()).count();
assert_eq!(project_count, 2); // graph_api and rust
// Count edges between vertices
let edge_count = graph
.walk()
.vertices(VertexSearch::scan())
.edges(EdgeSearch::scan())
.count();
assert!(edge_count > 0);
// Count created edges
let created_edge_count = graph
.walk()
.vertices(VertexSearch::scan())
.edges(Edge::created())
.count();
assert!(created_edge_count > 0);
For more examples, see the count example.
§Notes
- The
count
step consumes the entire traversal - This is a terminal operation - no further steps can be added after
count
- For very large graphs, be aware that this will traverse the entire graph which may be expensive
- Consider using
limit
beforecount
if you only need to check up to a certain number of elements
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn dbg(
self,
tag: &'static str,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexProbe<'graph, Walker, impl FnMut(&Graph::VertexReference<'_>, &Walker::Context)>>
pub fn dbg( self, tag: &'static str, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexProbe<'graph, Walker, impl FnMut(&Graph::VertexReference<'_>, &Walker::Context)>>
§Debug Step
The dbg
step prints elements as they are traversed through the graph, making it
easier to debug complex traversals. Each element is tagged with the provided label.
§Visual Diagram
Before dbg step:
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After dbg step (elements continue in traversal, but are also printed to console):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
Console output:
[stage1] Vertex(A)
[stage1] Vertex(B)
[stage1] Vertex(C)
[stage1] Vertex(D)
§Parameters
tag
: A string label that will prefix all debug output to help identify which debug step is printing
§Return Value
Returns the same traversal that was passed in, allowing the traversal to continue unmodified.
§Example
// Debug vertices in a traversal (this will print to console)
let vertex_count = graph
.walk()
.vertices(VertexSearch::scan())
.dbg("vertices") // Print vertices to console with tag "vertices"
.count();
// There should be at least 4 vertices in the graph
assert!(vertex_count >= 4);
println!("Found {} vertices in total", vertex_count);
§Notes
- The
dbg
step is non-destructive - it does not modify the traversal path - Debug output goes to the console using the standard Debug trait implementation
- Remember that traversals are typically depth-first, so the output order may not be immediately intuitive
- For complex graphs, consider using more descriptive tags at each debug point
- This step is particularly useful for understanding how graph elements flow through a complex traversal
- The
dbg
step has minimal performance impact when not in debug mode
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn push_default_context(
self,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexContext<'graph, Walker, impl Fn(&Graph::VertexReference<'_>, &Walker::Context) -> ContextRef<DefaultVertexContext<Graph::VertexId, Graph::Vertex>, Walker::Context>, ContextRef<DefaultVertexContext<Graph::VertexId, Graph::Vertex>, Walker::Context>>>
pub fn push_default_context( self, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexContext<'graph, Walker, impl Fn(&Graph::VertexReference<'_>, &Walker::Context) -> ContextRef<DefaultVertexContext<Graph::VertexId, Graph::Vertex>, Walker::Context>, ContextRef<DefaultVertexContext<Graph::VertexId, Graph::Vertex>, Walker::Context>>>
§Default Context Step
The push_default_context
step is a specialized version of the push_context
step that
automatically stores the current element’s ID and data in the context. This provides a
convenient way to preserve information about elements as you traverse through the graph.
§Visual Diagram
Before push_default_context step (traversal with regular elements):
[Person A]* --- created ---> [Project X]*
|
knows
|
[Person B]*
After push_default_context step (elements with default context):
[Person A]* + {vertex_id: id_a, vertex: Person{name: "A", age: 30}} --- created ---> [Project X]* + {vertex_id: id_x, vertex: Project{name: "X"}}
|
knows
|
[Person B]* + {vertex_id: id_b, vertex: Person{name: "B", age: 25}}
§Parameters
None
§Return Value
Returns a traversal with the same elements, but with each element’s ID and data stored in its context.
§Example
// Use default context to access vertex information directly from prior in the traversal
let knows = graph
.walk()
.vertices_by_id(vec![bryn_id, julia_id])
.push_default_context()
.edges(EdgeSearch::scan().outgoing())
.filter_knows()
.head()
.map(|target_vertex, ctx| {
// Access source person name from context
let source_name = match ctx.vertex() {
Vertex::Person { name, .. } => name.clone(),
_ => "Unknown".to_string(),
};
// Access target person name from vertex
let person = target_vertex.project::<Person<_>>().unwrap();
format!("{} knows {}", source_name, person.name())
})
.collect::<Vec<_>>();
// Check the results
println!("Relationships found:");
for relationship in &knows {
println!("- {}", relationship);
}
§Notes
- Default context for vertices includes:
vertex_id
: The ID of the vertexvertex
: The vertex data (cloned from the graph)
- Type safety is maintained as the vertex/edge types are preserved
- This step requires that your vertex/edge types implement Clone + ’static
- More concise than manual context handling for common use cases
- Especially useful when you need to preserve information across multiple traversal steps
- Combines well with other context operations for complex data gathering
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn detour<Path, Terminal, WalkerBuilderT>(
self,
predicate: Path,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, Detour<'graph, Walker, Path, Terminal>>where
Path: Fn(VertexWalkerBuilder<'graph, ImmutableMarker, Graph, Waypoint<'graph, Graph, Walker::Context>>) -> WalkerBuilderT,
WalkerBuilderT: Into<WalkerBuilder<'graph, ImmutableMarker, Graph, Terminal>>,
Terminal: Walker<'graph, Graph = Graph>,
pub fn detour<Path, Terminal, WalkerBuilderT>(
self,
predicate: Path,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, Detour<'graph, Walker, Path, Terminal>>where
Path: Fn(VertexWalkerBuilder<'graph, ImmutableMarker, Graph, Waypoint<'graph, Graph, Walker::Context>>) -> WalkerBuilderT,
WalkerBuilderT: Into<WalkerBuilder<'graph, ImmutableMarker, Graph, Terminal>>,
Terminal: Walker<'graph, Graph = Graph>,
§Detour Step
The detour
step allows you to create a sub-traversal for each element in the current traversal.
It’s like a temporary branch in the traversal that returns to the main traversal when complete.
This is powerful for exploring connected elements without losing your current position.
§Visual Diagram
Before detour step (traversal position on Person A):
[Person A]* --- knows ---> [Person B] --- created ---> [Project 1]
created
↓
[Project 2]
During detour execution (for each element, a sub-traversal is performed):
Main traversal:
[Person A]* --- knows ---> [Person B]
Sub-traversal from Person A:
[Person A] --- knows ---> [Person B]
created
↓
[Project 2]*
After detour step (traversal position returns to original elements):
[Person A]* --- knows ---> [Person B]
created
↓
[Project 2]
§Parameters
traversal_fn
: A function that takes a reference to the current element and returns a new traversal. The results of this traversal are collected in the context.
§Return Value
A walker with the same elements as before, but with the results of the sub-traversals stored in the context.
§Example
// Count projects that Bryn created using detour
let bryn_project_count = graph
.walk()
.vertices_by_id(vec![bryn_id])
.push_context(|_, _| 0) // Start with count 0
.detour(|waypoint| {
// For each person, find outgoing created edges and count them
waypoint
.edges(Edge::created().outgoing())
.probe(|_e, _ctx| todo!()) // Increment count for each created edge
})
.map(|_, count| *count)
.collect::<Vec<_>>();
// Bryn should have at least one project
assert_eq!(bryn_project_count.len(), 1);
println!("Bryn has {} project(s)", bryn_project_count[0]);
§Notes
- The detour doesn’t change the main traversal elements - it only adds context data
- Detours can be nested for complex traversals
- The detour function can return any walker, allowing for flexible sub-traversals
- Use
push_context
inside detours to store data from the sub-traversal - Detours are executed eagerly for each element in the traversal
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn edges<'a, T: Into<EdgeSearch<'a, Graph>>>(
self,
search: T,
) -> EdgeWalkerBuilder<'graph, Mutability, Graph, Edges<'a, 'graph, Walker>>
pub fn edges<'a, T: Into<EdgeSearch<'a, Graph>>>( self, search: T, ) -> EdgeWalkerBuilder<'graph, Mutability, Graph, Edges<'a, 'graph, Walker>>
§Edges Step
The edges
step allows you to traverse to the edges in a graph.
It moves the traversal position from vertices to their connected edges based on the provided search criteria.
§Visual Diagram
Before edges step (traversal position on vertices):
[Person A]* --- knows ---> [Person B] --- created ---> [Project]
^
|
owns
|
[Company C]
After edges step with outgoing direction (traversal position moves to edges):
[Person A] --- knows --->* [Person B] --- created ---> [Project]
^
|
owns -*
|
[Company C]
§Parameters
search
: AnEdgeSearch
that defines which edges to include. This can filter by label, direction, and other criteria.
§Return Value
A new walker where the traversal position is on the edges matching the search criteria.
§Example
// Get all edges from bryn
let bryn_edges = graph
.walk()
.vertices_by_id(vec![bryn_id])
.edges(EdgeSearch::scan())
.collect::<Vec<_>>();
// Bryn should have edges
assert!(!bryn_edges.is_empty());
// Get outgoing edges from bryn
let bryn_outgoing_edges = graph
.walk()
.vertices_by_id(vec![bryn_id])
.edges(EdgeSearch::scan().outgoing())
.collect::<Vec<_>>();
// Bryn should have outgoing edges
assert!(!bryn_outgoing_edges.is_empty());
// Get only 'Created' edges
let bryn_created_edges = graph
.walk()
.vertices_by_id(vec![bryn_id])
.edges(Edge::created())
.collect::<Vec<_>>();
// Bryn should have at least one `Created` edge
assert!(!bryn_created_edges.is_empty());
// Get outgoing 'Created' edges
let bryn_outgoing_created_edges = graph
.walk()
.vertices_by_id(vec![bryn_id])
.edges(Edge::created().outgoing())
.collect::<Vec<_>>();
// Bryn should have outgoing created edges
assert!(!bryn_outgoing_created_edges.is_empty());
// You can also use indexed edges when available
let indexed_created_edges = graph
.walk()
.vertices_by_id(vec![bryn_id])
.edges(Edge::created())
.collect::<Vec<_>>();
assert!(!indexed_created_edges.is_empty());
§Notes
- The edges step changes the traversal position from vertices to edges
- To get back to vertices after an edges step, use
head()
ortail()
- The search direction matters:
.outgoing()
finds edges where the current vertex is the source,.incoming()
finds edges where the current vertex is the target, and.bidirectional()
finds both - The edges step can filter by label and other properties through the EdgeSearch parameter
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn filter<Predicate>(
self,
predicate: Predicate,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexFilter<'graph, Walker, Predicate>>
pub fn filter<Predicate>( self, predicate: Predicate, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexFilter<'graph, Walker, Predicate>>
§Filter Step
The filter
step allows you to keep only vertices that match a predicate function.
Vertices that don’t match the predicate are excluded from further traversal.
§Visual Diagram
Before filter step (all vertices in traversal):
[Person A]* --- knows ---> [Person B]* --- created ---> [Project]*
^
|
owns
|
[Company C]*
After filter(is_project) step (only Project vertices remain in traversal):
[Person A] --- knows ---> [Person B] --- created ---> [Project]*
^
|
owns
|
[Company C]
§Parameters
predicate
: A function that takes a reference to a vertex and its context, and returns a boolean. Only vertices for which this function returnstrue
will be included in the traversal.
§Return Value
A new walker containing only the vertices that matched the predicate.
§Example
// Filter vertices to keep only those of a specific type
let projects = graph
.walk()
.vertices(VertexSearch::scan())
.filter(|vertex, _| matches!(vertex.weight(), Vertex::Project(_)))
.count();
println!("Found {} project vertices", projects);
§Notes
- The filter step does not modify the graph, only the traversal
- For complex filtering logic, consider breaking into multiple filter steps for better readability
- Use type projections or pattern matching when filtering to access type-specific methods and properties
- The filter is applied lazily during traversal, not when the step is added to the walker
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn first(self) -> Option<Graph::VertexId>where
'graph: 'graph,
pub fn first(self) -> Option<Graph::VertexId>where
'graph: 'graph,
§First Step
The first
step retrieves only the first vertex from a traversal and terminates.
This is a terminal operation that consumes the walker and returns an Option containing
the first vertex ID if one exists, or None if the traversal is empty.
§Visual Diagram
Before first step (multiple vertices in traversal):
[Project A]* --- uses ---> [Project B]* --- created_by ---> [Person]*
^
|
uses
|
[Project C]*
After first step (only first vertex returned):
[Project A]* --- uses ---> [Project B] --- created_by ---> [Person]
^
|
uses
|
[Project C]
Result: Project A
§Parameters
None
§Return Value
Option<VertexId>
- Returns Some(id) with the first vertex ID if the traversal contains at least one element,
or None if the traversal is empty.
§Example
// Get the first project vertex in the graph
let first_project = graph
.walk()
.vertices(VertexSearch::scan())
.filter(|v, _| matches!(v.weight(), Vertex::Project(_)))
.first();
// If found, print project information
if let Some(project_id) = first_project {
if let Some(vertex) = graph.vertex(project_id) {
if let Vertex::Project(project) = vertex.weight() {
println!("Found first project: {}", project.name);
}
}
} else {
println!("No projects found");
}
§Notes
- The
first
step is a terminal operation - it consumes the walker and returns immediately - If the traversal is empty,
first
returns None - More efficient than using
collect
when you only need the first vertex - Can be combined with filtering to find the first vertex of a specific type
- Order depends on the traversal steps and graph implementation
- For more deterministic results, consider using range indexes or sorting steps
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
pub fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
§Fold Step
The fold
step allows you to accumulate a result by processing each element in a traversal.
This is similar to the standard Rust fold
operation but works directly on graph traversals.
§Visual Diagram
Before fold step (traversal position on vertices):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
During fold step (processing each element with accumulator):
Accumulator: Init -> [A] -> [B] -> [C] -> [D] -> Final Result
§Parameters
init
: The initial value for the accumulatorf
: A closure that takes:- The current accumulator value
- A reference to the current element (vertex or edge)
- The current element’s context
- Returns the updated accumulator value
§Return Value
Returns the final accumulated value after processing all elements in the traversal.
§Example
// Calculate the average age of people
let (total_age, person_count) =
graph
.walk()
.vertices(Vertex::person())
.fold((0, 0), |(total, count), vertex, _| {
if let Vertex::Person { age, .. } = vertex.weight() {
(total + age, count + 1)
} else {
(total, count)
}
});
let average_age = if person_count > 0 {
total_age / person_count
} else {
0
};
// Average age should be reasonable for our test data
assert!(average_age > 20 && average_age < 100);
println!("Average age of people: {}", average_age);
§Notes
- The fold step is a terminal operation - it consumes the traversal and returns a value
- Unlike map, fold doesn’t yield a stream of values but a single accumulated result
- The closure is called once for each element with the accumulator and element
- Can be used for many common operations like counting, summing, finding min/max, etc.
- More flexible than specialized steps like count when you need to calculate custom aggregates
- The accumulator can be any type that matches your needs
- Context is available if you need it for your calculations
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn map<R, M>(self, mapping: M) -> impl Iterator<Item = R> + 'graph
pub fn map<R, M>(self, mapping: M) -> impl Iterator<Item = R> + 'graph
§Map Step
The map
step transforms vertices in the traversal by applying a mapping function to each vertex.
Unlike other steps that continue the traversal chain, map
returns an iterator that yields the
transformed elements directly.
§Visual Diagram
Before map step:
[Project A]* --- created_by ---> [Person B]* --- owns ---> [Project C]*
^
|
uses
|
[Project D]*
After map step with vertex -> extract project name
:
"Project A", "Person B", "Project C", "Project D"
§Parameters
mapping
: A function that takes a vertex reference and context, and returns a transformed value. The function signature isFnMut(Graph::VertexReference<'graph>, Walker::Context) -> R
.
§Return Value
Returns an iterator that yields the transformed elements. The type of the iterator items is determined by the return type of the mapping function.
§Example
// Map vertices to their names
let project_names: Vec<String> = graph
.walk()
.vertices(VertexSearch::scan())
.map(|vertex, _| {
// Extract project names using pattern matching
match vertex.weight() {
Vertex::Project(project) => project.name.clone(),
_ => "Not a project".to_string(),
}
})
.filter(|name| name != "Not a project")
.collect();
// Print the project names
println!("Projects in the graph:");
for name in &project_names {
println!("- {}", name);
}
§Notes
- The
map
step is terminal - it returns an iterator, not a traversal builder - The mapping function has access to both the vertex and its context
- After mapping, you can continue with standard Rust iterator operations like filter or collect
- Common uses include extracting properties from vertices (e.g., names, IDs, attributes)
- For building complex data structures, consider using pattern matching in the mapping function
- To map vertices with context data, use
push_context
before mapping
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn mutate<Callback>(self, callback: Callback) -> usize
pub fn mutate<Callback>(self, callback: Callback) -> usize
§Mutate Step
The mutate
step allows you to modify the graph during traversal. For each element
in the traversal (vertex or edge), the provided callback function is executed, giving
you the ability to create, modify, or delete elements in the graph.
§Visual Diagram
Before mutate step (traversal position on Person vertices):
[Person A]* [Project X]
|
[Person B]*
After mutate step (adding ‘Created’ edges to Project X):
[Person A]* ---- Created ----> [Project X]
|
[Person B]* ---- Created ----> [Project X]
§Parameters
callback
: A function that receives:- A mutable reference to the graph
- The element ID (vertex ID or edge ID)
- The context for the current element
§Requirements
- Must use
walk_mut()
instead ofwalk()
to get a mutable graph reference - Works with both vertex and edge traversals
- The traversal is collected before mutations are applied to avoid interference
§Return Value
Returns the number of elements that were modified (traversed and passed to the callback).
§Example
// Add a new project node to demonstrate mutations
let new_project_id = graph.add_vertex(Vertex::Project(Project {
name: "NewProject".to_string(),
}));
// Add 'Created' edges from people to a project using mutate
let mutations_count = graph
.walk_mut() // Must use walk_mut for mutations
.vertices(Vertex::person())
.mutate(|graph, person_id, _| {
// Add a 'Created' edge from each person to the new project
graph.add_edge(person_id, new_project_id, Edge::Created);
});
// Should have created edges for all people in the graph (at least 2)
assert!(mutations_count >= 2);
println!(
"Created {} edges connecting people to the project",
mutations_count
);
§Notes
- The
mutate
step doesn’t change the traversal position or context - All modifications happen to the graph itself, not to the traversal
- The traversal is completed first, then mutations are applied afterward to avoid traversal interference
- Be cautious when performing mutations that might interact with each other
- For better performance with large traversals, consider using
limit()
beforemutate()
- Can be used to implement complex graph algorithms like community detection, path finding, or graph rewriting
- Related steps:
filter()
for conditional traversal,collect()
for materializing results
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn mutate_context<Callback>(
self,
callback: Callback,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexMutateContext<'graph, Walker, Callback>>
pub fn mutate_context<Callback>( self, callback: Callback, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexMutateContext<'graph, Walker, Callback>>
§Mutate Context Step
The mutate_context
step allows you to modify the context during traversal. For each element
in the traversal, the provided callback function is executed, giving you the ability to modify
the current context object in-place.
§Visual Diagram
Before mutate_context step (traversal with contexts):
[Person A]* + {visited: false} --- knows ---> [Person B]* + {visited: false}
After mutate_context step (contexts have been modified):
[Person A]* + {visited: true} --- knows ---> [Person B]* + {visited: true}
§Parameters
callback
: A function that receives:- The current vertex reference
- A mutable reference to the current context
§Return Value
Returns a traversal with the same elements, but with modified context values.
§Example
// Use mutate_context to track each vertex we've seen
// Here we're using context as a way to observe the traversal
let ctx = graph
.walk()
.vertices_by_id(vec![start_id])
.push_context(|_, _| 0)
.mutate_context(|_, ctx| {
// Update the current context
**ctx += 1;
})
.map(|_, ctx| *ctx)
.next()
.expect("Expected to process one vertex");
println!("Visited {} vertices", ctx);
assert_eq!(ctx, 1, "Should have visited at least one vertex");
§Notes
- Unlike
push_context
, this step doesn’t create a new context layer - The callback can modify the context in-place, allowing for updating state during traversal
- Context modifications are applied immediately, affecting subsequent steps
- This is useful for building accumulators or updating state as you traverse
- Can be combined with other context-based steps for complex traversal logic
- When using nested contexts, only the current context level is mutable; parent contexts remain immutable
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn probe<Callback>(
self,
callback: Callback,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexProbe<'graph, Walker, Callback>>
pub fn probe<Callback>( self, callback: Callback, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexProbe<'graph, Walker, Callback>>
§Probe Step
The probe
step allows you to execute a callback function for each vertex in the traversal
without altering the traversal itself. This is useful for debugging, logging, or collecting
information during a traversal.
§Visual Diagram
Before probe step:
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After probe step (unchanged, but callback executed for each vertex *):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
§Parameters
callback
: A function that takes a reference to the current vertex being traversed, and optionally the current context. The function signature can be either:FnMut(&Graph::VertexReference<'_>, &Context)
- Probe with access to current context
§Return Value
A walker of the same type as the input with the probe operation added to the pipeline, allowing for further chaining of operations.
§Example
// Use probe to inspect vertices during traversal
let mut project_count = 0;
graph
.walk()
.vertices(VertexSearch::scan())
.probe(|vertex, _| {
// Inspect each vertex and count projects
if let Vertex::Project(project) = vertex.weight() {
project_count += 1;
println!("Found project: {}", project.name);
}
})
.count();
println!("Total projects found: {}", project_count);
§Notes
- The
probe
step does not modify the traversal path or elements - The callback function is executed for each vertex as it’s traversed
- When using the context variant, you can access traversal context data during probing
- Useful for debugging, logging, or gathering statistics about your graph
- Side effects in the callback function (like printing or counting) do not affect the traversal
- Can be used at multiple points in a traversal to monitor the flow at different stages
- Consider using pattern matching in the callback to work with specific vertex types
- Context access is especially useful when combined with
push_context
steps earlier in the traversal
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph + 'graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph + 'graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn reduce<Reducer>(
self,
reducer: Reducer,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexReduce<'graph, Walker, Reducer>>where
Reducer: for<'a> Fn(&'a Graph::VertexReference<'graph>, &'a Graph::VertexReference<'graph>, &Walker::Context) -> &'a Graph::VertexReference<'graph>,
pub fn reduce<Reducer>(
self,
reducer: Reducer,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexReduce<'graph, Walker, Reducer>>where
Reducer: for<'a> Fn(&'a Graph::VertexReference<'graph>, &'a Graph::VertexReference<'graph>, &Walker::Context) -> &'a Graph::VertexReference<'graph>,
§Reduce Step
The reduce
step combines elements in a traversal using a reducer function,
with the first element as the initial accumulator.
§Visual Diagram
Before reduce step (traversal position on vertices):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After reduce step (a single vertex containing the combined result):
[Result]* --- ... ---> [More Traversal Steps]
§Parameters
reducer
: A closure that takes:- The current accumulated element (left)
- The next element to combine (right)
- The parent walker’s context (passed through)
- Returns either the left or right element to continue the reduction
§Return Value
Returns a walker containing a single vertex representing the final reduced value. If the input traversal is empty, the walker will yield nothing.
§Example
// Find the oldest person in the graph
let oldest = graph
.walk()
.vertices(VertexSearch::scan())
.filter_person()
.reduce(|acc, vertex, _ctx| {
let acc_age = acc.project::<Person<_>>().unwrap().age();
let vertex_age = vertex.project::<Person<_>>().unwrap().age();
if vertex_age > acc_age { vertex } else { acc }
})
.map(|vertex, _ctx| {
let age = vertex.project::<Person<_>>().unwrap().age();
format!("The oldest person is {:?}, age {}", vertex.id(), age)
})
.next()
.expect("should have got a result");
println!("{}", oldest);
§Notes
- The reduce step is a non-terminal operation - it can be chained with other operations
- The walker will yield a single vertex - the final result of combining all input vertices
- If the traversal is empty, the walker will yield nothing
- The first element serves as the initial accumulator value
- Useful for finding maximum/minimum values or combining elements in a custom way
- Unlike
fold
, reduce doesn’t require an initial value and can still participate in further traversal - The reducer function must return a reference to one of the two input elements
- The returned element becomes the new accumulator for the next reduction step
- The reducer function operates on the elements only, the context remains unchanged
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn take(
self,
n: usize,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexTake<'graph, Walker>>
pub fn take( self, n: usize, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexTake<'graph, Walker>>
§Take Step
The take
step restricts a vertex traversal to return at most a specified number of vertices.
This is useful for pagination, performance optimization, or when you only need a subset of results.
§Visual Diagram
Before take step (with multiple vertices in traversal):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After take(2) step (only first 2 vertices remain in traversal):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]
^
|
edge3
|
[D]
§Parameters
n
: A usize value specifying the maximum number of vertices to include in the traversal
§Return Value
Returns a traversal containing at most the specified number of vertices.
§Example
// Get at most 2 vertices from the graph
let vertices = graph
.walk()
.vertices(VertexSearch::scan())
.take(2) // Only process two vertices, regardless of how many exist
.collect::<Vec<_>>();
// Verify we got at most 2 vertices
assert!(vertices.len() <= 2);
println!("Retrieved {} vertices (limited to 2)", vertices.len());
§Notes
- The
take
step is generally applied after filtering operations but before terminal operations - It does not guarantee which vertices will be returned, just how many
- For predictable results, combine with sorting operations or range indexes
- Can significantly improve performance by avoiding unnecessary traversal
- Particularly useful for large graphs where full traversal would be expensive
- If the traversal contains fewer vertices than the limit, all vertices are returned
- Different from
first()
which returns only a single vertex as an Option - Follows the naming convention of Rust’s standard library Iterator::take
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn vertices<'a, T: Into<VertexSearch<'a, Graph>>>(
self,
vertex_search: T,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, Vertices<'a, 'graph, Walker>>
pub fn vertices<'a, T: Into<VertexSearch<'a, Graph>>>( self, vertex_search: T, ) -> VertexWalkerBuilder<'graph, Mutability, Graph, Vertices<'a, 'graph, Walker>>
§Vertices Step
The vertices
step is the primary entry point for graph traversals, allowing you to select a set of
vertices to start traversing from. It accepts a VertexSearch
parameter that specifies which
vertices to include in the traversal.
§Visual Diagram
Before vertices step (empty traversal):
[A] --- edge1 ---> [B] --- edge2 ---> [C]
^
|
edge3
|
[D]
After vertices step (with VertexSearch::scan()):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After vertices step (with VertexSearch::scan().with_label(Vertex::person_label())):
[Person A]* --- edge1 ---> [Project B] --- edge2 ---> [Person C]*
^
|
edge3
|
[Person D]*
§Parameters
vertex_search
: AVertexSearch
object that defines the criteria for selecting vertices
§Return Value
Returns a traversal containing all vertices that match the search criteria.
§Example
// The vertices() step is the starting point for most graph traversals
// It finds vertices matching the given search criteria
// Get all vertices in the graph using a scan
let all_vertices = graph
.walk()
.vertices(VertexSearch::scan())
.collect::<Vec<_>>();
// Should find vertices in the graph
assert!(!all_vertices.is_empty());
// Get vertices with a specific label using an index
let people = graph.walk().vertices(Vertex::person()).collect::<Vec<_>>();
// Should find person vertices
assert!(!people.is_empty());
For more examples, see the vertices example.
§Notes
- The
vertices
step is typically the first step in a traversal - Use
VertexIndex
methods for faster access when you have appropriate indexes defined - For more complex criteria, you can chain the
filter
step after this one - When working with large graphs, consider using indexed properties for better performance
- This step supports all vertex search mechanisms, including label-based, index-based, and full scans
- The traversal order is not guaranteed unless you specifically use an range index
Source§impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
Sourcepub fn vertices_by_id<Iter>(
self,
vertex_ids: Iter,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexIter<'graph, Walker, Iter::IntoIter>>where
Iter: IntoIterator<Item = Graph::VertexId>,
pub fn vertices_by_id<Iter>(
self,
vertex_ids: Iter,
) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexIter<'graph, Walker, Iter::IntoIter>>where
Iter: IntoIterator<Item = Graph::VertexId>,
§Vertices By ID Step
The vertices_by_id
step allows you to begin a traversal from a specific set of vertex IDs.
This is useful when you already know the IDs of the vertices you want to include in your traversal.
§Visual Diagram
Before vertices_by_id step (empty traversal):
[A] --- edge1 ---> [B] --- edge2 ---> [C]
^
|
edge3
|
[D]
After vertices_by_id step (with [id_A, id_C]):
[A]* --- edge1 ---> [B] --- edge2 ---> [C]*
^
|
edge3
|
[D]
§Parameters
vertex_ids
: An iterator that yields vertex IDs to include in the traversal
§Return Value
Returns a traversal containing all vertices with the specified IDs.
§Example
// Simple example using known IDs
let result = graph
.walk()
.vertices_by_id(vec![bryn_id, julia_id])
.collect::<Vec<_>>();
assert_eq!(result.len(), 2);
// When using non-existent IDs, they are simply skipped (example is using simple graph vertex id)
let made_up_id = VertexId::new(3, 4);
let filtered_result = graph
.walk()
.vertices_by_id(vec![bryn_id, made_up_id])
.collect::<Vec<_>>();
assert_eq!(filtered_result.len(), 1); // Only bryn is found
For more examples, see the vertices_by_id example.
§Notes
- This step is efficient when you already know the exact IDs of vertices you want to work with
- The order of vertices in the traversal will match the order of IDs in the input iterator
- For vertices that don’t exist in the graph, they will be skipped without error
- This step is often used after a previous traversal has produced vertex IDs of interest
- When working with a large number of IDs, consider using a
HashSet
for deduplication if needed
Trait Implementations§
Source§impl<'graph, Mutability, Graph, Walker> From<VertexWalkerBuilder<'graph, Mutability, Graph, Walker>> for WalkerBuilder<'graph, Mutability, Graph, Walker>where
Walker: VertexWalker<'graph, Graph = Graph>,
impl<'graph, Mutability, Graph, Walker> From<VertexWalkerBuilder<'graph, Mutability, Graph, Walker>> for WalkerBuilder<'graph, Mutability, Graph, Walker>where
Walker: VertexWalker<'graph, Graph = Graph>,
Source§fn from(value: VertexWalkerBuilder<'graph, Mutability, Graph, Walker>) -> Self
fn from(value: VertexWalkerBuilder<'graph, Mutability, Graph, Walker>) -> Self
Source§impl<'graph, Mutability, Graph, Walker> IntoIterator for VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
§Iter Step
While there is no explicit iter
step method in the walker API, the walker builders implement
the IntoIterator
trait, allowing you to convert a traversal into a standard Rust iterator
with the .into_iter()
method. This enables using standard iterator methods like map
,
filter
, and fold
on your graph traversal results.
impl<'graph, Mutability, Graph, Walker> IntoIterator for VertexWalkerBuilder<'graph, Mutability, Graph, Walker>where
Graph: Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
§Iter Step
While there is no explicit iter
step method in the walker API, the walker builders implement
the IntoIterator
trait, allowing you to convert a traversal into a standard Rust iterator
with the .into_iter()
method. This enables using standard iterator methods like map
,
filter
, and fold
on your graph traversal results.
§Visual Diagram
Before iter (walker traversal):
[A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
^
|
edge3
|
[D]*
After iter (converted to standard Rust iterator):
Iterator<Item = VertexId> or Iterator<Item = EdgeId>
A -> B -> C -> D
When using map()
, the iterator yields references with contexts:
Iterator<Item = (reference, context)>
[A, ctx] -> [B, ctx] -> [C, ctx] -> [D, ctx]
§Parameters
None (when using .into_iter()
)
§Return Value
An iterator that yields element IDs (vertex or edge IDs, depending on the walker type).
When using the map()
method, the iterator yields tuples of (reference, context)
where:
reference
is either a vertex or edge reference depending on the walker typecontext
contains any accumulated context data from the traversal
§Example
// Basic iteration to collect IDs
let vertex_ids = graph
.walk()
.vertices(VertexSearch::scan())
.into_iter()
.collect::<Vec<_>>();
// There should be at least 4 vertices in the graph
assert!(vertex_ids.len() >= 4);
// We can use standard iterator operations like filtering
let filtered_vertices = graph
.walk()
.vertices(VertexSearch::scan())
.into_iter()
.filter(|vertex_id| {
// Get the vertex reference from the ID
if let Some(vertex) = graph.vertex(*vertex_id) {
// Check if it's a Person
matches!(vertex.weight(), Vertex::Person { .. })
} else {
false
}
})
.collect::<Vec<_>>();
// There should be exactly 2 Person vertices (bryn and julia)
assert_eq!(filtered_vertices.len(), 2);
// Using .map() on the walker directly yields references with context
let vertex_names = graph
.walk()
.vertices(VertexSearch::scan())
.map(|vertex, _ctx| {
match vertex.weight() {
Vertex::Person { name, .. } => name.clone(),
Vertex::Project(project) => project.name.clone(),
// Use a regular string instead of tech.clone() since Technology is not a variant
_ => "Unknown".to_string(),
}
})
.collect::<Vec<_>>();
assert!(vertex_names.contains(&"Bryn".to_string()));
assert!(vertex_names.contains(&"Julia".to_string()));
assert!(vertex_names.contains(&"GraphApi".to_string()));
assert!(vertex_names.contains(&"Rust".to_string()));
For more examples, see the into_iter example.
§Notes
- Using
.into_iter()
consumes the walker and returns an iterator over element IDs - This is the bridge between Graph API’s walker system and Rust’s standard iterator ecosystem
- After converting to an iterator, you can use all standard Rust iterator methods
- Prefer using walker steps for graph traversal logic, and iterator methods for post-traversal processing