0

I'm retrieving multiple fields of a redis hash key using HMGET to simply send them using JSON:

redis.HMGET('key', 'name', 'date', // a lot more fields here,
    function(err, reply){
        res.jsonp({
            name: reply[0],
            date: reply[1],
            // other fields
        });
    }
);

Working with an high amount of fields is leading to a quite long list, and therefore for a less readable code. So I was wondering: is there a more beautiful and common way of mapping the reply array to the JSON response object - preferably without having to write down the field names twice?

3
  • Not familiar with Redis, but can't you just send an object with properties instead of an array? Commented Nov 14, 2013 at 1:41
  • I've just tried to send the field names as keys of an object, but redis is returning null. HMGET is receiving the field names in seperate arguments, not as a single array (may have failed to make it really understanable). This approach would be a nice idea though! Commented Nov 14, 2013 at 1:46
  • Possible dub: stackoverflow.com/questions/9260647/… Commented Nov 14, 2013 at 2:25

2 Answers 2

0

It's unclear to me whether you are fetching all the properties of the hash, in which case you should use hgetall which returns an object. Otherwise, you want an interface looking something like this:

hmgetObject(redis)('key', 'name', 'date', ..., function (err, reply) {
  // Here, reply is already an object

  res.jsonp(reply);
});

You'll note how passing the redis client like this lets you easily reuse the function:

var hmget = hmgetObject(redis);

hmget('key1', 'name', 'date', ...);
hmget('key2', 'foo', 'bar', ...);

Here is the implementation, which is generic and works for an arbitrary number of arguments):

function hmgetObject (redis) {

  return function () {

    var args = [].slice.call(arguments, 0),
        cb = args.pop();

    args.push(map(args.slice(1), cb));
    redis.hmget.apply(redis, args);
  }

  function map (props, cb) {

    return function (err, vals) {

      if(err) return cb(err);

      var obj = {};
      for(var i = 0, l = props.length; i < l; i++) {
        obj[props[i]] = vals[i];
      }

      cb(null, obj);
    }
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

You could handle this by using a wrapper function for HMGET, like so:

function localHMGET(key, res, fieldsArray) {
  var args = [key].concat(fieldsArray);
  args.push(function(err, reply) {
    var json = {};
    for (var i = 0; i < fieldsArray.lenth; i++) {
      json[fieldsArray[i]] = reply[i];
    }
    res.jsonp(json);
  });
  redis.HMGET.apply(this, args);
}

Which could then be called by:

localHMGET('key', res, ['name', 'date' /* More fields */] );

I don't know if this is really what you're looking for, but it will get the job (as described) done. This will manually create the arguments for the GET call, and by isolating the keys used in the GET you can rely on them to unpack the arguments into 'res' (which I'm assuming is a predefined object here).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.