Skip to content

List indexing and querying

This page describes how to create a secondary index on bins whose data type is a list.

Indexing on List elements

  • Similar to basic indexing, the indexable list element data types are numeric, string, and GeoJSON.
  • You can index a List at any depth. Prior to Database 6.1.0, list indexing was only on the top-level element, not nested elements.
  • When creating and index, specify explicitly that list bins should be indexed, and what data type to index on.
  • When querying, specify that the query should be applied on a CDT data type.
  • Similar to basic querying, equality, range for numeric and string data type, points-within-region, region-containing-points for GeoJSON data type are supported.

In this example we use the asadm tool to create two indexes on a single LIST, one for values in the list with numeric data type, one for values in the list with string data type. For further instructions, see Secondary index queries.

Terminal window
Admin+> manage sindex create numeric foo_list_int in list ns test set demo bin foo
Admin+> manage sindex create string foo_list_string in list ns test set demo bin foo

Elements of the indexed list are type checked, so a record whose foo bin contains [ 1, "2", 3, [4], 5 ] results in the following indexing:

Index OnKey TypeIndex TypeEligible Secondary Index Key
foostringLIST”2”
foonumericLIST1, 3, 5

List index queries

The following example inserts three records, creates a string list index, and queries for records whose emails list contains a specific value.

Insert data

Two records have a list of email addresses in the emails bin. The third stores a scalar string instead of a list.

PKusernameemails
"u1""Bob Roberts"["bob.roberts@gmail.com", "bob@yahoo.com"]
"u2""rocketbob"["bigb@gmail.com", "bob@yahoo.com"]
"u3""samunwise""pppreciousss@gmail.com" (scalar string)
import com.aerospike.client.AerospikeClient;
import com.aerospike.client.Bin;
import com.aerospike.client.Key;
AerospikeClient client = new AerospikeClient("127.0.0.1", 3000);
Key key1 = new Key("test", "demo", "u1");
client.put(null, key1,
new Bin("username", "Bob Roberts"),
new Bin("emails", java.util.Arrays.asList("bob.roberts@gmail.com", "bob@yahoo.com"))
);
Key key2 = new Key("test", "demo", "u2");
client.put(null, key2,
new Bin("username", "rocketbob"),
new Bin("emails", java.util.Arrays.asList("bigb@gmail.com", "bob@yahoo.com"))
);
Key key3 = new Key("test", "demo", "u3");
client.put(null, key3,
new Bin("username", "samunwise"),
new Bin("emails", "pppreciousss@gmail.com")
);

Create the list index

Use asadm to create a string index on the list elements of the emails bin:

Terminal window
Admin+> manage sindex create string email_idx in list ns test set demo bin emails

Query the list index

Query for records whose emails list contains a specific string value.

Query 1: Find records where emails contains "bigb@gmail.com" — matches 1 record (rocketbob).

Query 2: Find records where emails contains "bob@yahoo.com" — matches 2 records (Bob Roberts and rocketbob), since both lists contain that address.

Query 3: Find records where emails contains "pppreciousss@gmail.com" — matches 0 records, because that value is stored as a scalar string (not inside a list), so the list index does not cover it.

import com.aerospike.client.query.Filter;
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.RecordSet;
import com.aerospike.client.query.Statement;
// Query 1: emails contains "bigb@gmail.com"
Statement stmt1 = new Statement();
stmt1.setNamespace("test");
stmt1.setSetName("demo");
stmt1.setFilter(Filter.contains("emails", IndexCollectionType.LIST, "bigb@gmail.com"));
RecordSet rs1 = client.query(null, stmt1);
while (rs1.next()) {
System.out.println(rs1.getRecord().getString("username"));
}
rs1.close();
// Output: rocketbob
// Query 2: emails contains "bob@yahoo.com"
Statement stmt2 = new Statement();
stmt2.setNamespace("test");
stmt2.setSetName("demo");
stmt2.setFilter(Filter.contains("emails", IndexCollectionType.LIST, "bob@yahoo.com"));
RecordSet rs2 = client.query(null, stmt2);
while (rs2.next()) {
System.out.println(rs2.getRecord().getString("username"));
}
rs2.close();
// Output: Bob Roberts
// rocketbob
// Query 3: emails contains "pppreciousss@gmail.com"
Statement stmt3 = new Statement();
stmt3.setNamespace("test");
stmt3.setSetName("demo");
stmt3.setFilter(Filter.contains("emails", IndexCollectionType.LIST, "pppreciousss@gmail.com"));
RecordSet rs3 = client.query(null, stmt3);
while (rs3.next()) {
System.out.println(rs3.getRecord().getString("username"));
}
rs3.close();
// Output: (none)

The third query returns no results because "pppreciousss@gmail.com" is stored as a scalar string in record u3, not as an element inside a list. The list index only covers values that are elements of a list bin. Querying without the list index (WHERE emails = "pppreciousss@gmail.com") would result in an AEROSPIKE_ERR_INDEX_NOT_FOUND error.

Known limitations

When using range queries on lists, records can be returned multiple times if the list contains multiple values that fall within the range.

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?