Read records
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
Learn how to read records from Aerospike using the Developer SDK. This guide covers getting records by key, selecting specific bins, handling missing records, and reading metadata.
Get a record by key
Use query() with a key to read a single record (one row in the stream):
import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;
DataSet users = DataSet.of("test", "users");
RecordStream stream = session.query(users.id("user-1")).execute();stream.getFirst().ifPresent(result -> { if (result.isOk()) { Record user = result.recordOrThrow(); System.out.println("Name: " + user.getString("name")); System.out.println("Email: " + user.getString("email")); System.out.println("Age: " + user.getInt("age")); }});stream.close();📖 API reference:
DataSet.of(...)|DataSet.id(...)|Session.query(Key)|ChainableQueryBuilder.execute()|RecordStream.getFirst()|RecordStream.close()|RecordResult.isOk()|RecordResult.recordOrThrow()|Record.getString(...)|Record.getInt(...)
async def demo(session): users = DataSet.of("test", "users")
stream = await session.query(users.id("user-1")).execute() row = await stream.first_or_raise() user = row.record_or_raise() stream.close() print(f"Name: {user.bins.get('name')}") print(f"Email: {user.bins.get('email')}") print(f"Age: {user.bins.get('age')}")📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|RecordStream.close()|QueryBuilder.execute()
Handle missing records
When a record doesn’t exist, the stream has no row (or the row signals not found):
import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;
RecordStream stream = session.query(users.id("nonexistent")).execute();if (stream.getFirst().isEmpty()) { System.out.println("Record not found");}stream.close();
// Or use a default when presentRecordStream s2 = session.query(users.id("user-1")).execute();String user = s2.getFirst() .filter(RecordResult::isOk) .map(result-> result.recordOrThrow().getString("name")) .orElse("Not found");s2.close();
// Or throw if not foundRecord s3 = session.query(users.id("user-1")) .includeMissingKeys() // Include errors for missing records in stream .execute() .getFirstRecord(); // Throws if record is missing📖 API reference:
DataSet.id(...)|Session.query(Key)|ChainableQueryBuilder.includeMissingKeys()|ChainableQueryBuilder.execute()|RecordStream.getFirstRecord()|RecordStream.getFirst()|RecordStream.close()|RecordResult.isOk()|RecordResult.recordOrThrow()|Record.getString(...)
async def demo(session): users = DataSet.of("test", "users") stream = await session.query(users.id("nonexistent")).execute() row = await stream.first() if row is None: print("Record not found") stream.close()
# Or use a default when present stream = await session.query(users.id("user-1")).execute() row = await stream.first() if row is None: name = "Unknown" else: user = row.record_or_raise() name = user.bins.get("name") stream.close()📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|RecordResult.record_or_raise()|RecordStream.first()|RecordStream.close()|QueryBuilder.execute()
Select specific bins
By default, a key query returns all bins. Use bins() to retrieve only the bins you need:
import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;
// Only fetch name and emailRecordStream stream = session.query(users.id("user-1")) .readingOnlyBins("name", "email") .execute();stream.getFirst().ifPresent(result -> { if (result.isOk()) { Record user = result.recordOrThrow(); System.out.println("Name: " + user.getString("name")); System.out.println("Email: " + user.getString("email")); // user.getInt("age") would be null - not fetched }});stream.close();📖 API reference:
DataSet.id(...)|Session.query(Key)|ChainableQueryBuilder.readingOnlyBins(...)|ChainableQueryBuilder.execute()|RecordStream.getFirst()|RecordStream.close()|RecordResult.isOk()|RecordResult.recordOrThrow()|Record.getString(...)|Record.getInt(...)
async def demo(session): users = DataSet.of("test", "users") # Only fetch name and email stream = await ( session.query(users.id("user-1")) .bins(["name", "email"]) .execute() ) row = await stream.first_or_raise() user = row.record_or_raise() stream.close() print(f"Name: {user.bins.get('name')}") print(f"Email: {user.bins.get('email')}") # user.bins.get("age") would be None - not fetched📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|QueryBuilder.bins()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|RecordStream.close()|QueryBuilder.execute()
Read record metadata
Records have metadata you can access:
import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;
RecordStream stream = session.query(users.id("user-1")).execute();stream.getFirst().ifPresent(result -> { if (result.isOk()) { Record user = result.recordOrThrow(); // Generation: incremented on each update int generation = user.generation; // TTL: seconds until expiration (0 = never) int ttlSeconds = user.getTimeToLive(); // User key (if sendKey was true during write) String key = result.key().userKey; System.out.println("Generation: " + generation); System.out.println("TTL: " + ttlSeconds + "s"); System.out.println("Key: " + key); }});stream.close();📖 API reference:
DataSet.id(...)|Session.query(Key)|ChainableQueryBuilder.execute()|RecordStream.getFirst()|RecordStream.close()|RecordResult.isOk()|RecordResult.recordOrThrow()
async def demo(session): users = DataSet.of("test", "users") stream = await session.query(users.id("user-1")).execute() row = await stream.first_or_raise() user = row.record_or_raise() stream.close() generation = user.generation # incremented on each update ttl_seconds = user.ttl # seconds until expiration (0 = never) key = row.key.value # user key (if send_key was True during write) print(f"Generation: {generation}") print(f"TTL: {ttl_seconds}s") print(f"Key: {key}")📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|RecordStream.close()|QueryBuilder.execute()
| Metadata | Description |
|---|---|
| Generation | Version counter, incremented on each update. Use for optimistic locking. |
| TTL | Seconds until expiration. 0 means never expires. -1 means use namespace default. |
| Key | Original user key (only available if send-key was enabled on the writing behavior — sendKey(true) in Java, send_key=True in Python). |
Read with type safety
Use typed getters for bin values:
import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;import java.util.List;import java.util.Map;
RecordStream stream = session.query(users.id("user-1")).execute();Record user = stream.getFirst() .filter(RecordResult::isOk) .map(RecordResult::recordOrThrow) .orElseThrow();stream.close();
// String valuesString name = user.getString("name");
// Integer valuesint age = user.getInt("age");long bigNumber = user.getLong("big_number");
// Double valuesdouble balance = user.getDouble("balance");
// Boolean valuesboolean active = user.getBoolean("active");
// List valuesList<String> tags = user.getList("tags");
// Map valuesMap<String, Object> preferences = user.getMap("preferences");
// Raw value (when type is unknown)Object value = user.getValue("unknown_field");📖 API reference:
DataSet.id(...)|Session.query(Key)|ChainableQueryBuilder.execute()|RecordStream.getFirst()|RecordStream.close()|RecordResult.isOk()|Record.getString(...)|Record.getInt(...)|Record.getLong(...)|Record.getList(...)|Record.getValue(...)
async def demo(session): users = DataSet.of("test", "users") stream = await session.query(users.id("user-1")).execute() row = await stream.first_or_raise() user = row.record_or_raise() stream.close()
name: str = user.bins["name"] age: int = user.bins["age"] balance: float = user.bins["balance"] active: bool = user.bins["active"] tags: list = user.bins["tags"] preferences: dict = user.bins["preferences"] value = user.bins.get("unknown_field") # None if absent📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|RecordStream.close()|QueryBuilder.execute()
Check if a record exists
To check existence without fetching data:
boolean exists = session.exists(users.id("user-1")).execute().getFirstBoolean().orElse(false);
if (exists) { System.out.println("User exists");} else { System.out.println("User not found");}📖 API reference:
DataSet.id(...)|Session.exists(Key)|ChainableQueryBuilder.execute()
async def demo(session): users = DataSet.of("test", "users") stream = await session.exists(users.id("user-1")).execute() row = await stream.first() stream.close()
if row is not None and row.as_bool(): print("User exists") else: print("User not found")📖 API reference:
DataSet.of()|DataSet.id()|Session.exists()|RecordResult.as_bool()|RecordStream.first()|RecordStream.close()|WriteSegmentBuilder.execute()
Read header only
To get only metadata (generation, TTL) without bin values:
import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;
RecordStream stream = session.query(users.id("user-1")) .withNoBins() .execute();stream.getFirst().ifPresent(result -> { if (result.isOk()) { Record header = result.recordOrThrow(); System.out.println("Generation: " + header.generation); System.out.println("TTL: " + header.getTimeToLive()); // Bins are not populated }});stream.close();📖 API reference:
DataSet.id(...)|Session.query(Key)|ChainableQueryBuilder.execute()|RecordStream.getFirst()|RecordStream.close()|RecordResult.isOk()|RecordResult.recordOrThrow()
async def demo(session): users = DataSet.of("test", "users") stream = await session.query(users.id("user-1")).with_no_bins().execute() row = await stream.first_or_raise() header = row.record_or_raise() stream.close()
print(f"Generation: {header.generation}") print(f"TTL: {header.ttl}") # header.bins is {} — no bin payload fetched📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|RecordStream.close()|QueryBuilder.execute()
Batch read
For reading multiple records efficiently, see Batch Operations.
import java.util.List;
// Quick preview - see Batch Operations for full detailsRecordStream usersStream = session.query(users.ids("user-1", "user-2", "user-3")).execute();List<Record> users = usersStream.stream().toList();📖 API reference:
DataSet.ids(...)|Session.query(List)|ChainableQueryBuilder.execute()|RecordStream.stream()
async def demo(session): users = DataSet.of("test", "users") stream = await session.query(users.ids("user-1", "user-2", "user-3")).execute() results = await stream.collect() records = [r.record_or_raise() for r in results if r.is_ok]📖 API reference:
DataSet.of()|DataSet.ids()|Session.query()|RecordResult.record_or_raise()|RecordStream.collect()|QueryBuilder.execute()
Complete example
import com.aerospike.client.sdk.Cluster;import com.aerospike.client.sdk.ClusterDefinition;import com.aerospike.client.sdk.DataSet;import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;import com.aerospike.client.sdk.Session;import com.aerospike.client.sdk.policy.Behavior;
public class ReadRecordsExample { public static void main(String[] args) { try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) { Session session = cluster.createSession(Behavior.DEFAULT); DataSet users = DataSet.of("test", "users"); String key = "read-example-user";
// Seed data so the example is repeatable. session.upsert(users) .bins("name", "email", "age") .id(key).values("Alice Smith", "alice@example.com", 28) .execute();
// Full record read RecordStream full = session.query(users.id(key)).execute(); full.getFirst().ifPresent(result -> { if (result.isOk()) { Record user = result.recordOrThrow(); System.out.println("=== Full Record ==="); System.out.println("Name: " + user.bins.get("name")); System.out.println("Generation: " + user.generation); } }); full.close();
// Partial read RecordStream partial = session.query(users.id(key)) .readingOnlyBins("name", "email") .execute(); partial.getFirst().ifPresent(result -> { if (result.isOk()) { Record user = result.recordOrThrow(); System.out.println("\n=== Selected Bins ==="); System.out.println("Name: " + user.getString("name")); System.out.println("Email: " + user.getString("email")); } }); partial.close();
// Existence check boolean exists = session.exists(users.id(key)).execute().getFirstBoolean().orElse(false); System.out.println("\nUser exists: " + exists); } }}📖 API reference:
ClusterDefinition(String,int)|ClusterDefinition.connect()|Cluster.createSession(Behavior)|Cluster.close()|DataSet.of(...)|Session.upsert(DataSet)|Session.exists(Key)|Session.query(Key)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.readingOnlyBins(...)|ChainableQueryBuilder.execute()|RecordStream.getFirst()|RecordStream.close()|RecordResult.isOk()|RecordResult.recordOrThrow()|Record.getString(...)
import asyncio
from aerospike_sdk import Behavior, DataSet, Client
async def main(): async with Client("localhost:3000") as client: session = client.create_session(Behavior.DEFAULT) users = DataSet.of("test", "users") key = users.id("read-example-user")
# Seed data so the example is repeatable. await session.upsert(key=key).put( {"name": "Alice Smith", "email": "alice@example.com", "age": 28} ).execute()
# Full record read stream = await session.query(key).execute() row = await stream.first_or_raise() user = row.record_or_raise() stream.close() print("=== Full Record ===") print(f"Name: {user.bins.get('name')}") print(f"Generation: {user.generation}")
# Partial read stream = await ( session.query(key) .bins(["name", "email"]) .execute() ) row = await stream.first_or_raise() user = row.record_or_raise() stream.close() print("\n=== Selected Bins ===") print(f"Name: {user.bins.get('name')}") print(f"Email: {user.bins.get('email')}")
# Existence check # exists() yields a row only when the record is found; for a missing # key the stream is empty, so use first() + None check rather than # first_or_raise(). stream = await session.exists(key).execute() row = await stream.first() exists = row is not None and row.as_bool() stream.close() print(f"\nUser exists: {exists}")
if __name__ == "__main__": asyncio.run(main())📖 API reference:
Client|Client.create_session()|DataSet.of()|DataSet.id()|Behavior.DEFAULT|Session.query()|Session.upsert()|Session.exists()|QueryBuilder.bins()|WriteSegmentBuilder.put()|RecordResult.record_or_raise()|RecordResult.as_bool()|RecordStream.first()|RecordStream.first_or_raise()|RecordStream.close()|QueryBuilder.execute()|WriteSegmentBuilder.execute()
API reference summary
| Method | Description | Link |
|---|---|---|
query(key) | Read a record by key (single-row stream) | Java · Python |
exists() | Check if a record exists | Java · Python |
.readingOnlyBins(...) / .bins([...]) | Bin projection on queries (session.query(DataSet)); see Query records | — |
.withNoBins() / .with_no_bins() | Read only metadata (no bin payload) | — |
Next steps
Update Records
Modify the records you’ve read.
Query Records
Find records with DSL queries.
Batch Operations
Read multiple records efficiently.