Skip to content

Map indexes and querying

Overview

This page describes how to create a secondary index on bins where the data type is a map. You can index either map key or map value.

Indexing on Map elements

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

Examples

The following example uses asadm to create an index with source type mapkeys and a String data type:

Terminal window
Admin+> manage sindex create string foo_mapkey_idx in mapkeys ns test set demo bin foo

The following example uses asadm to create an index with source type mapvalues with a Numeric data type:

Admin+> manage sindex create numeric foo_mapval_idx in mapvalues ns test set demo bin foo

Use show sindex to confirm the indexes were created successfully.

Terminal window
Admin+> show sindex
~~~~~~~~~~~~~~~~~~~Secondary Indexes (2026-04-08 16:01:35 UTC)~~~~~~~~~~~~~~~~~~~
Index Name|Namespace| Set|Bin| Bin| Index|State
| | | | Type| Type|
foo_mapkey_idx|test |demo|foo|string |mapkeys |RW
foo_mapval_idx|test |demo|foo|numeric|mapvalues|RW
Number of rows: 2

Elements of the indexed map are type checked, so a record whose foo bin contains { a:1, b:"2", c:3, d:[4], e:5, 666:"zzz" } results in the following indexing:

Index OnKey TypeIndex TypeEligible Secondary Index Key
foostringMAPKEYSa, b, c, d, e
foonumericMAPVALUES1, 3, 5

Map index queries

This example inserts records with a foo map bin containing mixed key-value types, then queries by map key and map value using the indexes created above.

Insert data

Key key1 = new Key("test", "demo", "u1");
Map<String, Object> cart1 = new HashMap<>();
cart1.put("a", 1);
cart1.put("b", "2");
cart1.put("c", 3);
client.put(null, key1,
new Bin("username", "Bob Roberts"),
new Bin("foo", cart1));
Key key2 = new Key("test", "demo", "u2");
Map<String, Object> cart2 = new HashMap<>();
cart2.put("c", 3);
cart2.put("e", 5);
client.put(null, key2,
new Bin("username", "rocketbob"),
new Bin("foo", cart2));
Key key3 = new Key("test", "demo", "u3");
Map<String, Object> cart3 = new HashMap<>();
cart3.put("x", new HashMap<>(Map.of("z", 26)));
cart3.put("y", "yyy");
client.put(null, key3,
new Bin("username", "samunwise"),
new Bin("foo", cart3));

Query by map value (numeric equality)

Query foo_mapval_idx for records where the foo map contains a value equal to 1. Only records with a matching numeric value are returned — b: "2" is a string, not a numeric, so it does not match.

Statement stmt = new Statement();
stmt.setNamespace("test");
stmt.setSetName("demo");
stmt.setFilter(Filter.contains("foo", IndexCollectionType.MAPVALUES, 1));
RecordSet rs = client.query(null, stmt);
// Returns: {username: "Bob Roberts", foo: {a: 1, b: "2", c: 3}}

Query by map value (numeric equality — multiple matches)

Query for records where the foo map contains a value equal to 3. Both u1 (c: 3) and u2 (c: 3) match.

Statement stmt = new Statement();
stmt.setNamespace("test");
stmt.setSetName("demo");
stmt.setFilter(Filter.contains("foo", IndexCollectionType.MAPVALUES, 3));
RecordSet rs = client.query(null, stmt);
// Returns: Bob Roberts, rocketbob

Query by map value (numeric range)

Query foo_mapval_idx for records where the foo map contains any numeric value in the range [1, 5]. A record is returned once for each matching value in its map.

Statement stmt = new Statement();
stmt.setNamespace("test");
stmt.setSetName("demo");
stmt.setFilter(Filter.range("foo", IndexCollectionType.MAPVALUES, 1, 5));
RecordSet rs = client.query(null, stmt);
// Returns: Bob Roberts (twice: a=1, c=3), rocketbob (twice: c=3, e=5)

Query by map key (string equality)

Query foo_mapkey_idx for records where the foo map contains the key "y".

Statement stmt = new Statement();
stmt.setNamespace("test");
stmt.setSetName("demo");
stmt.setFilter(Filter.contains("foo", IndexCollectionType.MAPKEYS, "y"));
RecordSet rs = client.query(null, stmt);
// Returns: samunwise

Query by map key (multiple matches)

Query for records where the foo map contains the key "c". Both u1 and u2 have a "c" key.

Statement stmt = new Statement();
stmt.setNamespace("test");
stmt.setSetName("demo");
stmt.setFilter(Filter.contains("foo", IndexCollectionType.MAPKEYS, "c"));
RecordSet rs = client.query(null, stmt);
// Returns: Bob Roberts, rocketbob

Query by map key (no match)

Query for a key that does not exist in any record’s map. The index for "z" exists only as a nested key inside the "x" sub-map — top-level MAPKEYS indexing does not reach nested keys.

Statement stmt = new Statement();
stmt.setNamespace("test");
stmt.setSetName("demo");
stmt.setFilter(Filter.contains("foo", IndexCollectionType.MAPKEYS, "z"));
RecordSet rs = client.query(null, stmt);
// Returns: 0 records

Known limitations

  • When using range queries on maps, records can be returned multiple times if the map 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?