This directory contains hands-on examples demonstrating ArcadeDB Python bindings in action.
examples/ directory for proper file paths and database creation.
# Navigate to the examples directory first
cd examples
# Then run the basic document store example
uv run --with arcadedb python 01_simple_document_store.py
# or install the package first: uv add arcadedb, then uv run python 01_simple_document_store.pyThe dataset downloader is download_data.py: its docstring lists the datasets, and uv run --no-project python download_data.py --help the options.
Examples 02, 03, 14, 15 and 25 use Java objects and run on arcadedb-jvm only (scripts/native_examples_skip.txt).
Document Types | CRUD Operations | Rich Data Types | NULL Handling
Perfect introduction to ArcadeDB basics:
- Creating embedded databases (no server needed)
- Document types with comprehensive schema (STRING, BOOLEAN, DATE, DATETIME, DECIMAL, FLOAT, INTEGER, LIST, etc.)
- CRUD operations with ArcadeDB SQL
- NULL value handling (INSERT, UPDATE, queries with IS NULL)
- Transactions and data validation
- DATE and DATETIME values written as string literals and read back as Python
date/datetime - Arrays/lists with type safety
Learn: Document storage, SQL dialect, schema design, NULL handling, data type diversity
Vertex Types | Edge Types | Graph Traversal | OpenCypher vs SQL MATCH | NULL Handling
Complete social network modeling with graph database:
- Creating vertex types (Person) and edge types (FRIEND_OF) with rich properties
- NULL value handling for optional fields (email, phone, reputation)
- Bidirectional relationships with metadata (since, closeness)
- Graph traversal patterns (friends, friends-of-friends, mutual connections)
- Comparing OpenCypher (recommended for graph patterns) with the older SQL MATCH syntax
- Variable-length path queries (
*1..3) and graph aggregations - NULL filtering (IS NULL queries for missing contact info)
- Relationship property queries (closeness filtering)
Learn: Graph schema design, relationship modeling, multi-language querying, NULL handling in graphs
๐ 03_vector_search.py
Vector Embeddings | HNSW (JVector) Index | Semantic Search | Performance Analysis
Semantic similarity search with AI/ML:
- Creating vector-ready schema (
ARRAY_OF_FLOATS) for embeddings - Generating mock embeddings clustered by category (seeded with
zlib.crc32, so every run builds the same embeddings) - Building a JVector (HNSW) index for nearest-neighbor search
- Running top-k similarity queries and inspecting distance scores
- Measuring insertion, indexing, and query phases
Learn: Vector data modeling, index creation strategy, and practical semantic search behavior
CSV Import | Schema Definition | Batch Processing | Explicit Schema Mapping
High-performance CSV import for document data:
- Importing the MovieLens dataset (movies, ratings, links, and tags)
- Explicit schema mapping (integer-like columns to LONG, decimals to DOUBLE, text to
STRING) and batched parameterized
INSERT - Handling NULL values and data cleaning
- Batch processing for optimal performance
- Index creation strategies
Note: Download the MovieLens dataset first with uv run --no-project python download_data.py movielens-<size>.
Learn: ETL patterns, bulk import, schema management, performance tuning
๐ธ๏ธ 05_csv_import_graph.py
Graph Import | Edge Creation | Foreign Keys | Performance Benchmarking
Complex graph construction from CSV data:
- Importing Users, Movies, and Ratings
- Creating edges (User-[RATED]->Movie) from foreign keys
- Handling large-scale edge creation (millions of edges)
- Benchmarking different import strategies (GraphBatch vs synchronous transactions)
- Memory management for large graphs
Learn: Graph ETL, edge creation patterns, performance optimization, memory management
Recommendation Engine | Vector Search vs Graph Traversal | Real-world Use Case
Building a movie recommendation engine:
- Generating embeddings for movies (Title + Genres) with two sentence-transformers models
- "More like this" recommendations for a given movie
- Graph-based collaborative filtering (movies rated highly by users who liked the query movie), in a full and a sampled fast mode
- Vector-similarity recommendations, compared side by side with the graph results
Learn: Recommendation systems, and how graph collaborative filtering and vector similarity differ on the same data
๐๏ธ 07_stackoverflow_tables_oltp.py
Table OLTP | Mixed CRUD Workload | Cross-DB Benchmarking
Table-oriented Stack Overflow OLTP benchmark:
- Loads Stack Overflow XML tables and runs a mixed OLTP workload (CRUD)
- CRUD operations are point-oriented and randomly target one table per operation
- For cross-database comparability, running with
--threads 1is recommended
Learn: Table-oriented OLTP benchmarking and cross-database workload fairness
Table OLAP | Fixed Query Suite | Dockerized Runs
Table-oriented Stack Overflow OLAP benchmark:
- Loads all Stack Overflow XML tables and runs a fixed OLAP query suite
- Re-launches itself in a Docker container when
dockeris available (and, for ArcadeDB, a wheel is present indist); otherwise it runs natively, and no container enforces--mem-limit - Reports load/index timing and repeated query runs
Learn: Analytical query benchmarking over table-shaped data
Graph OLTP | Deterministic Verification | Cross-DB Benchmarking
Stack Overflow property-graph OLTP benchmark with mixed CRUD operations:
- Supports deterministic single-thread verification through DB-scoped baselines
--verify-single-thread-serieschecks repeatability for one DB/mode, not strict cross-DB equality- Summary files report real post-run filesystem usage in
du_mib, whiledisk_after_*fields are benchmark-reported logical sizes - Per-operation latency is derived from
latency_summary.ops.{50,95,99}and converted from seconds to milliseconds; counts come fromop_counts
Learn: OLTP workload comparison, verification semantics, and benchmark result interpretation
Graph OLAP | OpenCypher Query Suite | Cross-DB Benchmarking
Fixed query-suite benchmark for Stack Overflow graph analytics:
- ArcadeDB preloads through
db.graph_batch(...)with two-way edges - ArcadeDB query execution is Cypher-only in this example path
Learn: OLAP graph query benchmarking and directed-edge traversal assumptions
๐๏ธ 11_vector_index_build.py
Vector Index Build | Build-Only Benchmark | Multi-Backend Comparison
Build-only vector index benchmark:
- Backends: ArcadeDB (embedded), pgvector, Qdrant, Milvus, FAISS, LanceDB
- Datasets: MSMARCO and Stack Overflow embedding vectors
- For client-server backends, peak RSS combines client process and server process tree
Learn: Vector index build cost and memory comparison across backends
๐ 12_vector_search.py
Vector Search | Search-Only Benchmark | ef_search Sweeps
Search-only vector benchmark that reuses Example 11 output:
- Backends: ArcadeDB (embedded), FAISS, LanceDB, brute-force NumPy scan, pgvector, Qdrant, Milvus
- Sweeps explicit
ef_searchvalues for HNSW-style backends - Measures client + server process RSS for client-server backends
Learn: Search latency/recall tradeoffs and backend-specific search parameters
Hybrid SQL + Graph + Vector | Standalone Workflow
Standalone Stack Overflow workflow combining documents, graph edges, embeddings, and hybrid queries:
- Preload uses synchronous transaction-batched ingest rather than
IMPORT DATABASE - Graph edge creation uses RID-based directed endpoints
Learn: End-to-end hybrid querying across SQL, OpenCypher, and vector search
โฑ๏ธ 14_lifecycle_timing.py
JVM Startup | DB Create/Open | Transaction Load | Query Phases | Reopen Timing
Lifecycle benchmark for embedded ArcadeDB with mixed workloads:
- Measures JVM startup time in-process
- Creates schema and loads table/graph/vector data
- Runs query workload before and after reopen
- Prints per-run timings and final averages
- Uses random
/tmpdatabase path and always cleans up
Learn: Cold-start behavior, lifecycle costs, and realistic mixed-workload timing patterns
Transactional SQL vs Async SQL vs SQL Import | Table Ingest Benchmark
Synthetic multi-table ingest comparison harness:
- Runs four modes against the same generated dataset shape
- Modes: transactional SQL, async SQL, SQL
IMPORT DATABASE, anddb.import_documents(...) - Includes parity checks so final table counts must match before timing results should be trusted
- Current outcome is workload-dependent; SQL import can win on some table-heavy shapes
- The async SQL arm is a comparison arm, not a recommendation, and
--async-parallelaccepts only 1. For bulk document ingest usedb.insert_many(...)(see Bulk loads and commit size)
Learn: Table-ingest tradeoffs for embedded Python workloads
Transactional SQL vs Async SQL vs SQL Import | Graph Ingest Benchmark
Synthetic graph ingest comparison harness:
- Runs transactional SQL, GraphBatch, async SQL, and SQL import on equivalent vertex/edge data
- Includes parity checks on final vertex and edge counts
- The async SQL arm is pinned to
--async-parallel 1. GraphBatch is the recommended bulk graph ingest path (see Bulk loads and commit size)
Learn: Graph-ingest tradeoffs for embedded Python workloads
โฑ๏ธ 17_timeseries_end_to_end.py
Time Series SQL | Tagged Points | Range Queries | Bucket Aggregation
SQL-first time-series workflow from Python bindings:
- Creates a
TIMESERIES TYPEwith timestamp, tags, and numeric fields - Inserts tagged samples inside a transaction
- Queries a time range for a single sensor
- Aggregates with
ts.timeBucket('1h', ts) - Demonstrates the current bindings posture: use SQL rather than a Python-native time-series API
Learn: How to drive ArcadeDB time-series capabilities from Python without adding a new public object model
GEOSPATIAL Indexes | WKT Geometry | Indexed Predicates | Fallback Queries
SQL-first geospatial workflow:
- stores points and polygons as WKT
- builds a GEOSPATIAL index
- runs indexed
withinandintersectspredicates - compares indexed behavior with fallback behavior after dropping the index
Learn: How to drive ArcadeDB geospatial features from Python through SQL without adding a Python-native spatial wrapper
#๏ธโฃ 19_hash_index_exact_match.py
HASH Index | Unique And Non-Unique Lookup | Schema Inspection | Duplicate Rejection
SQL-first exact-match workflow:
- builds unique and non-unique HASH indexes
- exercises exact-match lookup semantics for present and missing keys
- inspects created indexes from schema metadata
- verifies duplicate-key rejection for the unique case
Learn: When HASH indexes are the right tool for equality-heavy Python workloads
Graph Algorithms | shortestPath | dijkstra | astar | Route Comparison
SQL-first route-planning workflow:
- creates a directed multi-modal transport graph
- compares minimum-hop routing against weighted routing
- optimizes for distance, duration, and risk
- cross-checks
astar(...)againstdijkstra(...)
Learn: How to use ArcadeDB graph algorithms from Python without introducing a separate algorithm API layer
๐ธ๏ธ 21_graph_analytical_view_sql.py
Graph Analytical View | SQL DDL | Schema Metadata | Rebuild Lifecycle
SQL-first Graph Analytical View workflow:
- generates a larger synthetic transport graph with 100,000 base cities by default
- creates a named GAV with vertex and edge property filters
- polls
schema:graphAnalyticalViewsuntil the async build isREADY - shows
OFFmode becomingSTALEafter graph writes - rebuilds the view and then switches to
SYNCHRONOUSupdates - reopens the database to confirm persisted GAV restoration
Learn: How to use Graph Analytical Views from Python without introducing a dedicated Python object API
๐ข 22_numpy_bulk_io.py
numpy Bulk I/O | insert_many | append_samples | Columnar Export
Batched Python/Java boundary crossings for bulk workloads:
- Bulk document ingest with
Database.insert_many(rows as one JSON batch), transactional andparallel=True - Time-series ingest straight from numpy arrays via
AsyncExecutor.append_samples - Time-bucketed aggregation over the native
TIMESERIEStype - Columnar export with
to_columns(): scalar columns as 1-D numpy arrays and embeddings as a contiguous 2-D array
Learn: Why one crossing per batch (not per value) makes bulk ingest and export fast
Server Mode | HTTP API | Bearer Auth | Mixed Access Pattern
Embedded-first server workflow, all in one process:
- starts ArcadeDB server mode from the Python package
- reads server metadata over HTTP
- creates a database through the server-managed Java API
- mixes embedded writes with HTTP queries and updates
- prints the Studio URL; the Studio web UI is in the wheels from 26.11.1, and the earlier 26.10.x wheels do not include it (see the top-level README)
Learn: How to expose an embedded database over HTTP without running a separate container, and when you should reach for the Docker distribution instead
Server HTTP API | Multi-Request Transactions | Database Commands | Line Protocol
Three server features that belong to the HTTP API, shown against the server that
create_server() starts in this process:
- one transaction spanning several requests through the
arcadedb-session-idheader returned by/api/v1/begin/{db}, ended by/commitor/rollback - server-level database commands (
close database,open database) sent to/api/v1/server - writes to a TIMESERIES type through
/api/v1/ts/{db}/writein InfluxDB line protocol, read back with SQL - flags:
--server-root(default: a temp dir),--password, and--http-port(default 2482)
Learn: What a second process needs from the server's HTTP API, with standard-library HTTP only
Sparse Vectors | LSM_SPARSE_VECTOR | Weight Precision | COMPACT INDEX
Two decisions a sparse-retrieval workload should make on purpose:
- weight precision:
LSM_SPARSE_VECTORquantizes posting weights to INT8 by default;"weightQuantization": "FP32"keeps them exact - the settle step:
COMPACT INDEXmerges the LSM segments a bulk load leaves behind - builds the same synthetic corpus once per weight setting (INT8 rescored, INT8 without rescoring, and FP32), compacts each, and reports index size, query time before and after compaction, and each INT8 index's top-10 agreement with FP32
- flags:
--docs(default 20,000),--queries(default 50), and--db-dir
Learn: How weight precision and compaction change sparse index size and query time
Cross-Model Transaction | Vector + Graph + Document | Failure Injection
One operation that touches three models in one transaction:
- a vector search finds the nearest products, a graph hop expands to related products, and a document update bumps a counter on all of them
- injects a failure between the writes N times, inside a transaction (rolled back, never torn) and without one (each write committed on its own, torn every time)
- builds a small synthetic catalogue; no data download
- flags:
--products(default 2,000),--trials(default 20), and--db-path
Learn: Why one transaction across vector, graph, and document writes leaves nothing half-applied after an interruption
DataFrame And Arrow Ingest | pandas | Polars | Arrow | Declared Types
DataFrames and Arrow tables loaded straight into a type, and a result back out as Polars:
- a pandas DataFrame into a document type (timestamps, nulls, a list column), in batches
- a Polars DataFrame into a vertex type, then edges through
graph_batch().new_edges() - an Arrow table into declared
INTEGERandDATETIME_MICROSproperties, and a float column refused before a row is written to_polars()on the result- synthetic data; flags:
--rows(default 100,000) and--db-path - requires
uv add 'arcadedb[pandas,polars]'(or'arcadedb-jvm[pandas,polars]')
Learn: How a DataFrame becomes documents or vertices without a row loop, and what each Arrow type is stored as
Python Functions | Record Events | SQL + openCypher
Two things no query language can express:
db.register_function()makes a Pythonslugifycallable from SQL (SELECT and WHERE) and, aspy.slugify, from openCypher; an exception in the function is a query error- measures the cost of one call on your machine against the same SQL expression
db.on()keeps an audit trail withafter_create/after_update/after_deletecallbacks and vetoes a write with abefore_createcallback that returnsFalse- no data download; flags:
--rows(default 20,000) and--db-path
Learn: When a Python function or callback is the right tool, what it costs, and how errors, threads, and unregistering behave
Agent Memory | Tenant Pre-filter | Vector + Full-Text + Graph | vector.fuse
Hybrid retrieval for an agent memory in one SQL statement instead of three stores:
vector.neighborsrestricted to one tenant BEFORE the top-k (where, ArcadeDB 26.11.1, orfilterwith a RID subquery, 26.10.2 and later), aSEARCH_INDEXfull-text match on the same tenant, both fused by reciprocal rank fusion withvector.fuse, then graph hops (MENTIONS,RELATES) to related entities and facts, kept inside the tenant- shows why: a global top-k followed by a tenant test returns 0 rows when the nearest
neighbours belong to another tenant (the behaviour of Cypher
db.index.vector.queryNodeswithout its{where, filter}options map, new in 26.11.1) - checks that every result row, and every fact reached by a hop, belongs to the tenant
- builds a small synthetic memory (fixed-seed numpy embeddings); no data download
- flags:
--form(where, default, needs 26.11.1; orfilter) and--db-path
Learn: How to filter a vector search by tenant before the top-k and fuse it with full-text and graph context in a single query
Faceted Queries | COLUMNAR Index | FACETS Clause | result_set.facets
The counts of a search sidebar next to the rows of a query:
CREATE INDEX ... COLUMNARon the properties that the facets count- one query with a
TERMSfacet (the 3 biggest categories) and aRANGESfacet (price bands) next to a page of 5 rows, thenSTATSwithDISTINCT, then a calendarHISTOGRAM - the facets cover all the matches of the
WHERE, not only the rows of the page - checks every count against the same count made in Python over the inserted rows
- needs engine 26.12.1 or later: on an older engine it prints one line and exits with status 0
- generated data, no download; flags:
--rows(default 1,200) and--db-path
Learn: How to ask for counts per value, range and month in the same statement as the rows, and how to read them from the result set as a dict
- Run from examples/ directory - Always execute examples from
examples/for correct file paths - Start with Example 01 - Foundation for all ArcadeDB concepts
- Use directed graph assumptions - Graph examples keep edge direction semantics.
Every graph example stores both directions of each edge (the engine default). Load
one-way edges only into an edge type declared one-way (
CREATE EDGE TYPE ... UNIDIRECTIONAL): a one-way load into a two-way type makes any query the planner walks from the target end return 0 rows with no error (ArcadeData/arcadedb#8625) - Database files persist - Examples preserve data for inspection
- Output is educational - Check console output to understand operations
- Experiment freely - Examples clean up and recreate on each run
Examples are designed to be educational, and each includes detailed comments and step-by-step explanations. Most run on their own; 05 reads Example 04's database, 06 reads Example 05's, and 12 reuses Example 11's.