Skip to content

Record Wrappers (Document, Vertex, Edge)

The Python API provides wrapper classes for database records: Document, Vertex, and Edge.

Compatibility-oriented API

Prefer SQL/OpenCypher via db.command(...) and db.query(...) for normal schema, CRUD, and graph workflows. This page documents the wrapper layer for compatibility, targeted record manipulation, and wrapper-specific traversal helpers.

Overview

Class Purpose Usage
Document Base wrapper for all records (documents, vertices, edges) Property access, modification, deletion
Vertex Wrapper for graph vertices Creating edges, traversal
Edge Wrapper for graph edges Accessing source/target vertices

Document Wrapper

The Document class is the base wrapper for all record types. Use it for documents and as the base class for Vertex and Edge.

Creating Documents

For application code, prefer INSERT INTO ... statements. Use db.new_document(...) when you explicitly need the wrapper object in hand.

import arcadedb_embedded as arcadedb
from arcadedb_embedded.graph import Document, Vertex, Edge

with arcadedb.create_database("./mydb") as db:
    db.command("sql", "CREATE DOCUMENT TYPE Note")

    # Create a document
    with db.transaction():
        doc = db.new_document("Note")
        doc.set("title", "My Note")
        doc.set("content", "Important information")
        doc.save()

        # Get the RID for later retrieval
        doc_id = str(doc.get_identity())
        print(f"Created document: {doc_id}")

Properties and Methods

set(key, value) -> Document

Set a property on the document. Returns self for chaining.

doc.set("name", "Alice")
doc.set("age", 30)
doc.set("active", True)

# Chaining
doc.set("name", "Bob").set("age", 25).save()

get(key) -> Any

Get a property value.

name = doc.get("name")
age = doc.get("age")
email = doc.get("email")               # Returns None if not found
email = doc.get("email") or "unknown"  # Use default pattern

get_property_names() -> List[str]

Get all property names on the document.

props = doc.get_property_names()
print(f"Properties: {props}")
# Output: Properties: ['name', 'age', 'active']

has_property(key) -> bool

Check if a property exists.

if doc.has_property("email"):
    email = doc.get("email")
else:
    print("Email not set")

save() -> Document

Save changes to the database. Returns self.

doc.set("name", "Updated Name")
doc.save()  # Persists changes

delete() -> None

Delete the document from the database.

⚠️ Important Limitation: Only works on objects from lookup_by_rid() or newly created objects, not on query results. Use SQL DELETE for query results.

# ✅ Works on fresh lookup
with db.transaction():
    doc = db.lookup_by_rid("#1:0")
    doc.delete()

# ✅ Works on newly created
with db.transaction():
    doc = db.new_document("Note")
    doc.set("title", "Test")
    doc.save()
    doc.delete()

# ❌ Doesn't work on query results
results = db.query("sql", "SELECT FROM Note WHERE title = 'Test'")
for doc in results:
    doc.delete()  # No-op!

# ✅ Use SQL DELETE instead
with db.transaction():
    db.command("sql", "DELETE FROM Note WHERE title = 'Test'")

to_dict() -> dict

Convert the document to a Python dictionary of its properties (metadata like RID/type is not included). Use get_rid() for the record ID if needed.

Performance note: to_dict() eagerly converts the full document into Python data. For large scans or repeated wrapper access, prefer get() when you only need specific fields.

doc_dict = doc.to_dict()
print(doc_dict)
# Output: {'name': 'Alice', 'age': 30, 'active': True}

rid = doc.get_rid()

get_identity() -> str

Get the Record ID (RID) of the document.

rid = doc.get_identity()
print(rid)  # Output: #1:0

get_type_name() -> str

Get the type name of the document.

type_name = doc.get_type_name()
print(type_name)  # Output: Note

modify() -> Document

Get a mutable version of the document. Useful for immutable query results.

# Query results are iterators and often immutable
results = db.query("sql", "SELECT FROM Note LIMIT 1")
immutable_doc = next(iter(results))

# Get mutable version for modification
with db.transaction():
    mutable_doc = immutable_doc.modify()
    mutable_doc.set("updated", True).save()

wrap(java_object) -> Document

Static method to wrap Java objects as Python wrappers. Automatically detects type.

from arcadedb_embedded.graph import Document

# Wrap Java object and automatically detect type
wrapped = Document.wrap(java_object)
# Returns: Document, Vertex, or Edge depending on actual type

Vertex Wrapper

The Vertex class extends Document with graph-specific methods for wrapper-based edge creation and traversal.

Creating Vertices

For most app code, prefer SQL/OpenCypher vertex creation and graph writes. Use db.new_vertex(...) when you need direct wrapper manipulation.

db.command("sql", "CREATE VERTEX TYPE Person")

with db.transaction():
    alice = db.new_vertex("Person")
    alice.set("name", "Alice")
    alice.set("age", 30)
    alice.save()

    print(f"Created vertex: {alice.get_identity()}")

Graph Methods

new_edge(edge_type, target_vertex, **properties) -> Edge

Create an edge from this vertex to another vertex.

with db.transaction():
    alice = db.new_vertex("Person").set("name", "Alice").save()
    bob = db.new_vertex("Person").set("name", "Bob").save()

    # Create edge
    edge = alice.new_edge("Knows", bob)
    edge.set("since", 2020)
    edge.save()

get_out_edges(*labels) -> List[Edge]

Get outgoing edges from this vertex, optionally filtered by label.

# All outgoing edges
outgoing = alice.get_out_edges()
for edge in outgoing:
    target = edge.get_in()
    print(f"Alice -> {target.get('name')}")

# Filter by edge type
knows = alice.get_out_edges("Knows")
assert all(e.get_in().get("name") in {"Bob", "Carol"} for e in knows)

get_in_edges(*labels) -> List[Edge]

Get incoming edges to this vertex, optionally filtered by label.

incoming = alice.get_in_edges()
for edge in incoming:
    source = edge.get_out()
    print(f"{source.get('name')} -> Alice")

# Filter by edge type
knows_in = alice.get_in_edges("Knows")

get_both_edges(*labels) -> List[Edge]

Get both incoming and outgoing edges, optionally filtered by label.

all_edges = alice.get_both_edges()
print(f"Degree: {len(all_edges)}")

knows_edges = alice.get_both_edges("Knows")

Edge Wrapper

The Edge class represents a connection between vertices with optional properties.

Edge Properties

Edges have the same property methods as documents:

edge = alice.new_edge("Knows", bob)
edge.set("since", 2020)
edge.set("strength", 0.9)
edge.save()

print(edge.get("since"))  # Output: 2020
edge.get_property_names()  # ['since', 'strength']

Graph Methods

get_in() -> Vertex

Get the incoming (destination) vertex of the edge.

source = edge.get_in()
print(f"Source: {source.get('name')}")

get_out() -> Vertex

Get the outgoing (source) vertex of the edge.

target = edge.get_out()
print(f"Target: {target.get('name')}")

Best Practices

1. Prefer SQL/OpenCypher for set-based CRUD

with db.transaction():
    db.command(
        "sql",
        "INSERT INTO Note SET title = ?, content = ?",
        "My Note",
        "Content",
    )

results = db.query("sql", "SELECT FROM Note WHERE flagged = true")

Use wrappers when you specifically need object-style mutation, wrapper traversal, or a single looked-up record.

2. Always Save After Set

# ❌ Bad - changes not persisted
with db.transaction():
    doc.set("name", "Alice")
# No save!

# ✅ Good
with db.transaction():
    doc.set("name", "Alice")
    doc.save()

3. Prefer SQL DELETE unless you already have a looked-up wrapper

# ❌ Don't delete query results directly
results = db.query("sql", "SELECT FROM Note")
for doc in results:
    doc.delete()  # No-op

# ✅ Wrapper delete on an explicitly looked-up record
with db.transaction():
    doc = db.lookup_by_rid("#1:0")
    doc.delete()

# ✅ Convert query results to RIDs, then delete via lookup
with db.transaction():
    rids = [doc.get_rid() for doc in db.query("sql", "SELECT FROM Note WHERE flagged = true")]
    for rid in rids:
        db.lookup_by_rid(rid).delete()

# ✅ Default pattern for bulk or query-based delete
with db.transaction():
    db.command("sql", "DELETE FROM Note WHERE flagged = true")

4. Create Indexes for Frequent Lookups

db.command("sql", "CREATE INDEX ON Person (name) NOTUNIQUE")

5. Chain Methods for Brevity

# Chaining
with db.transaction():
    doc = db.new_document("Note") \
        .set("title", "My Note") \
        .set("content", "Content") \
        .save()