Read records
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();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')}")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 missingasync 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()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();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 fetchedRead 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();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}")| 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");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 absentCheck 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");}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")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();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 fetchedBatch 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();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]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); } }}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 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.