3

node_redisを使用して node.js で redis データベースを操作しています。これは、私が使用しているものと同様の構造の簡単な例です。

hmset('user:1234', 
    'user_id', 1234, 
    'user_name', billy, 
    'user_age', 16);
//add user to group 1 store their id with their age as their score
zadd(['group:1:users_by_age', 16, user:1234]);

hmset('user:1235', 
    'user_id', 1235, 
    'user_name', jake, 
    'user_age', 21);
//add user to group 1 store their id with their age as their score
zadd(['group:1:users_by_age', 21, user:1235]);

ここで、グループ 1 の 18 歳以上のユーザーのすべてのユーザー データを取得したいとします。

電話することでユーザーキーを取得できることを知っています

postClient.zrangebyscore( 
    [ 'group:1:users_by_age', '18', '+inf'],
    function( err, results ){
        console.log(results);
    }
);

すべてのユーザー オブジェクトを一度にフェッチするにはどうすればよいのでしょうか。さらに一歩進めると、1回の呼び出しでzrangebyscoreとすべてのユーザーオブジェクトを取得することは可能ですか?

4

1 に答える 1

3

さらに一歩進めると、1回の呼び出しでzrangebyscoreとすべてのユーザーオブジェクトを取得することは可能ですか?

私はあなたができるとは思わない。SORT コマンドには GET 機能が組み込まれており、1 回の呼び出しでそのようなことを行うことができますが、ZRANGEBYSCORE の結果を SORT にパイプする方法はありません (一時キーに格納してから、そのキーで SORT を使用することを禁止します)。

また、1 回の呼び出しで複数のハッシュを取得する自然な方法もありません。

現在の実装では、これらの制限を考慮して、次のようなマルチですべてのユーザーを取得できます。

postClient.zrangebyscore([...], function (err, results) {
  var multi = postClient.multi();
  for (var i=0; i<results.length; i++){
    multi.hgetall(results[i]);
  }
  multi.exec(function(err, users){
    console.log(users);
  });
});

ただし、luascript を使用してこれを行うこともできます。キーのリストを取得して反復し、各キーで hmget または hgetall を呼び出します。

次の例では、hmget と特定のキーを使用して、このようなことを行います。

明らかな免責事項: 私は lua プログラマーではありません。簡単な説明: スクリプトは、ユーザーの年齢の開始範囲と終了範囲を取り、次に各ユーザー キーの hmget に使用する任意の数のハッシュ キーを取り、それをすべて配列に追加します。この配列は、JavaScript でユーザー オブジェクトとしてラップされます。 .

var script = '\
local keys = redis.call("ZRANGEBYSCORE", KEYS[1], ARGV[1], ARGV[2]); \
if not keys then return {} end; \
local users, attrs = {}, {} \
for i=3,#ARGV do \
  table.insert(attrs, ARGV[i]) \
end \
for i,key in pairs(keys) do \
  local vals = redis.call("HMGET", key, unpack(attrs)); \
  if vals then \
    for j,val in pairs(vals) do \
      table.insert(users, val) \
    end \
  end \
end \
return users \
';

// The rest of this you'd probably want to wrap up in an async function, 
// e.g `getUsersByRange`

// specify the user attributes you want
var attrs = ["id", "name", "age"];

// specify the range
var range = [18, "+INF"];

// get the attributes length, used to build the user objects
var attrlen = attrs.length;

// wrap up the params
var params = [script, 1, "users_by_age"].concat(range).concat(attrs);

// retrieve the user attributes in the form of [a1, a2, a3, a1, a2, a3, ... ],
// then collate them into an array of user objects like hgetall would return.
postClient.eval(params, function (err, res) {
  var users = [], i, j, k;
  for (i=0, j=0; i<res.length; i+=attrlen, j++) {
    users[j] = {};
    for (k=0; k<attrlen; k++) {
      users[j][attrs[k]] = res[i+k];
    }

    // this should be a list of users
    console.log(users);
  }
});

ユーザーを処理して lua スクリプト内のオブジェクトに戻すのは簡単ですが、redis データ構造に戻すと、lua テーブルは redis マルチバルク応答 (配列) になり、構造が失われることに注意してください。そのため、複数の一括返信を JavaScript のユーザー オブジェクトに変換する必要があります。

于 2013-05-01T19:06:19.217 に答える