diff --git a/CHANGES b/CHANGES index 0bc9ebc..c9126df 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +== Release 0.2 + Added support for dumping out JSON to file and via API + == Release 0.1 First release to github Added initial support for loading JSON into Redis. Path support not yet fully tested diff --git a/Rakefile b/Rakefile index 612b59c..b65c5b3 100644 --- a/Rakefile +++ b/Rakefile @@ -5,11 +5,11 @@ require 'rake/testtask' require 'rake/clean' NAME = "redis-load" -VER = "0.1" +VER = "0.2" -RDOC_OPTS = ['--quiet', '--title', 'redis-load Reference', '--main', 'README'] +RDOC_OPTS = ['--quiet', '--title', 'redis-load Reference', '--main', 'README.md'] -PKG_FILES = %w( README Rakefile CHANGES ) + +PKG_FILES = %w( README.md Rakefile CHANGES ) + Dir.glob("{bin,doc,tests,examples,lib}/**/*") CLEAN.include ['*.gem', 'pkg'] @@ -20,7 +20,7 @@ SPEC = s.platform = Gem::Platform::RUBY s.required_ruby_version = ">= 1.8.5" s.has_rdoc = true - s.extra_rdoc_files = ["README", "CHANGES"] + s.extra_rdoc_files = ["README.md", "CHANGES"] s.rdoc_options = RDOC_OPTS s.summary = "Utility of loading/saving data structures from Redis" s.description = s.summary @@ -45,8 +45,8 @@ end Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'doc/rdoc' rdoc.options += RDOC_OPTS - rdoc.rdoc_files.include("README", "CHANGES", "lib/**/*.rb") - rdoc.main = "README" + rdoc.rdoc_files.include("README.md", "CHANGES", "lib/**/*.rb") + rdoc.main = "README.md" end diff --git a/bin/redis-load b/bin/redis-load index af66631..7105a60 100644 --- a/bin/redis-load +++ b/bin/redis-load @@ -32,6 +32,9 @@ MODE load-zset Load the contents of a file into a sort set. Each line is a key-value pair of entry,score + save-json + Save all or some keys as JSON. Filter keys to be saved using the --keys parameter. + save-list Save a list into a file @@ -58,6 +61,8 @@ OPTIONS specify port on which server is running --key , -k specify a key into which data is loaded + --keys , -e + specify a pattern for matching keys EOL @@ -71,7 +76,8 @@ opts = GetoptLong::new( [ "--database" , "-d" , GetoptLong::REQUIRED_ARGUMENT ], [ "--key" , "-k" , GetoptLong::REQUIRED_ARGUMENT ], [ "--file" , "-f" , GetoptLong::REQUIRED_ARGUMENT ], - [ "--jsonpath" , "-j" , GetoptLong::REQUIRED_ARGUMENT ] + [ "--jsonpath" , "-j" , GetoptLong::REQUIRED_ARGUMENT ], + [ "--keys" , "-e" , GetoptLong::REQUIRED_ARGUMENT ] ).enum_for.inject({}) { |h, (k, v)| h.update k.delete('-') => v } mode = "help" if opts["--help"] @@ -84,7 +90,7 @@ else abort USAGE end - if (mode != "load-json" && mode != "load-keys") && opts["key"] == nil + if (mode != "load-json" && mode != "load-keys" && mode != "save-json") && opts["key"] == nil abort USAGE end @@ -101,6 +107,8 @@ else cmdline.load_set() when "load-zset" cmdline.load_zset() + when "save-json" + cmdline.save_json() when "save-list" cmdline.save_list() when "save-set" diff --git a/lib/redis-load/command_line.rb b/lib/redis-load/command_line.rb index 6f82dcf..c28b2dd 100644 --- a/lib/redis-load/command_line.rb +++ b/lib/redis-load/command_line.rb @@ -49,6 +49,13 @@ def load_set() puts "#{counter} lines loaded." end + def save_json() + puts "Saving json into #{@opts["file"]}" + keys = @opts["keys"] || "*" + counter = @loader.save_json( @opts["file"], keys ) + puts "#{counter} keys saved." + end + def save_set() puts "Saving set #{@opts["key"]} into #{@opts["file"]}" size = @loader.save_set( @opts["key"], @opts["file"] ) diff --git a/lib/redis-load/loader.rb b/lib/redis-load/loader.rb index f678735..b0763ca 100644 --- a/lib/redis-load/loader.rb +++ b/lib/redis-load/loader.rb @@ -10,6 +10,28 @@ def initialize(redis) @redis = redis end + def to_json( pattern="*", limit=-1, opts=nil ) + keys = @redis.keys(pattern) + h = Hash.new + counter = 0 + keys.each do |key| + counter = counter + 1 + type = @redis.type(key) + if type == "hash" + h[key] = @redis.hgetall(key) + elsif type == "list" + h[key] = @redis.lrange(key, 0, limit) + elsif type == "set" + h[key] = @redis.smembers(key) + elsif type == "zset" + h[key] = @redis.zrange(key, 0, limit) + else + h[key] = @redis.get(key) + end + end + return JSON.fast_generate(h, opts), counter + end + def load_keys(file) f = File.new( file ) counter = process_lines(f) do |redis,line| @@ -36,7 +58,7 @@ def load_json(file, path=nil) json = Siren.query(query, json) end counter = 0 - #TODO could support proper results, not just path? + #TODO could support proper results, not just hash? if json != nil json.each_pair do |key,value| if value.class() == Array @@ -88,6 +110,16 @@ def load_zset(key, file) return counter end + def save_json(file, pattern="*", limit=-1, opts=nil) + counter = 0 + File.open( file, "w" ) do |file| + json, count = to_json(pattern, limit, opts) + file.write( json ) + counter = count + end + return counter + end + def save_list(key, file) size = @redis.llen( key ) count = 0