pub struct GraphStore {
pub current_version: u64,
pub vector_index: Arc<VectorIndexManager>,
pub property_index: Arc<IndexManager>,
pub node_columns: ColumnStore,
pub edge_columns: ColumnStore,
pub index_sender: Option<UnboundedSender<IndexEvent>>,
/* private fields */
}Expand description
In-memory graph storage engine.
GraphStore is the authoritative source of truth for all graph data.
Its data structure layout is designed for the access patterns of a
Cypher query engine:
| Field | Type | Purpose | Lookup cost |
|---|---|---|---|
nodes | Vec<Vec<Node>> | Arena-allocated node versions, indexed by NodeId | O(1) |
edges | Vec<Vec<Edge>> | Arena-allocated edge versions, indexed by EdgeId | O(1) |
outgoing | Vec<Vec<(NodeId, EdgeId)>> | Sorted adjacency list per node (outgoing) | O(log d) binary search |
incoming | Vec<Vec<(NodeId, EdgeId)>> | Sorted adjacency list per node (incoming) | O(log d) binary search |
label_index | HashMap<Label, HashSet<NodeId>> | Secondary index: label -> node set | O(1) lookup, O(n) scan |
edge_type_index | HashMap<EdgeType, HashSet<EdgeId>> | Secondary index: type -> edge set | O(1) lookup, O(n) scan |
node_columns | ColumnStore | Columnar property storage for late materialization | O(1) per cell |
catalog | GraphCatalog | Triple-level statistics for graph-native planning (ADR-015) | O(1) |
The free_node_ids / free_edge_ids vectors enable ID reuse after
deletions, avoiding unbounded growth of the arena vectors.
Thread safety: GraphStore is not Sync by itself. Concurrent access
is managed by the server layer, which wraps it in Arc<RwLock<GraphStore>>
for shared-nothing read parallelism with exclusive write access.
Fields§
§current_version: u64Current global version for MVCC
vector_index: Arc<VectorIndexManager>Vector indices manager
property_index: Arc<IndexManager>Property indices manager
node_columns: ColumnStoreColumnar storage for node properties
edge_columns: ColumnStoreColumnar storage for edge properties
index_sender: Option<UnboundedSender<IndexEvent>>Async index event sender
Implementations§
Source§impl GraphStore
impl GraphStore
Sourcepub fn with_async_indexing() -> (Self, UnboundedReceiver<IndexEvent>)
pub fn with_async_indexing() -> (Self, UnboundedReceiver<IndexEvent>)
Create a new GraphStore with async indexing enabled
Sourcepub async fn start_background_indexer(
receiver: UnboundedReceiver<IndexEvent>,
vector_index: Arc<VectorIndexManager>,
property_index: Arc<IndexManager>,
tenant_manager: Arc<TenantManager>,
)
pub async fn start_background_indexer( receiver: UnboundedReceiver<IndexEvent>, vector_index: Arc<VectorIndexManager>, property_index: Arc<IndexManager>, tenant_manager: Arc<TenantManager>, )
Start the background indexer loop
Sourcepub fn create_node(&mut self, label: impl Into<Label>) -> NodeId
pub fn create_node(&mut self, label: impl Into<Label>) -> NodeId
Create a node with auto-generated ID and single label
Sourcepub fn create_node_with_properties(
&mut self,
tenant_id: &str,
labels: Vec<Label>,
properties: PropertyMap,
) -> NodeId
pub fn create_node_with_properties( &mut self, tenant_id: &str, labels: Vec<Label>, properties: PropertyMap, ) -> NodeId
Create a node with multiple labels and properties
Sourcepub fn get_node_at_version(&self, id: NodeId, version: u64) -> Option<&Node>
pub fn get_node_at_version(&self, id: NodeId, version: u64) -> Option<&Node>
Get a node by ID at a specific version (MVCC)
Sourcepub fn get_node_mut(&mut self, id: NodeId) -> Option<&mut Node>
pub fn get_node_mut(&mut self, id: NodeId) -> Option<&mut Node>
Get a mutable node by ID (always latest version)
Sourcepub fn set_node_property(
&mut self,
tenant_id: &str,
node_id: NodeId,
key: impl Into<String>,
value: impl Into<PropertyValue>,
) -> GraphResult<()>
pub fn set_node_property( &mut self, tenant_id: &str, node_id: NodeId, key: impl Into<String>, value: impl Into<PropertyValue>, ) -> GraphResult<()>
Set a property on a node and update vector indices if necessary
Sourcepub fn delete_node(&mut self, tenant_id: &str, id: NodeId) -> GraphResult<Node>
pub fn delete_node(&mut self, tenant_id: &str, id: NodeId) -> GraphResult<Node>
Delete a node and all its connected edges
Sourcepub fn add_label_to_node(
&mut self,
tenant_id: &str,
node_id: NodeId,
label: impl Into<Label>,
) -> GraphResult<()>
pub fn add_label_to_node( &mut self, tenant_id: &str, node_id: NodeId, label: impl Into<Label>, ) -> GraphResult<()>
Add a label to an existing node AND update the label index
This is the correct way to add labels to nodes after creation.
Using node.add_label() directly will NOT update the label_index,
making the node invisible to get_nodes_by_label() queries.
Sourcepub fn create_edge(
&mut self,
source: NodeId,
target: NodeId,
edge_type: impl Into<EdgeType>,
) -> GraphResult<EdgeId>
pub fn create_edge( &mut self, source: NodeId, target: NodeId, edge_type: impl Into<EdgeType>, ) -> GraphResult<EdgeId>
Create an edge between two nodes
Sourcepub fn create_edge_with_properties(
&mut self,
source: NodeId,
target: NodeId,
edge_type: impl Into<EdgeType>,
properties: PropertyMap,
) -> GraphResult<EdgeId>
pub fn create_edge_with_properties( &mut self, source: NodeId, target: NodeId, edge_type: impl Into<EdgeType>, properties: PropertyMap, ) -> GraphResult<EdgeId>
Create an edge with properties
Sourcepub fn get_edge_at_version(&self, id: EdgeId, version: u64) -> Option<&Edge>
pub fn get_edge_at_version(&self, id: EdgeId, version: u64) -> Option<&Edge>
Get an edge by ID at a specific version (MVCC)
Sourcepub fn get_edge_mut(&mut self, id: EdgeId) -> Option<&mut Edge>
pub fn get_edge_mut(&mut self, id: EdgeId) -> Option<&mut Edge>
Get a mutable edge by ID (always latest version)
Sourcepub fn delete_edge(&mut self, id: EdgeId) -> GraphResult<Edge>
pub fn delete_edge(&mut self, id: EdgeId) -> GraphResult<Edge>
Delete an edge
Sourcepub fn get_outgoing_edges(&self, node_id: NodeId) -> Vec<&Edge>
pub fn get_outgoing_edges(&self, node_id: NodeId) -> Vec<&Edge>
Get all outgoing edges from a node
Sourcepub fn get_incoming_edges(&self, node_id: NodeId) -> Vec<&Edge>
pub fn get_incoming_edges(&self, node_id: NodeId) -> Vec<&Edge>
Get all incoming edges to a node
Sourcepub fn get_outgoing_edge_targets(
&self,
node_id: NodeId,
) -> Vec<(EdgeId, NodeId, NodeId, &EdgeType)>
pub fn get_outgoing_edge_targets( &self, node_id: NodeId, ) -> Vec<(EdgeId, NodeId, NodeId, &EdgeType)>
Get outgoing edge targets as lightweight tuples (no Edge clone) Returns (EdgeId, source NodeId, target NodeId, &EdgeType) for each outgoing edge
Sourcepub fn get_incoming_edge_sources(
&self,
node_id: NodeId,
) -> Vec<(EdgeId, NodeId, NodeId, &EdgeType)>
pub fn get_incoming_edge_sources( &self, node_id: NodeId, ) -> Vec<(EdgeId, NodeId, NodeId, &EdgeType)>
Get incoming edge sources as lightweight tuples (no Edge clone) Returns (EdgeId, source NodeId, target NodeId, &EdgeType) for each incoming edge
Sourcepub fn edge_between(
&self,
source: NodeId,
target: NodeId,
edge_type: Option<&EdgeType>,
) -> Option<EdgeId>
pub fn edge_between( &self, source: NodeId, target: NodeId, edge_type: Option<&EdgeType>, ) -> Option<EdgeId>
Check if an edge exists between source and target, optionally filtered by edge type. Uses binary search on sorted adjacency lists for O(log d) lookup. Returns the first matching EdgeId, or None.
Sourcepub fn edges_between(
&self,
source: NodeId,
target: NodeId,
edge_type: Option<&EdgeType>,
) -> Vec<EdgeId>
pub fn edges_between( &self, source: NodeId, target: NodeId, edge_type: Option<&EdgeType>, ) -> Vec<EdgeId>
Get all edges between source and target, optionally filtered by edge type. Uses binary search on sorted adjacency lists.
Sourcepub fn get_nodes_by_label(&self, label: &Label) -> Vec<&Node>
pub fn get_nodes_by_label(&self, label: &Label) -> Vec<&Node>
Get all nodes with a specific label
Sourcepub fn get_edges_by_type(&self, edge_type: &EdgeType) -> Vec<&Edge>
pub fn get_edges_by_type(&self, edge_type: &EdgeType) -> Vec<&Edge>
Get all edges of a specific type
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
Get total number of nodes
Sourcepub fn edge_count(&self) -> usize
pub fn edge_count(&self) -> usize
Get total number of edges
Sourcepub fn compute_statistics(&self) -> GraphStatistics
pub fn compute_statistics(&self) -> GraphStatistics
Compute statistics for the current graph state
Sourcepub fn catalog(&self) -> &GraphCatalog
pub fn catalog(&self) -> &GraphCatalog
Get the triple-level statistics catalog (for graph-native query planning)
Sourcepub fn label_node_count(&self, label: &Label) -> usize
pub fn label_node_count(&self, label: &Label) -> usize
Get node count for a specific label (fast, O(1))
Sourcepub fn edge_type_count(&self, edge_type: &EdgeType) -> usize
pub fn edge_type_count(&self, edge_type: &EdgeType) -> usize
Get edge count for a specific type (fast, O(1))
Sourcepub fn all_labels(&self) -> Vec<&Label>
pub fn all_labels(&self) -> Vec<&Label>
Get all label names in the graph
Sourcepub fn all_edge_types(&self) -> Vec<&EdgeType>
pub fn all_edge_types(&self) -> Vec<&EdgeType>
Get all edge type names in the graph
pub fn handle_index_event( &self, event: IndexEvent, _tenant_manager: Option<Arc<TenantManager>>, )
Sourcepub fn create_vector_index(
&self,
label: &str,
property_key: &str,
dimensions: usize,
metric: DistanceMetric,
) -> VectorResult<()>
pub fn create_vector_index( &self, label: &str, property_key: &str, dimensions: usize, metric: DistanceMetric, ) -> VectorResult<()>
Create a vector index for a specific label and property
Sourcepub fn vector_search(
&self,
label: &str,
property_key: &str,
query: &[f32],
k: usize,
) -> VectorResult<Vec<(NodeId, f32)>>
pub fn vector_search( &self, label: &str, property_key: &str, query: &[f32], k: usize, ) -> VectorResult<Vec<(NodeId, f32)>>
Search for nearest neighbors using a vector index
Sourcepub fn insert_recovered_node(&mut self, node: Node)
pub fn insert_recovered_node(&mut self, node: Node)
Insert a recovered node (used during recovery from persistence) Unlike create_node(), this preserves the node’s existing ID
Sourcepub fn insert_recovered_edge(&mut self, edge: Edge) -> GraphResult<()>
pub fn insert_recovered_edge(&mut self, edge: Edge) -> GraphResult<()>
Insert a recovered edge (used during recovery from persistence) Unlike create_edge(), this preserves the edge’s existing ID Note: Source and target nodes must already exist
Trait Implementations§
Source§impl Debug for GraphStore
impl Debug for GraphStore
Auto Trait Implementations§
impl Freeze for GraphStore
impl RefUnwindSafe for GraphStore
impl Send for GraphStore
impl Sync for GraphStore
impl Unpin for GraphStore
impl UnsafeUnpin for GraphStore
impl UnwindSafe for GraphStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more