Skip to content

Query records

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

Learn how to find records in Aerospike using the Developer SDK’s AEL (Aerospike Expression Language) queries. AEL provides a readable, SQL-like syntax for filtering data.

Basic query

All operations which read data are queries, regardless of whether you are reading one record, 100 records, or performing an index query. Use query() to find records, and a where clause to provide filtering if desired:

import com.aerospike.client.sdk.DataSet;
import com.aerospike.client.sdk.Record;
import com.aerospike.client.sdk.RecordStream;
DataSet users = DataSet.of("test", "users");
RecordStream stream = session.query(users)
.where("$.status == 'active'")
.execute();
stream.forEach(result -> {
Record user = result.recordOrThrow();
System.out.println("Name: " + user.getString("name"));
});

📖 API reference: DataSet.of(...) | Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.recordOrThrow() | Record.getString(...)

AEL operators

Use $.binName to get the contents of a bin called binName. String literals can be in either single or double quotes, floats are numbers with a decimal point and integer are just digits.

Comparison operators

OperatorDescriptionExample
==Equal"$.status == 'active'"
!=Not equal"$.status != 'inactive'"
>Greater than"$.age > 21"
>=Greater than or equal"$.age >= 18"
<Less than"$.balance < 0"
<=Less than or equal"$.score <= 100"

See AEL reference for a complete list of AEL operators.

import com.aerospike.client.sdk.Record;
import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
// Numeric comparisons
RecordStream s1 = session.query(users).where("$.age >= 18").execute();
s1.forEach((RecordResult result) -> { /* use result.recordOrThrow() */ });
// String equality
RecordStream s2 = session.query(users).where("$.role == 'admin'").execute();
s2.forEach((RecordResult result) -> { /* ... */ });
// Not equal
RecordStream s3 = session.query(users).where("$.deleted != true").execute();
s3.forEach((RecordResult result) -> { /* ... */ });

📖 API reference: Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.recordOrThrow()

Logical operators

Combine conditions with and, or, and not:

import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
// AND
RecordStream a = session.query(users)
.where("$.status == 'active' and $.age >= 18")
.execute();
a.forEach((RecordResult result) -> { /* ... */ });
// OR
RecordStream b = session.query(users)
.where("$.role == 'admin' or $.role == 'moderator'")
.execute();
b.forEach((RecordResult result) -> { /* ... */ });
// NOT
RecordStream c = session.query(users)
.where("not($.status == 'banned')")
.execute();
c.forEach((RecordResult result) -> { /* ... */ });
// Complex combinations
RecordStream d = session.query(users)
.where("($.status == 'active' or $.status == 'pending') and $.age >= 18")
.execute();
d.forEach((RecordResult result) -> { /* ... */ });

📖 API reference: Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.recordOrThrow()

Membership and existence operators

OperatorDescriptionExample
inMembership in a list"'admin' in $.roles"
exists()Path/bin existence check"$.email.exists()"
count()Collection cardinality"$.tags.count() > 3"
import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
// Membership in list
RecordStream s1 = session.query(users)
.where("'admin' in $.roles")
.execute();
s1.forEach((RecordResult result) -> { /* ... */ });
// Exists tests for the presence of the bin in the record
RecordStream s2 = session.query(users)
.where("$.email.exists()")
.execute();
s2.forEach((RecordResult result) -> { /* ... */ });
// Collection size
RecordStream s3 = session.query(users)
.where("$.tags.count() > 3")
.execute();
s3.forEach((RecordResult result) -> { /* ... */ });

📖 API reference: Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.recordOrThrow()

Select specific bins

Return only the bins you need:

import com.aerospike.client.sdk.Record;
import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
RecordStream stream = session.query(users)
.where("$.status == 'active'")
.readingOnlyBins("name", "email") // Only return name and email
.execute();
stream.forEach((RecordResult result) -> {
Record user = result.recordOrThrow();
System.out.println(user.getString("name"));
});

