Results API¶
The ResultSet and Result classes provide Python-friendly interfaces for working with query results from ArcadeDB. They handle iteration, property access, and type conversion automatically.
Using Context Managers
For automatic resource cleanup, prefer using context managers:
with arcadedb.open_database("./mydb") as db:
result_set = db.query("sql", "SELECT FROM Person WHERE age > 25")
for result in result_set:
print(result.get("name"))
# Database automatically closed
db.close() for clarity, but context managers are recommended in production.
Overview¶
When you execute a query, ArcadeDB returns a ResultSet that can be iterated to access individual Result objects. Each Result represents one row/record from your query.
Key Features:
- Pythonic iteration: Use
forloops or iterators - Property access: Get values by property name
- Type conversion: Automatic conversion from Java to Python types
- Multiple access patterns: Dict-like access, JSON export, direct properties
ResultSet Class¶
Iterable wrapper for query results. ResultSet is a Python iterator: iterate it with a
for loop, next(), or materialize it with helpers like to_list(), first(), and
one().
Creation¶
ResultSet objects are returned by query operations:
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./mydb")
# query() returns ResultSet
result_set = db.query("sql", "SELECT FROM Person WHERE age > 25")
# command() also returns ResultSet for SELECT queries
result_set = db.command("sql", "SELECT * FROM Person LIMIT 10")
Iteration¶
ResultSet implements the Python iterator protocol (__iter__/__next__), so each
iteration yields a Result. Iteration consumes the underlying result set.
# Using for loop (most Pythonic)
for result in result_set:
name = result.get("name")
age = result.get("age")
print(f"{name}: {age}")
# As iterator
result_set = db.query("sql", "SELECT FROM Product")
results = list(result_set) # Convert to list of Result objects
# Or use the built-in next()
result_set = db.query("sql", "SELECT FROM Document")
first = next(result_set) # Raises StopIteration when exhausted
to_list(convert_types: bool = True) -> List[Dict[str, Any]]¶
Convert all results to a list of dictionaries.
Parameters:
convert_types(bool): Convert Java types to Python types (default:True)
Returns:
List[Dict[str, Any]]: List of dictionaries with result data
Example:
results = db.query("sql", "SELECT FROM User LIMIT 10")
users = results.to_list()
print(users[0])
# {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}
iter_dicts(convert_types: bool = True) -> Iterator[Dict[str, Any]]¶
Iterate results as dictionaries.
Parameters:
convert_types(bool): Convert Java types to Python types (default:True)
Yields:
- Result rows as dictionaries
to_json_list(batch_size: int = 10_000) -> List[Dict[str, Any]]¶
Bulk-materialize all rows via batched Java-side JSON serialization.
The fast path for large result sets: rows are serialized to JSON in batches on the Java
side (one JPype crossing per batch instead of several per row) and parsed with the C
json module. Measured ~5.5x faster than to_list() on a 10,000-row, nine-property scan
(578 ms against 103 ms, laptop, 2026-09-27).
Trade-off: values carry JSON-native types. Numbers, strings, booleans, lists, and
nested maps convert as expected, but DATE and DATETIME values arrive as
epoch-millisecond integers (not datetime) and DECIMALs as floats. A DATE is the
epoch milliseconds of midnight UTC, whatever the JVM's time zone, so it is the same
integer Result.to_json() writes and datetime.fromtimestamp(ms / 1000, timezone.utc)
gives the right day. (Before this was fixed it was midnight in the JVM's zone: the
previous day when decoded as UTC east of UTC, humemai/arcadedb-embedded-python#116.)
Use to_list() when full Python-type fidelity matters more than speed.
It is also the fast path for a small result: a one-row read through to_json_list() takes
one Java crossing (a short batch ends the read) and allocates only what the row needs,
about 0.022 ms for a bound openCypher point lookup against 0.037 ms before this was fixed
(laptop, relative only, 2026-10-04).
Parameters:
batch_size(int): Rows serialized per Java crossing (default:10_000); must be at least 1 (ValueErrorotherwise)
Returns:
List[Dict[str, Any]]: List of dictionaries with JSON-native values
Example:
iter_json_batches(batch_size: int = 10_000) -> Iterator[List[Dict[str, Any]]]¶
Yield rows as lists of dicts, one Java-serialized batch at a time.
Streaming counterpart of to_json_list() with the same JSON-native type semantics;
bounds memory to one batch. Falls back to chunked per-row conversion when the bridge
jar is unavailable.
Parameters:
batch_size(int): Rows serialized per Java crossing (default:10_000); must be at least 1 (ValueErrorotherwise)
Yields:
- Lists of dictionaries (up to
batch_sizeelements each)
Example:
to_dataframe(convert_types: bool = True)¶
Convert results to a pandas DataFrame. Requires pandas to be installed.
Parameters:
convert_types(bool): Convert Java types to Python types (default:True)
Returns:
- pandas DataFrame
Raises:
ImportError: If pandas is not installed
Example:
to_columns(batch_size: int = 25_000, columns: Optional[Sequence[str]] = None)¶
Bulk-materialize all rows as columns: a dict of column name to numpy array
(int64/float64/bool/datetime64[ms]) or Python list (strings and
JSON-typed values). The fastest bulk path; to_dataframe() uses it internally.
Fixed-dimension vector properties (e.g. ARRAY_OF_FLOATS embedding
columns) come back as one contiguous 2-D array of shape (rows, dim)
(float32 or float64), ready for scikit-learn/faiss without per-row
conversion; ragged array columns fall back to lists.
Null handling follows pandas conventions: int/datetime columns with nulls
are promoted to float64 with NaN / datetime64 NaT; a null row in a vector
column becomes a NaN row. Returns None when numpy or the bridge jar is
unavailable (callers fall back to row-based paths).
The columns are the union of the property names of every row, in order of first
appearance, because a document is schemaless: a property the first row lacks is still
a column, null where a row lacks it. (Before this was fixed the columns were the first
row's, and to_columns(), to_dataframe(), and to_arrow() dropped the others,
humemai/arcadedb-embedded-python#113.) The result does not depend on batch_size.
Finding the columns costs one pass over each row's property names (about 25% of a
200,000-row, twelve-property to_columns(), measured on the laptop, relative only);
pass columns=["a", "b"] to read exactly those, as a projection would, and skip it. A
row lacking one of them reads null, and a property not listed is left out.
A DECIMAL column is an object array of Decimal (None for null), exact to the last
digit; it used to arrive as JSON numbers, so a double lost digits and the dtype followed
the data (humemai/arcadedb-embedded-python#115).
Example:
cols = db.query("sql", "SELECT cid, embedding FROM Chunk").to_columns()
emb = cols["embedding"] # float32, shape (n, dim)
sims = emb @ query_vector # immediately usable
to_arrow(batch_size: int = 25_000, columns: Optional[Sequence[str]] = None)¶
Bulk-materialize all rows as a pyarrow.Table. Requires numpy and pyarrow.
It reads the same columnar buffer as to_columns(), so the Java side does no extra
work. Two things differ. Nulls keep their column type, because Arrow carries a validity
bitmap: a nullable int64 column stays int64 (where to_columns() promotes it to float64
with NaN, losing precision above 2**53), and a nullable boolean column stays boolean.
Strings are cheaper, because the buffer already holds Arrow's string layout (int32
offsets and a UTF-8 blob), so a column is wrapped instead of decoded one str at a
time.
The table's columns are the union of the rows' property names, as in to_columns(). A
column's type does not depend on batch_size: a batch whose rows lack the column, carry
it as null, or hold only empty lists in it says nothing about its type and takes the
type of the other batches (humemai/arcadedb-embedded-python#114). If batches really do
disagree (an int in one row, a string in another), the column becomes strings, in one
batch as well as across batches. A DECIMAL column is decimal128 (decimal256 above
38 digits, strings above 76), so no digit is lost.
Parameters:
batch_size(int): Rows per Java crossing (default:25_000)
Returns:
pyarrow.Table, orNonewhen pyarrow, numpy, or the bridge jar is unavailable (fall back toto_columns())
Example:
iter_chunks(size: int = 1000, convert_types: bool = True) -> Iterator[List[Dict[str, Any]]]¶
Iterate results in chunks for memory-efficient processing.
Parameters:
size(int): Chunk size (default:1000)convert_types(bool): Convert Java types to Python types (default:True)
Yields:
- Lists of dictionaries (up to
sizeelements each)
Example:
results = db.query("sql", "SELECT FROM User")
for chunk in results.iter_chunks(size=1000):
process_batch(chunk) # chunk is a list of dicts
count() -> int¶
Count the remaining results without building a list.
Returns:
int: Number of remaining results
Note: This consumes the remaining rows from the current result set. After calling
count(), the iterator is exhausted.
Example:
first() -> Optional[Result]¶
Get the first result, or None if there are no results.
Returns:
ResultorNone
Example:
one() -> Result¶
Get a single result, raising ValueError if there is not exactly one.
Returns:
Result: The single result
Raises:
ValueError: If zero or multiple results
Example:
user = db.query(
"sql",
"SELECT FROM User WHERE email = ?",
"alice@example.com",
).one()
print(user.get("name"))
close() -> None¶
Close the underlying Java result set. Idempotent.
A result set is closed for you as soon as it is exhausted (by iteration or any of the
to_* methods), by first() and one() once they have their row, and when the
object is freed (CPython frees it as soon as nothing refers to it, e.g. after a break).
Call close(), or use the result set as a context manager, when you stop reading early
and keep the object around.
A result set read to its end reads as empty afterwards. One closed before its end, by
first(), one(), close(), or leaving its with block, raises ArcadeDBError if you
read it again: the rows it had not returned are gone, so run the query again. (Until
2026-09-29 such a read returned whatever the closed Java result set still handed out,
which depended on the engine build.) To take one row and keep reading, use
next(iter(rs)) rather than first().
The engine computes rows lazily, so an error in the statement can come while the rows are
read, after query() returned: a division by zero on the tenth row, say. Iteration,
first(), one(), count(), and every to_* and iter_* method raise it as
ArcadeDBError, with the Java exception as its __cause__. (Before 26.10.1 the Java
exception reached Python as it was.)
A result set, and each Result it returns, keeps its Database alive. Reading a result
set after the database was closed (db.close(), or leaving the with block that opened
it) raises ArcadeDBError ("Database is closed") unless it was already read to its end,
because the rows it has not returned may still be read lazily from the engine. A Result
that is a record row (SELECT FROM T) raises too: its properties are loaded lazily from
the open database, so there is nothing to return. A Result that is a projection
(SELECT name FROM T) or a command result (for example the one IMPORT DATABASE
returns) holds its own values and stays readable, so it can be read after the database
is closed. See Database.close().
Closing is not only memory hygiene: since 26.10.1's parallel scan
(ArcadeData/arcadedb#8524) a query whose LIMIT is satisfied keeps its scan's producer
threads parked until its result set is closed or
arcadedb.parallelScanAbandonedTimeout (10 minutes) passes, and a few such result sets
stall the next query that needs those threads (ArcadeData/arcadedb#8594). 26.10.1
development wheels built before 2026-09-28 closed nothing on exhaustion, so RID-paged
reads (WHERE @rid > <last> LIMIT n) stalled on their fifth page on 8 cores. The
26.9.1 release does not have that parallel scan and is not affected.
ResultSet is also a context manager (__enter__/__exit__), so with blocks close
it automatically.
Example:
# Explicit close
result_set = db.query("sql", "SELECT FROM User")
names = [r.get("name") for r in result_set]
result_set.close()
# Context-manager usage (closes automatically)
with db.query("sql", "SELECT FROM User") as result_set:
for result in result_set:
print(result.get("name"))
Result Class¶
Represents a single result row/record from a query.
Creation¶
Result objects are created automatically when iterating a ResultSet:
result_set = db.query("sql", "SELECT FROM Person")
# Each iteration gives you a Result
for result in result_set:
# result is a Result object
pass
get(name: str, convert_types: bool = True) -> Any¶
Get the value of a property by name.
Parameters:
name(str): Property nameconvert_types(bool): Convert Java types to Python types (default:True)
Returns:
Any: Property value (type depends on the data), orNoneif property doesn't exist- Automatically converts Java types to Python types
- Java
Boolean→ Pythonbool - Java
Integer/Long→ Pythonint - Java
Float/Double→ Pythonfloat - Java
String→ Pythonstr - Java collections → Python lists/dicts
Example:
result_set = db.query("sql", "SELECT name, age, active FROM User")
for result in result_set:
name = result.get("name") # str
age = result.get("age") # int
active = result.get("active") # bool (converted from Java Boolean)
print(f"{name} is {age} years old, active: {active}")
# Handle optional properties with fallback
email = result.get("email") or "unknown@example.com"
print(f"Email: {email}")
get_raw(name: str) -> Any¶
Get a property value without Java-to-Python conversion.
Parameters:
name(str): Property name
Returns:
- Raw Java-backed property value, or
Noneif the property doesn't exist
Example:
result = db.query("sql", "SELECT FROM User LIMIT 1").first()
java_value = result.get_raw("created_at") # Java object, no conversion
has_property(name: str) -> bool¶
Check if a property exists in the result.
Parameters:
name(str): Property name to check
Returns:
bool:Trueif property exists,Falseotherwise
Example:
result_set = db.query("sql", "SELECT * FROM Person")
for result in result_set:
if result.has_property("email"):
email = result.get("email")
print(f"Email: {email}")
else:
print("No email address")
get_property_names() -> List[str]¶
Get list of all property names in the result.
Returns:
List[str]: List of property names
Example:
result_set = db.query("sql", "SELECT * FROM Document LIMIT 1")
for result in result_set:
properties = result.get_property_names()
print(f"Properties: {', '.join(properties)}")
for prop in properties:
value = result.get(prop)
print(f" {prop}: {value}")
property_names -> List[str]¶
Property (attribute-style) equivalent of get_property_names(): all property names in
this result.
Returns:
List[str]: List of property names
Example:
result = db.query("sql", "SELECT FROM User LIMIT 1").first()
print(result.property_names)
# ['name', 'email', 'age', 'created_at']
get_rid() -> Optional[str]¶
Get the Record ID (RID) of the result, if available.
Returns:
str(e.g."#10:5") orNone
Example:
to_dict(convert_types: bool = True) -> Dict[str, Any]¶
Convert the result to a Python dictionary.
Parameters:
convert_types(bool): Convert Java types to Python types (default:True)
Returns:
Dict[str, Any]: Dictionary with property names as keys
Example:
result_set = db.query("sql", "SELECT name, age, city FROM Person")
# Convert all results to list of dicts
people = [result.to_dict() for result in result_set]
for person in people:
print(person)
# {'name': 'Alice', 'age': 30, 'city': 'NYC'}
Use Cases:
- Converting to pandas DataFrame
- Serialization to JSON (via
json.dumps()) - Passing data to other libraries
- Debugging/inspection
Performance note: to_dict() converts the whole row in one call into Java, which
is cheaper than one get() per property when you need several fields. For large result
sets, the bulk methods are faster than any per-row access: to_json_list(),
to_columns(), to_dataframe(), or to_arrow().
to_json() -> str¶
Convert the result to a JSON string.
Returns:
str: JSON representation of the result
Example:
result_set = db.query("sql", "SELECT * FROM Product WHERE price > 100")
for result in result_set:
json_str = result.to_json()
print(json_str)
# {"@rid":"#1:0","@type":"Product","name":"Laptop","price":999.99}
Note: The JSON includes ArcadeDB metadata like @rid (record ID) and @type (type name).
Note: Array/list properties are serialized as JSON arrays in to_json().
Common Patterns¶
Converting to Lists and Dicts¶
ResultSet.to_list() and Result.to_dict() are eager materializers. They are the
right choice when you explicitly want Python-native data, but they are not the
lowest-overhead path for large result sets.
# List of dictionaries (most common)
result_set = db.query("sql", "SELECT FROM User")
users = [result.to_dict() for result in result_set]
# List of specific property values
result_set = db.query("sql", "SELECT name FROM User")
names = [result.get("name") for result in result_set]
# Dictionary keyed by ID
result_set = db.query("sql", "SELECT id, name FROM User")
user_map = {
result.get("id"): result.get("name")
for result in result_set
}
Pandas Integration¶
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./mydb")
# Query and convert to DataFrame (columnar path; requires pandas)
df = db.query("sql", "SELECT name, age, city FROM Person").to_dataframe()
print(df.head())
# name age city
# 0 Alice 30 NYC
# 1 Bob 25 LA
# 2 Charlie 35 Boston
Processing Large Result Sets¶
For memory efficiency with large datasets:
# Stream one row at a time when you only need a few fields
result_set = db.query("sql", "SELECT name, email FROM LargeTable")
for result in result_set:
process_row(result.get("name"), result.get("email"))
# Or process in batches of dicts
for batch in db.query("sql", "SELECT FROM LargeTable").iter_chunks(size=1000):
process_batch(batch)
# Faster, with JSON-native values (DATE and DATETIME as epoch-millisecond
# integers, DECIMALs as floats)
for batch in db.query("sql", "SELECT FROM LargeTable").iter_json_batches():
process_batch(batch)
Conditional Property Access¶
result_set = db.query("sql", "SELECT * FROM Product")
for result in result_set:
# Safely get optional properties
discount = (
result.get("discount")
if result.has_property("discount")
else 0.0
)
price = result.get("price")
final_price = price * (1 - discount)
print(f"Price: ${final_price:.2f}")
Extracting RIDs and Types¶
result_set = db.query("sql", "SELECT FROM Person")
for result in result_set:
# Get ArcadeDB metadata (a SELECT without a projection has no "@rid" column,
# so get("@rid") would return None)
rid = result.get_rid() # Record ID (e.g., "#1:0")
rec_type = result.get_element().get_type_name() # Type name (e.g., "Person")
# Get user properties
name = result.get("name")
print(f"[{rid}] {rec_type}: {name}")
Converting Results to Vertices for Modification¶
Query results are read-only by default. To modify a vertex or edge returned from a query, get its Vertex or Edge object with .get_vertex() or .get_edge(), then call .modify() on it for a mutable copy. The object from .get_vertex() or .get_edge() is itself immutable: calling .set() on it raises AttributeError.
get_vertex() -> Optional[Vertex]¶
Get the Vertex object of a Result (if the result is a vertex). Call .modify() on it before .set().
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./mydb")
# Query returns read-only Results
result_set = db.query("sql", "SELECT FROM Person WHERE name = 'Alice'")
with db.transaction():
for result in result_set:
# Get the Vertex, then a mutable copy of it
vertex = result.get_vertex()
if vertex:
vertex = vertex.modify()
# Now you can modify it
vertex.set("age", 31)
vertex.set("updated", True)
vertex.save()
print(f"Updated: {result.get('name')}")
get_edge() -> Optional[Edge]¶
Get the Edge object of a Result (if the result is an edge). Call .modify() on it before .set().
# Query edges
result_set = db.query("sql", "SELECT FROM FRIEND_OF")
with db.transaction():
for result in result_set:
# Get the Edge, then a mutable copy of it
edge = result.get_edge()
if edge:
edge = edge.modify()
edge.set("strength", 0.95)
edge.save()
get_element() -> Optional[Document]¶
Get the underlying element regardless of kind. Returns the matching wrapper
(Document, Vertex, or Edge) or None if the result carries no element (e.g. a
projection or aggregation row).
result_set = db.query("sql", "SELECT FROM Person")
with db.transaction():
for result in result_set:
element = result.get_element()
if element:
print(element.get_rid(), element.get_type_name())
Full Example: Bulk Update with Caching¶
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./mydb")
# Query all movies
movies = list(db.query("sql", "SELECT FROM Movie"))
print(f"Processing {len(movies)} movies...")
with db.transaction():
for movie_result in movies:
# Get the vertex, then a mutable copy of it
movie = movie_result.get_vertex()
if not movie:
continue
movie = movie.modify()
# Modify the vertex
title = movie_result.get("title")
# Add embedding or update properties
movie.set("processed", True)
movie.set("updated_at", "2024-01-02")
movie.save()
print(f"✓ Updated: {title}")
db.close()
Key Distinction:
| Object | Read | Write |
|---|---|---|
Result (from query) |
✅ Yes | ❌ No |
Vertex/Edge from .get_vertex()/.get_edge() |
✅ Yes | After .modify() |
Created with db.new_vertex() |
✅ Yes | ✅ Yes |
Looked up with db.lookup_by_rid() |
✅ Yes | After .modify() |
Complete Examples¶
User Search and Display¶
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./users_db")
def search_users(name_pattern):
"""Search users by name pattern."""
query = """
SELECT name, email, created_at
FROM User
WHERE name LIKE ?
ORDER BY name
"""
result_set = db.query("sql", query, f"%{name_pattern}%")
users = []
for result in result_set:
user = {
'name': result.get("name"),
'email': result.get("email"),
'created_at': result.get("created_at")
}
users.append(user)
return users
# Search
results = search_users("John")
print(f"Found {len(results)} users:")
for user in results:
print(f" {user['name']} <{user['email']}>")
db.close()
Graph Traversal Results¶
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./social_graph")
# Find friends of friends
query = """
SELECT
@rid as person_rid,
name,
out('Follows').out('Follows').name as friends_of_friends
FROM Person
WHERE name = 'Alice'
"""
result_set = db.query("sql", query)
for result in result_set:
person_name = result.get("name")
friends_of_friends = result.get("friends_of_friends")
print(f"{person_name}'s extended network:")
# get() has already converted the Java collection to a Python list
if friends_of_friends:
for friend in friends_of_friends:
print(f" - {friend}")
db.close()
Aggregation Results¶
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./analytics_db")
# Group by and aggregation
query = """
SELECT
category,
COUNT(*) as product_count,
AVG(price) as avg_price,
MAX(price) as max_price
FROM Product
GROUP BY category
ORDER BY product_count DESC
"""
result_set = db.query("sql", query)
print("Product Statistics by Category:")
print("-" * 60)
for result in result_set:
category = result.get("category")
count = result.get("product_count")
avg_price = result.get("avg_price")
max_price = result.get("max_price")
print(f"{category}:")
print(f" Products: {count}")
print(f" Avg Price: ${avg_price:.2f}")
print(f" Max Price: ${max_price:.2f}")
print()
db.close()
Export to JSON File¶
import arcadedb_embedded as arcadedb
import json
db = arcadedb.open_database("./mydb")
# Export query results to JSON file
result_set = db.query("sql", "SELECT * FROM Document")
# Method 1: Using to_dict()
documents = [result.to_dict() for result in result_set]
with open("export.json", "w") as f:
json.dump(documents, f, indent=2, default=str)
# Method 2: Using to_json() directly
result_set = db.query("sql", "SELECT * FROM Document")
with open("export_raw.jsonl", "w") as f:
for result in result_set:
f.write(result.to_json() + "\n")
db.close()
Cypher Query Results¶
import arcadedb_embedded as arcadedb
db = arcadedb.open_database("./graph_db")
# OpenCypher queries also return ResultSet
cypher_query = """
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
WHERE c.name = 'TechCorp'
RETURN p.name AS employee, p.role AS position
"""
result_set = db.query("opencypher", cypher_query)
print("TechCorp Employees:")
for result in result_set:
employee = result.get("employee")
position = result.get("position")
print(f" {employee} - {position}")
db.close()
Error Handling¶
from arcadedb_embedded import ArcadeDBError
result_set = db.query("sql", "SELECT * FROM Person")
for result in result_set:
try:
# Safe property access
name = result.get("name")
# May not exist
if result.has_property("phone"):
phone = result.get("phone")
else:
phone = "N/A"
print(f"{name}: {phone}")
except ArcadeDBError as e:
print(f"Error accessing properties: {e}")
continue
Type Handling¶
get(), to_dict(), and to_list() convert Java values to Python types
automatically (Boolean to bool, BigDecimal to Decimal, dates to date and
datetime, collections to list, set, and dict). See
Type Conversion for the full table.
Performance Tips¶
Minimize Property Access¶
# Less efficient: Multiple property accesses
for result in result_set:
if result.get("age") > 25:
name = result.get("name")
age = result.get("age")
print(f"{name}: {age}")
# More efficient: Access once, reuse
for result in result_set:
age = result.get("age")
if age > 25:
name = result.get("name")
print(f"{name}: {age}")
Use to_dict() for Multiple Properties¶
# When accessing many properties, convert to dict once
for result in result_set:
data = result.to_dict()
# Now access from Python dict (faster)
process(
data["name"],
data["age"],
data["email"],
data["phone"]
)
Stream Processing¶
# Don't collect all results if you can process incrementally
result_set = db.query("sql", "SELECT * FROM LargeTable")
# Process as you iterate (memory efficient)
total = 0
for result in result_set:
value = result.get("amount")
total += value
# Better than:
# results = list(result_set) # Loads everything into memory
See Also¶
- Database API - Query and command methods
- Query Guide - Writing effective queries
- Transaction API - Transaction context
- Graph Operations Guide - Working with graph results