更清洁的方法在node.js中执行多个redis查询

时间:2011-11-22 09:31:34

标签: node.js redis

我做了一些node.js代码来检索redis数据库中的数据,但我真的不高兴,我想改进它...
基本上,我的redis数据库中有一个“人”记录。从“人”我得到一个“人:我”的列表(我是一个整数),并为每个“人:我”,我做了一个额外的查询,以检索关键“人:我”的哈希。

我就是这样做的:

db.smembers("people", function(err1, people){
  var jsonObj;
  var jsonArr = [];
  if(!err1) {
    var i = 0;
    res.writeHead(200, {'content-type': 'application/json'});
    // people will provide a list like [person:1, person:2, ..., person:n]
    people.forEach(function(person){
      // In redis I get the hash with key "person:i" 
      db.hgetall(person, function(err2,obj){
        if(!err2){
          // Add person into array
          jsonArr.push({ "id" : person.substring(7), "lastname" : obj["lastname"], "firstname" : obj["firstname"]});

          // I'm not happy with this part where I check if I reached the last item of people array....
          i = i + 1;
          if(i == people.length){
            res.write(JSON.stringify(jsonArr));
            res.end();
          }
        } else {
          var jsonObj = { "error" : "database error", "message" : "Cannot get hash " + person}; 
          res.write(JSON.stringify(jsonObj));
          res.end();
        }
      });
    });
  } else {
    jsonObj = { "error" : "database error", "message" : err1.message };
    res.writeHead(200, {'content-type': 'application/json'});
    res.write(JSON.stringify(jsonObj));
    res.end();
  }
});

最干净的(至少是更干净的)方法是什么?

1 个答案:

答案 0 :(得分:4)

您正在寻找的是异步控制流系统。一个例子是Stepstreamline.js

另一种方法是抽象流程,为Person创建一个数据模型,用于获取单个人对象,以及People模型,这是一个人员集合,其中包含一个方法,用于根据您所在的结构获取多个人使用

编辑:我找到了节点兼容控制流/异步库的完整列表:https://github.com/joyent/node/wiki/modules#wiki-async-flow

编辑:在审核完您的代码后,我想到了另一种非常特殊的替代方法,但没有直接解决问题的控制流性质。

通过更改架构以仅存储people密钥中人员的ID,您可以使用redis的SORT命令打开自己,这将使整个集合可以在单个命令中获取。要在redis中执行此操作:

> SADD people 1 2 3 4
> HMSET person:1 firstname John lastname Smith
> HMSET person:2 firstname Jane lastname Smith
> HMSET person:3 firstname John lastname Doe
> HMSET person:4 firstname Jane lastname Doe
> SORT people GET # GET person:*->firstname GET person:*->lastname
 1) "1"
 2) "Jane"
 3) "Doe"
 4) "2"
 5) "Jane"
 6) "Smith"
 7) "3"
 8) "John"
 9) "Doe"
10) "4"
11) "Jane"
12) "Doe"

这可以在people键中节省内存,并通过SORT命令的bylimit选项启用分页/排序。