Graph (lexigram-graph)
Graph database support for the Lexigram Framework (Neo4j, in-memory).
Overview
Section titled “Overview”lexigram-graph provides graph storage backends with DI wiring for in-memory and Neo4j implementations behind the graph contracts. It supports node and edge creation, graph traversal queries, Cypher compilation for Neo4j, and lazy graph creation with lifecycle events.
Install
Section titled “Install”uv add lexigram-graph# With Neo4j supportuv add "lexigram-graph[neo4j]"Quick Start
Section titled “Quick Start”from lexigram import Applicationfrom lexigram.di.module import Module, modulefrom lexigram.graph import GraphConfig, GraphModulefrom lexigram.contracts.data.graph import GraphStoreProtocol, TraversalQuery, StartSpec, TraversalStep
@module(imports=[GraphModule.configure(GraphConfig(backend="memory"))])class AppModule(Module): pass
async def main() -> None: async with Application.boot(modules=[AppModule]) as app: store = await app.container.resolve(GraphStoreProtocol) graph = await store.get_graph()
await graph.create_node(["Person"], {"name": "Alice"}, node_id="alice") await graph.create_node(["Person"], {"name": "Bob"}, node_id="bob") await graph.create_edge("alice", "bob", "KNOWS")
paths = await graph.traverse( TraversalQuery( start=StartSpec(node_ids=("alice",)), steps=(TraversalStep(edge_types=("KNOWS",)),), ) ) assert paths
if __name__ == "__main__": import asyncio asyncio.run(main())Configuration
Section titled “Configuration”Zero-config usage: Call
GraphModule.configure()with no arguments to use all defaults (in-memory backend).
Option 1 — YAML file
Section titled “Option 1 — YAML file”graph: enabled: true backend: neo4j default_traversal_max_depth: 10 neo4j: uri: bolt://localhost:7687 password: "${NEO4J_PASSWORD}"Option 2 — Profiles + Environment Variables (recommended)
Section titled “Option 2 — Profiles + Environment Variables (recommended)”export LEX_GRAPH__BACKEND=neo4jexport LEX_GRAPH__NEO4J__URI=bolt://localhost:7687Option 3 — Python
Section titled “Option 3 — Python”from lexigram.graph import GraphConfig, GraphModulefrom lexigram.graph.config import Neo4jConfig
GraphModule.configure( GraphConfig( backend="neo4j", neo4j=Neo4jConfig( uri="bolt://localhost:7687", password="${NEO4J_PASSWORD}", ), ))Config reference
Section titled “Config reference”| Field | Default | Env var | Description |
|---|---|---|---|
enabled | true | LEX_GRAPH__ENABLED | Enable or disable the graph subsystem |
backend | memory | LEX_GRAPH__BACKEND | Graph backend to use (memory or neo4j) |
default_traversal_max_depth | 10 | LEX_GRAPH__DEFAULT_TRAVERSAL_MAX_DEPTH | Maximum depth for graph traversals |
default_query_limit | 100 | LEX_GRAPH__DEFAULT_QUERY_LIMIT | Default result limit for graph queries |
bulk_batch_size | 1000 | LEX_GRAPH__BULK_BATCH_SIZE | Batch size for bulk insert and update operations |
max_retries | 3 | LEX_GRAPH__MAX_RETRIES | Retry attempts on transient graph errors |
retry_delay | 1.0 | LEX_GRAPH__RETRY_DELAY | Seconds between retry attempts |
neo4j.uri | bolt://localhost:7687 | LEX_GRAPH__NEO4J__URI | Neo4j Bolt connection URI |
neo4j.username | neo4j | LEX_GRAPH__NEO4J__USERNAME | Neo4j authentication username |
neo4j.password | — | LEX_GRAPH__NEO4J__PASSWORD | Neo4j authentication password (required for production) |
neo4j.database | neo4j | LEX_GRAPH__NEO4J__DATABASE | Target Neo4j database name |
neo4j.max_connection_pool_size | 100 | LEX_GRAPH__NEO4J__MAX_CONNECTION_POOL_SIZE | Maximum driver connection pool size |
memory.max_nodes | 1000000 | LEX_GRAPH__MEMORY__MAX_NODES | Node capacity for the in-memory backend |
Module Factory Methods
Section titled “Module Factory Methods”| Method | Description |
|---|---|
GraphModule.configure(config=None) | Register GraphProvider with a config |
GraphModule.stub(config=None) | Lightweight test module with in-memory backend |
Key Features
Section titled “Key Features”- In-memory backend — no external service needed; for development and tests
- Neo4j backend — async Neo4j driver with Cypher query compilation
- Graph traversal —
TraversalQuery,StartSpec,TraversalStepfor graph walks - Named graphs — lazy graph creation per name with lifecycle events
- Connection pooling — configurable pool size for Neo4j driver
Testing
Section titled “Testing”async with Application.boot(modules=[GraphModule.stub()]) as app: store = await app.container.resolve(GraphStoreProtocol) graph = await store.get_graph() # Test with in-memory backendKey Source Files
Section titled “Key Source Files”| File | What it contains |
|---|---|
src/lexigram/graph/module.py | GraphModule.configure(), .stub() |
src/lexigram/graph/config.py | GraphConfig, Neo4jConfig |
src/lexigram/graph/di/provider.py | GraphProvider boot and registration |
src/lexigram/graph/backends/memory/backend.py | InMemoryGraphStore implementation |
src/lexigram/graph/backends/neo4j/backend.py | Neo4jGraphStore implementation |
src/lexigram/graph/backends/neo4j/cypher.py | CypherCompiler |