Skip to content

Named Graphs

Grafeo supports multiple named graphs within a single database instance. Each graph has its own nodes, edges, labels, indexes and MVCC versioning. This lets you partition data into logical units while sharing a single database connection and benefiting from cross-graph transactional guarantees.

Every database starts with an implicit default graph. All queries target the default graph until you explicitly create and switch to a named graph.

Creating Named Graphs

Use CREATE GRAPH to add a new named graph. The basic form creates an open (schema-free) graph:

CREATE GRAPH friends

Variants

Syntax Description
CREATE GRAPH g Create an open (schema-free) graph
CREATE GRAPH g ANY Explicitly open: any node/edge types allowed
CREATE GRAPH g OPEN Synonym for ANY
CREATE GRAPH IF NOT EXISTS g No-op if the graph already exists
CREATE GRAPH g TYPED my_type Bind the graph to a declared graph type
CREATE GRAPH g2 LIKE g1 Copy the schema (graph type) of g1, without data
CREATE GRAPH g3 AS COPY OF g1 Copy both schema and data from g1

Examples

-- Open graph (no type constraints)
CREATE GRAPH friends

-- Idempotent creation
CREATE GRAPH IF NOT EXISTS friends

-- Copy structure only
CREATE GRAPH friends_staging LIKE friends

-- Full clone with data
CREATE GRAPH friends_backup AS COPY OF friends

-- Typed graph (requires a previously created graph type)
CREATE GRAPH TYPE SocialNetwork (
    NODE TYPE Person (name STRING NOT NULL),
    EDGE TYPE KNOWS (since INT64)
)
CREATE GRAPH social TYPED SocialNetwork

Python API

import grafeo

db = grafeo.GrafeoDB()
db.create_graph("friends")

Rust API

use grafeo::GrafeoDB;

let db = GrafeoDB::new_in_memory();
db.create_graph("friends").unwrap();

Switching Graphs

Once a named graph exists, switch to it with USE GRAPH or SESSION SET GRAPH. Both set the active graph for the current session; SESSION SET GRAPH follows the ISO/IEC 39075 session-state grammar.

-- Switch to the friends graph
USE GRAPH friends

-- ISO session syntax (equivalent)
SESSION SET GRAPH friends

-- Return to the default graph
USE GRAPH DEFAULT

After switching, all subsequent queries in that session read from and write to the selected graph. The direct calls follow it too: creating and dropping vector and text indexes, vector_search, text_search, hybrid_search, mmr_search and import_edge_list act on the graph set_graph() selects (set_current_graph in Rust), and CALL grafeo.search.* after USE GRAPH finds that graph's indexes.

One Statement on Another Graph

USE g in front of a query or a data-modifying statement (the ISO/IEC 39075 use graph clause) runs that one statement on g and leaves the session's graph as it is. GRAPH is optional, and USE CURRENT_GRAPH names the session's graph:

-- Writes to friends, reads friends; the session stays on its graph
USE friends INSERT (:Person {name: 'Alix'})
USE GRAPH friends MATCH (p:Person) RETURN p.name

-- SELECT ... FROM names the graph the same way
SELECT p.name FROM friends MATCH (p:Person)

The graph must exist (Graph 'g' does not exist, GQLSTATUS 42002). Every part of the statement reads the same graph: the operands of a UNION or a NEXT chain may repeat the USE, and parts that name different graphs fail with an error that this is not supported yet. Inside a transaction, the statement's writes commit or roll back with the transaction, as a USE GRAPH switch does.

Python API

db.set_graph("friends")

# Check which graph is active
print(db.current_graph())  # "friends"

Rust API

let session = db.session();
session.execute("CREATE GRAPH friends")?;
session.execute("USE GRAPH friends")?;

assert_eq!(session.current_graph(), Some("friends".to_string()));

Working in Several Graphs at Once

db.set_graph() selects one graph for the whole database object, so code that works in two graphs would have to switch back and forth, and threads would race on the switch. A graph handle works in one graph without switching: it has the query methods, the direct API and transactions of the database, and every call goes to its graph whatever set_graph() selects. One handle can be used from several threads at once. A call through a handle whose graph no longer exists raises an error; it never falls back to another graph.

Python API

db.create_graph("extraction")
db.create_graph("model")
extraction, model = db.graph("extraction"), db.graph("model")

source = extraction.create_node(["File"], {"path": "billing.py"})
component = model.create_node(["Component"], {"name": "Billing"})
model.execute("MATCH (c:Component) RETURN c.name")

