Regex is not fully supported with filterExp (java com.aerospike.client.Exp library)

I’m trying to query keys based on regex and it is returning expected results for queries like "^key1.*" but it is not working in cases such as "^(key1|key2).*" or "^(key1|key2).*$". I’ve tried almost all the combinations but I’m not able to get it to work when I need to retrieve keys that either start with “key1” or “key2”.

My code:

    var regex = "^key.*";
    var keyRecordPairs = new ArrayList<Pair<String, Record>>();
    QueryListener queryListener = (key, asRecord) -> {
      if (key.userKey != null) {
        keyRecordPairs.add(Pair.of(key.userKey.toString(), asRecord));
      }
    };
    QueryPolicy queryPolicy = getQueryPolicy();
    queryPolicy.filterExp = Exp.build(
      Exp.regexCompare(regex, RegexFlag.ICASE, Exp.key(Type.STRING)));
    var statement = new Statement();
    statement.setNamespace("namespace");
    statement.setSetName("set");
    aerospikeClient.query(queryPolicy, statement, queryListener);

Please assume that the above code is correct and working for simple cases like "^key.*" or "key", but not for the cases that I outlined earlier. SendKey is enabled.

I have tested in Java, it works. Your issue may be that you have written records with sendKey not set to true in the WritePolicy.

Aerospike by default does not store your string key - it stores the 20 byte RIPEMD160 hash only. If you want to use Exp.key(Type.STRING) - the key also has to be stored in Aeropike which you can do, by setting (Java client) WritePolicy.sendKey set to true.

I will share the code snippet here - tested in my Jupyter Notebook environment;

//Run SI query
Statement stmt = new Statement();
stmt.setNamespace("test");
stmt.setSetName("testset");

//Filter key by expressions
Expression recKeyExp = Exp.build( 
    Exp.regexCompare(".*[2,3]", RegexFlag.ICASE|RegexFlag.NEWLINE, Exp.key(Exp.Type.STRING))
    ); 
QueryPolicy qp = new QueryPolicy();

qp.filterExp = recKeyExp;

RecordSet rs = client.query(qp, stmt);

while(rs.next()){
    Record r = rs.getRecord();
    Key thisKey = rs.getKey();  
    System.out.println(thisKey);
    System.out.println(r);
}

Output:

test:testset:key2:c10b2c764e604c439039804ec947fa2b18520d1a
(gen:1),(exp:453831888),(bins:(name:Jill),(age:20))
test:testset:key3:10fd8f59adf1833152e439a2e03c19efcb12c145
(gen:1),(exp:453831888),(bins:(name:James),(age:38))

My test data is:

Initialized the client and connected to the cluster.
key0 : (gen:1),(exp:453831888),(bins:(name:Sandra),(age:34))
key1 : (gen:1),(exp:453831888),(bins:(name:Jack),(age:26))
key2 : (gen:1),(exp:453831888),(bins:(name:Jill),(age:20))
key3 : (gen:1),(exp:453831888),(bins:(name:James),(age:38))
key4 : (gen:1),(exp:453831888),(bins:(name:Jim),(age:46))
key5 : (gen:1),(exp:453831888),(bins:(name:Julia),(age:62))
key6 : (gen:1),(exp:453831888),(bins:(name:Sally),(age:32))
key7 : (gen:1),(exp:453831888),(bins:(name:Sean),(age:24))
key8 : (gen:1),(exp:453831888),(bins:(name:Sam),(age:12))
key9 : (gen:1),(exp:453831888),(bins:(name:Susan),(age:42))

Data was added using aql:

aql> set key_send true
aql> run 'insert.aql'

where, insert.aql is:

INSERT INTO test.testset (PK, name, age) VALUES ('key1', 'Jack', 26)
INSERT INTO test.testset (PK, name, age) VALUES ('key2', 'Jill', 20)
INSERT INTO test.testset (PK, name, age) VALUES ('key3', 'James', 38)
INSERT INTO test.testset (PK, name, age) VALUES ('key4', 'Jim', 46)
INSERT INTO test.testset (PK, name, age) VALUES ('key5', 'Julia', 62)
INSERT INTO test.testset (PK, name, age) VALUES ('key6', 'Sally', 32)
INSERT INTO test.testset (PK, name, age) VALUES ('key7', 'Sean', 24)
INSERT INTO test.testset (PK, name, age) VALUES ('key8', 'Sam', 12)
INSERT INTO test.testset (PK, name, age) VALUES ('key9', 'Susan', 42)
INSERT INTO test.testset (PK, name, age) VALUES ('key0', 'Sandra', 34)

Hope that helps.

1 Like