Search code examples
databaseaerospike

Is it possible to search for all keys that start with a certain prefix in Aerospike?


So I am looking to model our existing redis data into aerospike. One requirement that we have is to be able to get all the keys for a given user. For eg., say we have keys such as <id>:<timestamp>. Now, at some point in time, I need to get all keys for the given id, where I would require something like a prefix search across all keys in the aerospike namespace (which are indexed) to get the values for all <id>:<timestamp> keys. Would like to know if this is possible, and if yes, how.


Solution

  • You cannot do a query on key prefix directly. The server only stores the key digest, so the key value (<id>:<timestamp> in your case) doesn't get indexed.

    The way to model this would be to add the <id> part of your key as a separate record bin. Then you can index that bin and run a query on it.

    Here is a simple example - it's using the Aerospike Node.js client but the concept is the same no matter what client you prefer:

    const Aerospike = require('aerospike')
    
    const ns = 'test'
    const set = 'demo'
    
    // connect to cluster and create index on 'id' bin
    var client = Aerospike.client()
    client.connect((err) => {
      assertOk(err, 'connecting to cluster')
      createIndex('id', 'id_idx', Aerospike.indexDataType.STRING, () => {
    
        // create a new sample record
        var userId = 'user1'
        var ts = new Date().getTime()
        var key = new Aerospike.Key(ns, set, `${userId}:${ts}`)
        var record = { id: userId, value: Math.random() }
        client.put(key, record, (err) => {
          assertOk(err, 'write record')
    
          // query for records with matching 'id'
          var query = client.query(ns, set)
          query.where(Aerospike.filter.equal('id', userId))
          var stream = query.foreach()
          stream.on('error', (error) => assertOk(error, 'executing query'))
          stream.on('end', () => client.close())
          stream.on('data', (record, meta, key) => {
            console.log(record)
          })
        })
      })
    })
    
    function assertOk (err, message) {
      if (err) {
        console.error('ERROR: %s - %s', message, err)
        process.quit()
      }
    }
    
    function createIndex (bin, name, datatype, callback) {
      var index = {
        ns: ns,
        set: set,
        bin: bin,
        index: name,
        datatype: datatype
      }
      client.createIndex(index, (err, job) => {
        assertOk(err, 'creating index')
        job.waitUntilDone(100, (err) => {
          assertOk(err, 'creating index')
          callback()
        })
      })
    }
    

    Hope this helps!