2016年10月15日土曜日

redisでset->zsetのコピーだとか、zset->zsetのコピーだとかをLuaスクリプトでやろう的なお話

  • このエントリーをはてなブックマークに追加

redisを使うと色々と便利なわけで。
特にzsetとかはscoreで自動的にソートしてくれるし取り出しやすいし。
あと集合演算とか。

けどそんな中でもちょっと物足りない機能とかあるわけで。
特に集合演算はもちろん同じ型でないとできないからちょっと面倒だしなぁと。
それにzset型はdiff(差集合)ができないわけで。

で、それを解決するには値をそのままに、zsetをset型にしたいとか、set型をzset型にしたいとかそういうことがあるわけで。
ということで今日はそのお話をば。

// set->zset
for i,v in ipairs( redis.call('smembers', KEYS[1]) ) do
  for i2,v2 in ipairs( redis.call('zrange', 'user:'..v..':post', 0, -1) ) do
    redis.call('zadd', KEYS[2], v, v2)
  end
end

redis:0>EVAL "for i,v in ipairs( redis.call('smembers', KEYS[1]) ) do for i2,v2 in ipairs( redis.call('zrange', 'user:'..v..':post', 0, -1) ) do redis.call('zadd', KEYS[2], v, v2) end end" 2 dst_key src_key

// zset->zset
for i,v in ipairs( redis.call('zrange', KEYS[1], 0, -1) ) do
  redis.call('zadd', KEYS[2], i, v)
end

redis:0>EVAL "for i,v in ipairs( redis.call('zrange', KEYS[1], 0, -1) ) do redis.call('zadd', KEYS[2], i, v) end" 2 dst_key src_key

こんな感じ。
わかりづらいから該当する部分だけそれぞれわかりやすく書いたのも載せておく。
とりあえずEVALを使ってあげればよい。
で、redis.call('関数名')でredisの関数が使えるので、それでデータを取り出してfor文で回してあげるっていう。

これを使うとsetをzsetとしたり、むしろzsetからlistを作れたりなどなど。
特に集合計算を行いたいときに、listからsetを生成するとかもできるっていう。

Luaとか難しいんじゃないかって感じるかもしれないけど、スクリプト言語だからbashだとかphpだとかに似てるからわかりやすいっていう的なみたいな。

Adsense