with model.begin_transaction() as tx:
    tx.execute("INSERT (:Component {name: 'Ledger'})")
    tx.commit()

Rust API

let model = db.graph("model")?;
model.execute("INSERT (:Component {name: 'Billing'})")?;

// Direct writes and transactions go through a session in the graph
let session = model.session()?;
session.create_node_with_props(&["Component"], [("name", Value::from("Ledger"))])?;

Writes to different graphs never conflict with each other: every graph numbers its nodes and edges on its own, so node 0 of one graph and node 0 of another are different nodes.

Listing and Dropping Graphs

Listing

SHOW GRAPHS returns all named graphs visible in the current schema context:

SHOW GRAPHS

In Python:

names = db.list_graphs()
print(names)  # ["friends", "colleagues"]

In Rust:

let names = db.list_graphs();
println!("{names:?}");

Dropping

Remove a named graph with DROP GRAPH. All data in the graph is deleted. If the session is currently using that graph, the session resets to the default graph automatically. While an open transaction has changes in the graph, DROP GRAPH fails with a write conflict (GRAFEO-T001): drop the graph once that transaction commits or rolls back.

DROP GRAPH friends

-- No error if the graph does not exist
DROP GRAPH IF EXISTS friends

In Python:

db.drop_graph("friends")

In Rust:

db.drop_graph("friends")?;

Cross-Graph Transactions

USE GRAPH works within an active transaction. You can switch between graphs mid-transaction, and the commit or rollback applies atomically across all graphs that were touched.

START TRANSACTION

USE GRAPH friends
INSERT (:Person {name: 'Alix'})

USE GRAPH colleagues
INSERT (:Person {name: 'Gus'})

COMMIT
-- Both inserts succeed or neither does

If a conflict is detected in any graph during commit, the entire transaction is rolled back. Savepoints also span graph boundaries: rolling back to a savepoint restores the active graph that was set when the savepoint was created.

Data Isolation

Each named graph has completely separate storage. Queries only see data in the active graph, and mutations in one graph never affect another.

CREATE GRAPH alpha
CREATE GRAPH beta

USE GRAPH alpha
INSERT (:Person {name: 'Alix'})

USE GRAPH beta
INSERT (:Person {name: 'Gus'})

-- Only Gus is visible here
MATCH (p:Person) RETURN p.name

Internally, the query plan cache keys include the active graph name. This means switching graphs does not cause stale cache hits: plans compiled for alpha are never reused when the session is using beta.

Persistence

Named graphs are fully persisted when the database uses a persistent storage backend. CREATE GRAPH and DROP GRAPH operations are WAL-logged, so they survive crashes and are recovered on restart.

import grafeo

# Persistent database
db = grafeo.GrafeoDB("my_data.grafeo")
db.execute("CREATE GRAPH friends")
db.execute("USE GRAPH friends")
db.execute("INSERT (:Person {name: 'Alix'})")

# After restart, the friends graph and its data are still present
db2 = grafeo.GrafeoDB("my_data.grafeo")
db2.execute("USE GRAPH friends")
result = db2.execute("MATCH (p:Person) RETURN p.name")
# Returns Alix

Snapshots also include named graph state. Both incremental and full snapshots capture all named graphs along with the default graph.

Schema-Scoped Graphs

Experimental

Schema-scoped graph resolution is experimental and incomplete. The session schema is parsed and stored, but full catalog-level schema isolation (e.g., preventing cross-schema graph access, schema-qualified names in queries) is not yet implemented. Use this feature for forward-compatible session state only.

Grafeo supports ISO/IEC 39075 session schemas. When a schema is set, graph names are resolved within that schema context. CREATE GRAPH creates the graph under the active schema, and SHOW GRAPHS only returns graphs belonging to that schema.

-- Set the session schema
SESSION SET SCHEMA analytics

-- This graph is scoped to "analytics"
CREATE GRAPH daily_metrics

-- Only shows graphs in the analytics schema
SHOW GRAPHS

-- Switch schema
SESSION SET SCHEMA reporting
CREATE GRAPH monthly_summary

Schema and graph are independent session settings (per ISO/IEC 39075 Section 7.1). Changing the schema does not reset the active graph, and changing the graph does not reset the schema.

-- Reset schema without affecting the active graph
SESSION RESET SCHEMA

-- Reset graph without affecting the schema
SESSION RESET GRAPH

-- Reset everything
SESSION RESET