LoginSignup
1
2

More than 5 years have passed since last update.

Redisでzset型のデータをコピーする

Last updated at Posted at 2015-11-18

概要

Redisにランキングデータとかをzsetで格納してたのですが、そのランキングデータを使って諸々テストしたくなりまして。
とはいえ、zsetをコピーする術がcommands探してもなかった。かなしい。

そんな中で以下のようなエントリを見つけて、サクッとスクリプト書いたらコピーできちゃったお話です。
RedisのLuaスクリプティング機能について « Rest Term

Redisでlua script書ける

EVALってコマンドを使うと書けるらしい。

bash
# 127.0.0.1:6379 にredis-serverがいるとして
redis-cli
redis-cli
127.0.0.1:6379> EVAL "return 'Hello, world!'" 0
#=> "Hello, world!"

これを読むと、引数も拾える。

redis-cli
127.0.0.1:6379> EVAL "return {KEYS[1], KEYS[2], ARGV[1], ARGV[2]}" 2 key1 key2 1 2
#=> 1) "key1"
#=> 2) "key2"
#=> 3) "1"
#=> 4) "2"

127.0.0.1:6379> EVAL "return {KEYS[1], KEYS[2], ARGV[1], ARGV[2]}" 2 key1 key2
#=> 1) "key1"
#=> 2) "key2"

127.0.0.1:6379> EVAL "return {KEYS[1], KEYS[2], ARGV[1], ARGV[2]}" 2 key1
#=> (error) ERR Number of keys can't be greater than number of args

SCRIPT LOADでscriptを登録しておける

SCRIPT LOADEVALSHAを使えば諸々捗りそう。
(redis-serverが落ちなければ発行されたhashkeyは残るっぽい)

redis-cli
127.0.0.1:6379> SCRIPT LOAD "return {KEYS[1], KEYS[2], ARGV[1], ARGV[2]}"
#=> "c0d2d6f81be75d67523d7c8ac69a932fbe1aa4e2"

127.0.0.1:6379> EVALSHA c0d2d6f81be75d67523d7c8ac69a932fbe1aa4e2 2 key1 key2
#=> 1) "key1"
#=> 2) "key2"

127.0.0.1:6379> exit
redis-cli
127.0.0.1:6379> EVALSHA c0d2d6f81be75d67523d7c8ac69a932fbe1aa4e2 2 key1 key2 1 2
#=> 1) "key1"
#=> 2) "key2"
#=> 3) "1"
#=> 4) "2"

zsetをコピーするスクリプト

というわけで、この辺を参考に本題のスクリプト書いてみた。

とりあえずサンプルとしてコピー元データを作っとく。

redis-cli
127.0.0.1:6379> ZADD key1 10 1
#=> (integer) 1
127.0.0.1:6379> ZADD key1 20 2
#=> (integer) 1
127.0.0.1:6379> ZADD key1 50 3
#=> (integer) 1
127.0.0.1:6379> ZADD key1 100 4
#=> (integer) 1
127.0.0.1:6379> ZADD key1 30 5
#=> (integer) 1
127.0.0.1:6379> ZADD key1 1 6
#=> (integer) 1

127.0.0.1:6379> ZRANGE key1 0 -1
#=> 1) "6"
#=> 2) "1"
#=> 3) "2"
#=> 4) "5"
#=> 5) "3"
#=> 6) "4"

で、こんなかんじでスクリプト走らせると...

redis-cli
127.0.0.1:6379> EVAL "for i,v in ipairs(redis.call('zrange', KEYS[1], 0, -1)) do redis.call('zadd', KEYS[2], redis.call('zscore', KEYS[1], v), v) end" 2 key1 key2
#=> (nil)

127.0.0.1:6379> ZRANGE key2 0 -1
#=> 1) "6"
#=> 2) "1"
#=> 3) "2"
#=> 4) "5"
#=> 5) "3"
#=> 6) "4"

# ちゃんと`score`もコピーできてるで
127.0.0.1:6379> ZSCORE key2 6
#=> "1"
127.0.0.1:6379> ZSCORE key2 4
#=> "100"

というかんじになります。便利!

おわりに

別の言語でscript書いて実行させてもよいのだけど、カジュアルに実行できるので割と便利かな、という感想です。以上!

参考

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2