Software

ArcadeDB in Python

The Python package for ArcadeDB. It runs the engine inside your process, for documents, graphs, vectors and time series, with no service to start. Install it with uv.

Illustration of three stacked slabs with the middle one in rose, inside a larger outlined square, standing for a database running inside a process.

What it is

ArcadeDB inside your Python process.

ArcadeDB in Python is the Python package for ArcadeDB. It runs the same engine inside your process, so there is no service to start. We maintain it within the ArcadeDB project, in ArcadeData/arcadedb-python.

The default package, arcadedb, is a native build that needs no Java. arcadedb-jvm bundles a Java runtime instead, for heavy, long-running loads. Both use import arcadedb.

Use it for notebooks, tests, single-node services and agent tooling. When more than one process or machine needs the data, or you need replication, failover or TLS, run the official server instead. ArcadeDB covers the server, its protocols, backups and replication, and explains the statements used below.

Install

Install it and run a query.

uv add arcadedb

Schema and queries are SQL, or openCypher for graphs, through db.command and db.query. That covers documents, graphs, vectors and time series, and ArcadeDB shows the statements for each. A write needs a transaction. A read does not.

import arcadedb

with arcadedb.create_database("./mydb") as db:
    db.command("sql", "CREATE DOCUMENT TYPE Person")
    db.command("sql", "CREATE PROPERTY Person.name STRING")

    with db.transaction():
        db.command("sql", "INSERT INTO Person SET name = ?", "Alice")

    for record in db.query("sql", "SELECT FROM Person"):
        print(record.get("name"))

Only one process can open an embedded database at a time. When a second process needs the data, start a server from the same package, with Studio.

with arcadedb.create_server("./databases", root_password="password123") as server:
    db = server.create_database("mydb")
    print("Studio:", server.get_studio_url())

Your code keeps its direct access and everything else connects over HTTP. That server stops when your script does. The on-disk format is the same as the official server’s, so you can export a database from one and import it into the other.

Graphs

Vertices, edges and traversals.

The statements are SQL, run through db.command. You declare vertex and edge types, then connect vertices that already exist.

with db.transaction():
    db.command("sql", "CREATE VERTEX TYPE Person")
    db.command("sql", "CREATE EDGE TYPE Knows")
    db.command("sql", "INSERT INTO Person SET name = 'Alice'")
    db.command("sql", "INSERT INTO Person SET name = 'Bob'")
    db.command("sql", """
        CREATE EDGE Knows
        FROM (SELECT FROM Person WHERE name = 'Alice')
        TO (SELECT FROM Person WHERE name = 'Bob')
    """)

You can traverse with SQL or with openCypher, as on the server.

result = db.query("opencypher", """
    MATCH (p:Person {name: $name})-[:Knows]->(friend:Person)
    RETURN friend.name
""", {"name": "Alice"})

For a large graph, load it with GraphBatch instead of one statement at a time. In our measurements it loaded 50,000 vertices and about a million edges in roughly 7.5 seconds, against about 30 seconds one element at a time.

Vectors

Store embeddings and search them.

The vector statements are SQL too, run through db.command and db.query. ArcadeDB explains the index and the search.

db.command("sql", "CREATE VERTEX TYPE Doc")
db.command("sql", "CREATE PROPERTY Doc.text STRING")
db.command("sql", "CREATE PROPERTY Doc.embedding ARRAY_OF_FLOATS")
db.command("sql", """
    CREATE INDEX ON Doc (embedding)
    LSM_VECTOR
    METADATA {"dimensions": 3, "similarity": "COSINE"}
""")

rows = db.query(
    "sql",
    "SELECT vectorNeighbors('Doc[embedding]', :vec, 2) AS res",
    {"vec": [0.9, 0.1, 0.0]},
).to_list()

Loading

Getting a lot of data in.

For documents and rows, db.insert_many(...) batches rows across the Java boundary, and db.insert_columns(...) takes a DataFrame or numpy arrays. For graphs, use GraphBatch. Against a server, use POST /api/v1/batch/{db} for graphs and the line-protocol endpoint for time series.

IMPORT DATABASE and EXPORT DATABASE work as on the server, and ArcadeDB shows them. Create indexes after a big load where you can.

Paper

The design and the measurements.

Our SciPy paper describes the bindings and measures them against SQLite, DuckDB, LadybugDB, and Chroma. It is on the ArcadeDB in Python research page.