GraphQLite Python
Python bindings for GraphQLite, a SQLite extension that adds graph database capabilities using Cypher.
Installation
pip install graphqlite
Quick Start
High-Level Graph API (Recommended)
The Graph class provides an ergonomic interface for common graph operations:
from graphqlite import Graph
# Create a graph (in-memory or file-based)
g = Graph(":memory:")
# Add nodes
g.upsert_node("alice", {"name": "Alice", "age": 30}, label="Person")
g.upsert_node("bob", {"name": "Bob", "age": 25}, label="Person")
# Add edges
g.upsert_edge("alice", "bob", {"since": 2020}, rel_type="KNOWS")
# Query
print(g.stats()) # {'nodes': 2, 'edges': 1}
print(g.get_neighbors("alice")) # [{'id': 'bob', ...}]
print(g.node_degree("alice")) # 1
# Graph algorithms
ranks = g.pagerank()
communities = g.community_detection()
# Raw Cypher when needed
results = g.query("MATCH (a)-[:KNOWS]->(b) RETURN a.name, b.name")
Low-Level Cypher API
For complex queries or when you need full control:
from graphqlite import connect
db = connect("graph.db")
db.cypher("CREATE (a:Person {name: 'Alice', age: 30})")
db.cypher("CREATE (b:Person {name: 'Bob', age: 25})")
db.cypher("""
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:KNOWS]->(b)
""")
results = db.cypher("MATCH (a:Person)-[:KNOWS]->(b) RETURN a.name, b.name")
for row in results:
print(f"{row['a.name']} knows {row['b.name']}")
API Reference
Graph Class
from graphqlite import Graph, graph
# Constructor
g = Graph(db_path=":memory:", namespace="default", extension_path=None)
# Or use the factory function
g = graph(":memory:")
Node Operations
| Method | Description |
|---|---|
upsert_node(node_id, props, label="Entity") |
Create or update a node |
get_node(node_id) |
Get node by ID |
has_node(node_id) |
Check if node exists |
delete_node(node_id) |
Delete node and its edges |
get_all_nodes(label=None) |
Get all nodes, optionally by label |
Edge Operations
| Method | Description |
|---|---|
upsert_edge(source, target, props, rel_type="RELATED") |
Create edge between nodes |
get_edge(source, target) |
Get edge properties |
has_edge(source, target) |
Check if edge exists |
delete_edge(source, target) |
Delete edge |
get_all_edges() |
Get all edges |
Graph Queries
| Method | Description |
|---|---|
node_degree(node_id) |
Count edges connected to node |
get_neighbors(node_id) |
Get adjacent nodes |
get_node_edges(node_id) |
Get all edges for a node |
stats() |
Get node/edge counts |
query(cypher) |
Execute raw Cypher query |
Graph Algorithms
Centrality
| Method | Description |
|---|---|
pagerank(damping=0.85, iterations=20) |
PageRank importance scores |
degree_centrality() |
In/out/total degree for each node |
betweenness_centrality() |
Betweenness centrality scores |
closeness_centrality() |
Closeness centrality scores |
eigenvector_centrality(iterations=100) |
Eigenvector centrality scores |
Community Detection
| Method | Description |
|---|---|
community_detection(iterations=10) |
Label propagation communities |
louvain(resolution=1.0) |
Louvain modularity optimization |
leiden_communities(resolution, seed) |
Leiden algorithm (requires graspologic) |
Connected Components
| Method | Description |
|---|---|
weakly_connected_components() |
Weakly connected components |
strongly_connected_components() |
Strongly connected components |
Path Finding
| Method | Description |
|---|---|
shortest_path(source, target, weight) |
Dijkstra's shortest path |
astar(source, target, lat, lon) |
A* with optional heuristic |
all_pairs_shortest_path() |
All-pairs shortest paths (Floyd-Warshall) |
Traversal
| Method | Description |
|---|---|
bfs(start, max_depth=-1) |
Breadth-first search |
dfs(start, max_depth=-1) |
Depth-first search |
Similarity
| Method | Description |
|---|---|
node_similarity(n1, n2, threshold, top_k) |
Jaccard similarity |
knn(node, k=10) |
K-nearest neighbors |
triangle_count() |
Triangle counts and clustering coefficients |
Export
| Method | Description |
|---|---|
to_rustworkx() |
Export to rustworkx PyDiGraph (requires rustworkx) |
Batch Operations
# Batch insert nodes (upsert semantics)
g.upsert_nodes_batch([
("n1", {"name": "Alice"}, "Person"),
("n2", {"name": "Bob"}, "Person"),
])
# Batch insert edges (upsert semantics)
g.upsert_edges_batch([
("n1", "n2", {"weight": 1.0}, "KNOWS"),
])
Bulk Insert (High Performance)
For maximum throughput when building graphs from external data, use the bulk insert methods. These bypass Cypher parsing entirely and use direct SQL, achieving 100-500x faster insert rates.
# Bulk insert nodes - returns dict mapping external_id -> internal_rowid
id_map = g.insert_nodes_bulk([
("alice", {"name": "Alice", "age": 30}, "Person"),
("bob", {"name": "Bob", "age": 25}, "Person"),
("charlie", {"name": "Charlie"}, "Person"),
])
# Bulk insert edges using the ID map - no MATCH queries needed!
edges_inserted = g.insert_edges_bulk([
("alice", "bob", {"since": 2020}, "KNOWS"),
("bob", "charlie", {"since": 2021}, "KNOWS"),
], id_map)
# Or use the convenience method for both
result = g.insert_graph_bulk(nodes=nodes, edges=edges)
print(f"Inserted {result.nodes_inserted} nodes, {result.edges_inserted} edges")
# Resolve existing node IDs (for edges to pre-existing nodes)
resolved = g.resolve_node_ids(["alice", "bob"])
| Method | Description |
|---|---|
insert_nodes_bulk(nodes) |
Insert nodes, returns ID mapping dict |
insert_edges_bulk(edges, id_map=None) |
Insert edges using ID map |
insert_graph_bulk(nodes, edges) |
Insert both, returns BulkInsertResult |
resolve_node_ids(ids) |
Resolve external IDs to internal rowids |
Connection Class
from graphqlite import connect, wrap
# Open new connection
db = connect("graph.db")
db = connect(":memory:")
# Wrap existing sqlite3 connection
import sqlite3
conn = sqlite3.connect("graph.db")
db = wrap(conn)
Methods
| Method | Description |
|---|---|
cypher(query) |
Execute Cypher query, return results |
execute(sql) |
Execute raw SQL |
close() |
Close connection |
CypherResult
Results from cypher() calls:
results = db.cypher("MATCH (n) RETURN n.name")
len(results) # Number of rows
results[0] # First row as dict
results.columns # Column names
results.to_list() # All rows as list
for row in results:
print(row["n.name"])
Utility Functions
from graphqlite import escape_string, sanitize_rel_type, CYPHER_RESERVED
# Escape strings for Cypher queries
safe = escape_string("It's a test") # "It\\'s a test"
# Sanitize relationship types
rel = sanitize_rel_type("has-items") # "has_items"
rel = sanitize_rel_type("CREATE") # "REL_CREATE" (reserved word)
# Set of Cypher reserved keywords
if "MATCH" in CYPHER_RESERVED:
print("MATCH is reserved")
Extension Path
The extension is located automatically. To specify a custom path:
db = connect("graph.db", extension_path="/path/to/graphqlite.dylib")
Or set the GRAPHQLITE_EXTENSION_PATH environment variable.
Troubleshooting
See FAQ.md for common issues and solutions.
License
MIT
Metadata
Release files for graphqlite 0.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| graphqlite-0.9.0.tar.gz | 475.5 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| graphqlite-0.9.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| graphqlite-0.9.0-py3-none-manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.28+ ARM64 | Details |
| graphqlite-0.9.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| graphqlite-0.9.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
Total release size: 2.8 MB
Release files / graphqlite-0.9.0.tar.gz
| Download URL | graphqlite-0.9.0.tar.gz |
|---|---|
| Size | 475.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
26bd94486c110fce60903a2615967ef2ed5ffffc22c6452890b553866657bf29
|
|
BLAKE2b-256 checksum How to use checksums |
41c449702f21b25cc402339943e9c2fd3017a36b9ec55ce317c68faa1f04c278
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / graphqlite-0.9.0-py3-none-win_amd64.whl
| Download URL | graphqlite-0.9.0-py3-none-win_amd64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0b12086c76432b7cc1b610f4d2c82ac6b3754b0219e6cef9b94ede671d040adc
|
|
BLAKE2b-256 checksum How to use checksums |
0d4663aa0d6abf39c569ac0d3adabdc4f75ea83cce25e874a6a42063af3de076
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / graphqlite-0.9.0-py3-none-manylinux_2_28_aarch64.whl
| Download URL | graphqlite-0.9.0-py3-none-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 376.6 kB |
| Tags | Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
1406ec9b82a205a9bcb68ad678481d8c54df19b3810bb1b2fda406c9b96e3580
|
|
BLAKE2b-256 checksum How to use checksums |
9574d4696c0933df935f2471b77b2da898af970419f8d3d3c7a0475d416cbcb1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / graphqlite-0.9.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | graphqlite-0.9.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 380.4 kB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
baf9196bdd8df5a9f26e9f71805e1f09ae8202e05eee27bb40131f3fedf926db
|
|
BLAKE2b-256 checksum How to use checksums |
ed116ebe96a0cdda6114c1206cba169e99becc5c7bd93bf52d631b58d0b11bfa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / graphqlite-0.9.0-py3-none-macosx_11_0_arm64.whl
| Download URL | graphqlite-0.9.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 300.3 kB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
4b260a6b790ff80f4d57f17871d6aee0b30b2589856293d059de01262a49d4ff
|
|
BLAKE2b-256 checksum How to use checksums |
eaec5cc7a9282dc9795856d8cb17f8fad4353b224c6289039b23c427c7e28f85
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|