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.10.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.10.0.tar.gz | 487.4 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| graphqlite-0.10.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| graphqlite-0.10.0-py3-none-manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.28+ ARM64 | Details |
| graphqlite-0.10.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| graphqlite-0.10.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
Total release size: 2.9 MB
Release files / graphqlite-0.10.0.tar.gz
| Download URL | graphqlite-0.10.0.tar.gz |
|---|---|
| Size | 487.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
43b0b782799258361b5c90445cc22f41f8da302075a7ef6f80475bb52dbe4d4f
|
|
BLAKE2b-256 checksum How to use checksums |
1023d3d9ed24c3d098be1f0fa755400277f0d16e89439c67597d7326b82c0011
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Release files / graphqlite-0.10.0-py3-none-win_amd64.whl
| Download URL | graphqlite-0.10.0-py3-none-win_amd64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c711318246ae54531d903f3cbb0a274255f89d4c8b1546ecba24a9b7f357e1fd
|
|
BLAKE2b-256 checksum How to use checksums |
2472b7d5e7d6dbf16c2df62fcdad487c8eeb2330e5b4f9d7d3e0fd64fae2dfe4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Release files / graphqlite-0.10.0-py3-none-manylinux_2_28_aarch64.whl
| Download URL | graphqlite-0.10.0-py3-none-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 415.2 kB |
| Tags | Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
a582e932dbe5c81ada37100696a837d0b2e24c4b01616402785be7c610bfca66
|
|
BLAKE2b-256 checksum How to use checksums |
5264c64bb12c3865cb96eef21e35f0ad68d95ab7e6fd6e8fee8a9c6e81cf3da5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Release files / graphqlite-0.10.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | graphqlite-0.10.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 419.3 kB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
83b71f9b6978d70f8390af9f7ef6e71ffe4f9ea85781e2d2e7994ca53a34e43f
|
|
BLAKE2b-256 checksum How to use checksums |
773453fd9deb70231e6fc0c087c2c06e2572b0c8a55ef6022c98e46dfa6a6409
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Release files / graphqlite-0.10.0-py3-none-macosx_11_0_arm64.whl
| Download URL | graphqlite-0.10.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 331.8 kB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
7e60bdf83f430fb30657049d3d7d47fddac5b6a926ff96a22bdcf07fc6ebbc1e
|
|
BLAKE2b-256 checksum How to use checksums |
4d8dfd02639a0e1deecf3b4818c277faf484e6a78ed5151b5593d576ed761f94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|