📖 API reference: Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.readingOnlyBins(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.recordOrThrow() | Record.getString(...)

Limit results

Limit the number of records returned:

import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
// Get first 10 active users
RecordStream stream = session.query(users)
.where("$.status == 'active'")
.limit(10)
.execute();
stream.forEach((RecordResult result) -> { /* ... */ });

📖 API reference: Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.limit(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.recordOrThrow()

Stream results

The record streams buffer results returned from the server efficiently when queries which return large numbers of results are executed. This is transparent to the API, but it means that large result sets are not loaded into memory in their entirety.

Record streams should be closed when finished, freeing up resources on both the client side and server side. In Java, terminal helpers such as getFirst, getFirstRecord, and forEach close the stream when the call finishes. In Python, helpers like first(), first_or_raise(), collect(), and failures() consume the stream but do not auto-close it; always call stream.close() (or wrap the work in a try / finally) to release client and server resources promptly.

For large result sets, stream records instead of loading all into memory:

import com.aerospike.client.sdk.Record;
import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
// Process records one at a time
RecordStream stream = session.query(users)
.where("$.status == 'active'")
.execute();
stream.forEach((RecordResult result) -> {
if (result.isOk()) {
Record user = result.recordOrThrow();
if (user != null) {
System.out.println("Processing: " + user.getString("name"));
}
}
});

📖 API reference: Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.isOk() | RecordResult.recordOrThrow() | Record.getString(...)

Query without filter (scan)

Query all records in a set:

import com.aerospike.client.sdk.Record;
import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
import java.util.ArrayList;
import java.util.List;
// Get all users (use with caution on large datasets!)
RecordStream allStream = session.query(users).execute();
List<Record> allUsers = new ArrayList<>();
allStream.forEach(result -> {
if (result.isOk()) {
allUsers.add(result.recordOrThrow());
}
});
// forEach closes allStream.
// Better: stream one record at a time without building a full list
RecordStream scan = session.query(users).execute();
scan.forEach(result -> {
if (result.isOk()) {
Record user = result.recordOrThrow();
System.out.println(user.getString("name"));
}
});

📖 API reference: Session.query(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.isOk() | RecordResult.recordOrThrow() | Record.getString(...)

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 QueryRecordsExample {
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 k1 = "query-example-1";
String k2 = "query-example-2";
String k3 = "query-example-3";
String k4 = "query-example-4";
// Cleanup so the example is repeatable.
session.delete(users.ids(k1, k2, k3, k4)).execute().close();
// Create sample data
session.insert(users)
.bins("name", "age", "status")
.id(k1).values("Alice", 28, "active")
.id(k2).values("Bob", 35, "active")
.id(k3).values("Carol", 22, "inactive")
.id(k4).values("David", 45, "active")
.execute();
// Simple query
System.out.println("Active users:");
RecordStream q1 = session.query(users)
.where("$.status == 'active'")
.execute();
q1.forEach((RecordResult result) -> {
Record u = result.recordOrThrow();
System.out.println(" - " + u.getString("name"));
});
// Complex query
System.out.println("\nActive adults over 30:");
RecordStream q2 = session.query(users)
.where("$.status == 'active' and $.age > 30")
.readingOnlyBins("name", "age")
.execute();
q2.forEach(result -> {
if (result.isOk()) {
Record u = result.recordOrThrow();
System.out.println(
" - " + u.getString("name") + " (" + u.getInt("age") + ")"
);
}
});
// Count
RecordStream q3 = session.query(users)
.where("$.status == 'active'")
.execute();
long activeCount = 0;
while (q3.hasNext()) {
RecordResult rr = q3.next();
activeCount++;
}
q3.close();
System.out.println("\nActive user count: " + activeCount);
}
}
}

📖 API reference: ClusterDefinition(String,int) | ClusterDefinition.connect() | Cluster.createSession(Behavior) | Cluster.close() | DataSet.of(...) | DataSet.ids(...) | Session.delete(...) | ChainableNoBinsBuilder.execute() | RecordStream.close() | Session.insert(DataSet) | OperationObjectBuilder.bins(...) | IdValuesBuilder.id(...) | IdValuesRowBuilder.id(...) | IdValuesRowBuilder.values(...) | IdValuesRowBuilder.execute() | Session.query(...) | ChainableQueryBuilder.where(...) | ChainableQueryBuilder.readingOnlyBins(...) | ChainableQueryBuilder.execute() | RecordStream.forEach(...) | RecordResult.isOk() | RecordResult.recordOrThrow() | Record.getString(...) | Record.getInt(...) | RecordStream.hasNext() | RecordStream.next()

AEL and secondary indexes

AEL text does not force a full scan. The planner can use available secondary indexes for selective predicates and fall back to scans when no useful index exists.

📖 Learn more: AEL Reference covers the full AEL syntax.

API reference summary

MethodDescription
session.query(dataSet)Start a query on a DataSet
.where("expression")Filter with AEL expression (use $.bin for bin paths)
.readingOnlyBins(bins...) / .bins([...]) on session.query(DataSet)Select specific bins to return
.limit(n)Limit number of results
.execute()Run the query and return a RecordStream
RecordStream / async forIterate results; call stream.close() when done

Next steps

Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?