Chapter 8. Indexing Non-Scalar Data Types

Table of Contents

Indexing Arrays
Indexing Maps
Indexing by Map Keys
Indexing by Map Values
Indexing by a Specific Map Key Name
Indexing by Map Key and Value
Indexing Embedded Records

We describe how to index scalar data types in Creating Indexes, and we show how to read using indexes in Reading Indexes. However, non-scalar data types (Arrays, Maps and Records) require more explanation, which we give here.

Index creation is accomplished using the CREATE INDEX statement. See CREATE INDEX for details on this statement.

Indexing Arrays

You can create an index on an array field so long as the array contains scalar data, or contains a record with scalar fields.

Note

You cannot index a map or array that is nested beneath another map or array. This is not allowed because of the potential for an excessively large number of index entries.

Be aware that indexing an array potentially results in multiple index entries for each row, which can lead to very large indexes.

To create the index, first create the table:

CREATE TABLE myArrayTable (
    uid INTEGER,
    testArray ARRAY(STRING),
    PRIMARY KEY(uid)
) 

Once the table has been added to the store, create the index:

CREATE INDEX arrayFieldIndex on myArrayTable (testArray) 

In the case of arrays, the field can be indexed only if the array contains values that are of one of the other indexable types. For example, you can create an index on an array of Integers. You can also create an index on a specific record in an array of records. Only one array should participate in an index, otherwise the size of the index can grow exponentially because there is an index entry for each array entry.

To retrieve data using an index of arrays, you first retrieve the index using its name, and create an instance of IndexKey that you will use to perform the index lookup:

Index arrayIndex = myTable.getIndex("arrayFieldIndex");
IndexKey indexKey = arrayIndex.createIndexKey(); 

Next you create an ArrayValue instance, and assign a value to it. When you perform the index lookup, the only records that will be returned will be those which have an array with at least one item matching the value set to the ArrayValue. For example, if you have individual records that contain arrays like this:

Record 1: ["One," "Two", "Three"]
Record 2: ["Two", "Three", "One"]
Record 3: ["One", "Three", "One"]
Record 4: ["Two", "Three", "Four"] 

and you then perform an array lookup on the array value "One", then Records 1 - 3 will be returned, but not 4.

To set an ArrayValue, construct it using IndexKey.putArray(). Pass the method the name of the array field. Then add the index value to the ArrayValue instance using an array of the appropriate type:

ArrayValue av = indexKey.putArray("testArray");
av.add("One"); 

After that, you retrieve the matching table rows, and iterate over them in the same way you would any other index type. For example:

TableIterator<Row> iter = tableH.tableIterator(indexKey, null, null);
System.out.println("Results for Array value 'One' : ");
try {
    while (iter.hasNext()) {
        Row rowRet = iter.next();
        int uid = rowRet.get("uid").asInteger().get();
        System.out.println("uid: " + uid);
        ArrayValue avRet = rowRet.get("testArray").asArray();
        for (FieldValue fv: avRet.toList()) {
            System.out.println(fv.asString().get());
        }
    }
} finally {
    if (iter != null) {
        iter.close();
    }
}