GestaltDB
GestaltDB is a pure Python graph database toolkit for attributed graphs. It stores nodes, edges, labels, typed adjacency records, and property indexes on embedded key-value backends.
Documentation: https://mylonasc.github.io/gestaltdb/
Install From PyPI
With pip:
python -m pip install gestaltdb
With uv:
uv add gestaltdb
Install columnar ingestion dependencies:
python -m pip install "gestaltdb[arrow,polars]"
Install all optional backends and serializers:
python -m pip install "gestaltdb[all]"
Optional extras include lmdb, leveldb, rocksdb, arrow, polars, fast-ingest, msgpack, protobuf, bloom, docs, dev, and all.
Basic Example
from tempfile import TemporaryDirectory
from gestaltdb.graphdb import Edge, GraphDB, Node
from gestaltdb.kvstores import LevelDBStore
from gestaltdb.serializers import PickleSerializer
with TemporaryDirectory() as tmpdir:
graph = GraphDB(LevelDBStore(path=f"{tmpdir}/graph"), PickleSerializer())
graph.put_node(Node(node_id="alice", labels=["Person"], properties={"name": "Alice"}))
graph.put_node(Node(node_id="bob", labels=["Person"], properties={"name": "Bob"}))
graph.put_edge(Edge(
edge_id="alice-knows-bob",
source="alice",
target="bob",
properties={"type": "knows", "since": 2024},
))
result = graph.query('MATCH (a:Person {name: "Alice"}) MATCH (a)-[:knows]->(b) RETURN a.id, b.name')
print(result.records)
graph.close()
Arrow Ingestion Example
This example ingests entity columns from PyArrow arrays. JSONSerializer lets GestaltDB build node and edge payloads from structured columns.
from tempfile import TemporaryDirectory
import pyarrow as pa
from gestaltdb.graphdb import GraphDB
from gestaltdb.kvstores import LevelDBStore
from gestaltdb.serializers import JSONSerializer
from gestaltdb import IndexMaintenanceMode
with TemporaryDirectory() as tmpdir:
graph = GraphDB(LevelDBStore(path=f"{tmpdir}/graph"), JSONSerializer())
graph.create_node_property_index("name")
result = graph.ingest_arrow(
pa.array(["alice", "bob", "carol"]),
pa.array(["alice-knows-bob", "bob-knows-carol"]),
pa.array(["alice", "bob"]),
pa.array(["bob", "carol"]),
pa.array(["knows", "knows"]),
labels=pa.array([["Person"], ["Person"], ["Person"]]),
node_properties={"name": pa.array(["Alice", "Bob", "Carol"]), "age": pa.array([34, 36, 29])},
edge_properties={"since": pa.array([2024, 2025])},
index_mode=IndexMaintenanceMode.DEFER_REBUILD,
)
print(result) # {'nodes': 3, 'edges': 2, 'rebuilt_indexes': ..., 'stale_indexes': ()}
result = graph.query('MATCH (a:Person {name: "Alice"}) MATCH (a)-[:knows]->(b) RETURN a.id, b.name')
print(result.records)
graph.close()
Polars Ingestion Example
This example ingests the same graph from Polars DataFrames. Property columns are converted into node and edge payloads during ingestion.
from tempfile import TemporaryDirectory
import polars as pl
from gestaltdb.graphdb import GraphDB
from gestaltdb.kvstores import LevelDBStore
from gestaltdb.serializers import JSONSerializer
from gestaltdb import IndexMaintenanceMode
nodes = pl.DataFrame({
"node_id": ["alice", "bob", "carol"],
"labels": [["Person"], ["Person"], ["Person"]],
"name": ["Alice", "Bob", "Carol"],
"age": [34, 36, 29],
})
edges = pl.DataFrame({
"edge_id": ["alice-knows-bob", "bob-knows-carol"],
"source": ["alice", "bob"],
"target": ["bob", "carol"],
"edge_type": ["knows", "knows"],
"since": [2024, 2025],
})
with TemporaryDirectory() as tmpdir:
graph = GraphDB(LevelDBStore(path=f"{tmpdir}/graph"), JSONSerializer())
graph.create_node_property_index("name")
graph.ingest_polars(
nodes,
edges,
node_property_columns=["name", "age"],
edge_property_columns=["since"],
index_mode=IndexMaintenanceMode.DEFER_REBUILD,
)
result = graph.query('MATCH (a:Person) MATCH (a)-[:knows]->(b) RETURN a.name, b.name ORDER BY a.name')
print(result.records)
graph.close()
Install From A Checkout
From a local checkout:
uv sync
Install into another project:
uv add /path/to/gestaltdb
With pip:
python -m pip install /path/to/gestaltdb
Backend and Ingestion Recommendations
For the current library:
- Use
LevelDBStorefor small local graphs, examples, and straightforward embedded use. - Use
PyRexStore/RocksDB for large append-only loads and Arrow/Polars columnar ingestion. - Use
LMDBStorewhen LMDB's storage model is desirable and you can sizemap_sizeahead of loading. - Use
JSONSerializerwithGraphDB.ingest_polarsorGraphDB.ingest_arrowwhen input data is already tabular and JSON-compatible. - Use pre-serialized
node_valueandedge_valuecolumns when upstream data already has serializer-compatible payload bytes. - Keep
IndexMaintenanceMode.MAINTAINfor incremental writes that need indexes ready immediately. - Use
IndexMaintenanceMode.DEFERorDEFER_REBUILDfor bulk loads when you want to move secondary-index work out of the write path.
Measured locally on 100k nodes and 500k edges, RocksDB native columnar ingestion was 1.16x faster end-to-end than LevelDB on the same Python JSON payload path, and Polars JSON payload construction was 1.86x faster than Python JSON serialization. Deferred indexing made the write phase 8.72x faster, but immediate full rebuild made total ingest-plus-rebuild 17.2% slower for that subset. Treat these as workload-specific guidance and benchmark your graph shape, serializer, and indexes.
Features
- Attributed
NodeandEdgeobjects with stable IDs. - Native node labels and typed edge traversal through
edge.properties["type"]. - LMDB, LevelDB, and RocksDB/PyRex storage backends.
- Pickle, JSON, MessagePack, and Protobuf serializers.
- Label, relationship type, property, composite, and range indexes.
- Read-only Cypher subset for indexed scans, typed traversal, filtering, ordering, limits, and chained
MATCHclauses. - Bulk and columnar ingestion helpers for Arrow and Polars.
- Typed path and subgraph sampling.
See the full documentation for backend selection, indexing, Cypher syntax, ingestion, sampling, and benchmarks.
Name origin
The name GestaltDB is inspired by Gestalt psychology and the idea that the whole is something more than its parts.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gestaltdb-0.5.1.tar.gz.
File metadata
- Download URL: gestaltdb-0.5.1.tar.gz
- Upload date:
- Size: 70.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
573ca75ef0d4377e144d2852ec3624809a273c1f55cc2654b9f9fd5a0a00365c
|
|
| MD5 |
a8cf53f84bc5d0cd5ea09318d73fdef3
|
|
| BLAKE2b-256 |
51448e4c5276647a1a0d0b370bb8243c85eb020531f26adc6fd51112478672e7
|
Provenance
The following attestation bundles were made for gestaltdb-0.5.1.tar.gz:
Publisher:
publish.yml on mylonasc/gestaltdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gestaltdb-0.5.1.tar.gz -
Subject digest:
573ca75ef0d4377e144d2852ec3624809a273c1f55cc2654b9f9fd5a0a00365c - Sigstore transparency entry: 2538712343
- Sigstore integration time:
-
Permalink:
mylonasc/gestaltdb@26307279ae44a55482785744088811648ba9327f -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/mylonasc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@26307279ae44a55482785744088811648ba9327f -
Trigger Event:
release
-
Statement type:
File details
Details for the file gestaltdb-0.5.1-py3-none-any.whl.
File metadata
- Download URL: gestaltdb-0.5.1-py3-none-any.whl
- Upload date:
- Size: 55.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0403e148aba36146e90cb6d64f0d0ed57f6f1cf1f1b6e14b2ea47678a469314
|
|
| MD5 |
6efed1de392d26f43c705bd129cfff20
|
|
| BLAKE2b-256 |
9d002f0e3cd3e67546f4cfbb90afdcc4f51f6185420b241411d78edfb66c42c1
|
Provenance
The following attestation bundles were made for gestaltdb-0.5.1-py3-none-any.whl:
Publisher:
publish.yml on mylonasc/gestaltdb
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gestaltdb-0.5.1-py3-none-any.whl -
Subject digest:
d0403e148aba36146e90cb6d64f0d0ed57f6f1cf1f1b6e14b2ea47678a469314 - Sigstore transparency entry: 2538712479
- Sigstore integration time:
-
Permalink:
mylonasc/gestaltdb@26307279ae44a55482785744088811648ba9327f -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/mylonasc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@26307279ae44a55482785744088811648ba9327f -
Trigger Event:
release
-
Statement type: