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.
save() -> Document¶
Save changes to the database. Returns self.
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.
get_type_name() -> str¶
Get the type name of the document.
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.
get_out() -> Vertex¶
Get the outgoing (source) vertex of the edge.
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")