Created
April 12, 2013 06:29
-
-
Save mash/5369915 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package Redis::Custom; | |
| use strict; | |
| use warnings; | |
| # Redis::Custom->setup_custom_command( $redis, 'saddnested', $lua_script, 1 ); | |
| sub setup_custom_command { | |
| my ($package, $redis, $command_name, $lua_script, $key_count, @binded_values) = @_; | |
| my ($sha1) = $redis->script_load( $lua_script ); | |
| { | |
| no strict 'refs'; | |
| no warnings 'redefine'; | |
| *{ "Redis::$command_name" } = sub { | |
| my $self = shift; | |
| $self->evalsha( $sha1, $key_count, @binded_values, @_ ); | |
| }; | |
| } | |
| } | |
| 1; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package Redis::Nested; | |
| use strict; | |
| use warnings; | |
| use Redis::Custom; | |
| use Data::Section::Simple qw(get_data_section); | |
| sub setup_nested { | |
| my ($package, $redis, $separator) = @_; | |
| my $saddnested = get_data_section( 'saddnested.lua' ); | |
| my $smembersnested = get_data_section( 'smembersnested.lua' ); | |
| Redis::Custom->setup_custom_command( $redis, 'saddnested', $saddnested, 2, ':' ); | |
| Redis::Custom->setup_custom_command( $redis, 'smembersnested', $smembersnested, 2, ':' ); | |
| } | |
| 1; | |
| __DATA__ | |
| @@ saddnested.lua | |
| --thanks to http://d.aoikujira.com/blog/index.php?2009%252F04%252F16%252FLua%E3%81%AEstring%E3%81%ABsplit%E3%81%A8join%E3%82%92%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B | |
| --[[* split string *]]-- | |
| -- return iterator | |
| string.split_it = function(str, sep) | |
| if str == nil then return nil end | |
| assert(type(str) == "string", "str must be a string") | |
| assert(type(sep) == "string", "sep must be a string") | |
| return string.gmatch(str, "[^\\" .. sep .. "]+") | |
| end | |
| -- return table | |
| string.split = function(str, sep) | |
| local ret = {} | |
| for seg in string.split_it(str, sep) do | |
| table.insert( ret, seg ) | |
| end | |
| return ret | |
| end | |
| -- saddnested( '.', 'a.b.c', 'd' ) | |
| -- -> sadd('a', 'b') | |
| -- sadd('a.b', 'c') | |
| -- sadd('a.b.c','d') | |
| -- return 1 on success | |
| local saddnested = function(separator, str, val) | |
| assert( str ~= nil, 'provide str argument' ) | |
| assert( val ~= nil, 'provide val argument' ) | |
| local parts = str:split( separator ) | |
| for i,part in ipairs(parts) do | |
| if i == #parts then | |
| redis.call( 'sadd', str, val ) | |
| else | |
| redis.call( 'sadd', table.concat( parts, separator, 1, i ), parts[ i + 1 ] ) | |
| end | |
| end | |
| return 1 | |
| end | |
| return saddnested( KEYS[1], KEYS[2], ARGV[1] ) | |
| @@ smembersnested.lua | |
| -- smembersnested( '.', 'a', 2 ) | |
| -- 1. fetches smembers( 'a' ) | |
| -- 2. calls smembers( 'a.' .. smember ) for each smember, recursively | |
| -- 3. join the results | |
| -- return table | |
| local function smembersnested( separator, str, depth ) | |
| assert( depth ~= nil, "provide depth argument" ) | |
| local members = redis.call( 'smembers', str ) | |
| if depth == 0 then | |
| return members | |
| elseif #members == 0 then | |
| return members | |
| end | |
| depth = depth - 1 | |
| local ret = {} | |
| for i,member in ipairs(members) do | |
| local deep_members = smembersnested( separator, str .. separator .. member, depth ) | |
| for j,m in ipairs(deep_members) do | |
| table.insert( ret, m ) | |
| end | |
| end | |
| return ret | |
| end | |
| return smembersnested( KEYS[1], KEYS[2], tonumber(ARGV[1]) ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment