Search code examples
aerospikeaql

Querying on key of a Map in Aerospike


I'm trying to store a map in aerospike and fetch the data based on the key of the map.

First I created a Index on the bin where i'm storing the map

 aql> create mapkeys index status on test.myset (state) String
 aql> show indexes
+--------+---------+-----------+---------+-------+-----------+---------+------------+----------+
| ns     | bin     | indextype | set     | state | indexname | path    | sync_state | type     |
+--------+---------+-----------+---------+-------+-----------+---------+------------+----------+
| "test" | "state" | "MAPKEYS" | "myset" | "RW"  | "status"  | "state" | "synced"   | "STRING" |
+--------+---------+-----------+---------+-------+-----------+---------+------------+----------+
1 row in set (0.000 secs)
OK

Then I used java client to store the map

AerospikeClient client = new AerospikeClient("127.0.0.1",3000);

    WritePolicy writePolicy = new WritePolicy();
    writePolicy.timeout=500;

    for(int i = 1;i<10;i++){
        Key key = new Key("test","myset",""+i);
        client.delete(writePolicy, key);

        HashMap<String,String> map = new HashMap<String,String>();
        map.put("key1", "string1");
        map.put("key2", "string2");
        map.put("key3", "string3");

        Bin bin = new Bin("state", map);
        client.put(writePolicy, key, bin);

    }

I checked the data through apl and the data is clearly present.

aql> select * from test.myset
+--------------------------------------------------------+
| state                                                  |
+--------------------------------------------------------+
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
| {"key1":"string1", "key2":"string2", "key3":"string3"} |
+--------------------------------------------------------+
10 rows in set (0.019 secs)

Now when I try to query based on the index created it gives

aql> select * from test.myset where status = 'key1'
0 rows in set (0.000 secs)
Error: (204) AEROSPIKE_ERR_INDEX

aql> select * from test.myset where state = 'key1'
0 rows in set (0.000 secs)
Error: (201) AEROSPIKE_ERR_INDEX_NOT_FOUND

Can someone help me with this. I searched for that error but found no information. Thank you.


Solution

  • Secondary indexes on MapKeys, MapValues, Lists are supported by Aerospike, apart from Numeric, String and Geo2DSphere types.

    For your scenario, you can query on the Mapkey as follows.

    select * from test.myset in mapkeys where state='key1'
    

    This should return the results.

    In AQL, if you type help, you should get the following for queries

        SELECT <bins> FROM <ns>[.<set>]
        SELECT <bins> FROM <ns>[.<set>] WHERE <bin> = <value>
        SELECT <bins> FROM <ns>[.<set>] WHERE <bin> BETWEEN <lower> AND <upper>
        SELECT <bins> FROM <ns>[.<set>] WHERE PK = <key>
        SELECT <bins> FROM <ns>[.<set>] IN <indextype> WHERE <bin> = <value>
        SELECT <bins> FROM <ns>[.<set>] IN <indextype> WHERE <bin> BETWEEN <lower> AND <upper>
    

    Similarly, you can run a query for the MapValue as well.