使用node.js从redis获取hierchical数据

我希望有人可以用这个来救我。 出于某种原因,我无法绕过node.js中的recursion。 如果还有其他方法,它甚至不需要recursion。

我正在使用redis集来存储层次结构:

SADD parents.<name> <parent1> <parent2> 

那么,parent1和parent2也将有条目,并在上面。 我想将其转换为JSON数组对象。

JSON将如下所示:

 [ { label: <name>, parents: [ { label: <parent1>, parents: [ {label: <grandparent1>}] }, { label: <parent2> } ] } ] 

等等等等。 这应该能够工作在任何深度,但平均而言,它只能达到4-6节点深度。

下面是我一直在玩的一些代码,只是让我第一级:

 var redis = require('node-redis'); var r_client = redis.createClient(); function get_parents (name, current, cb) { var output = new Array; output.push( { label: name, parents: [] } ); r_client.smembers('parents.' + name, function(err, reply) { for (var i = 0; i < reply.length; i++) { var name = reply[i].toString('utf8'); output[i].parents.push({label: name, parents: [] }); } cb (output); }); } get_parents( 'bob', function(out) {console.log('Final output: ' + JSON.stringify( out ))} ); 

我基本上想这样做:

  • 从根节点开始。 打电话redis,得到父母。
  • 为根节点构build对象。
  • 调用相同的函数来构build其他对象。
  • 由于对redis的调用开始返回null,调用将返回并开始合并对象。

任何帮助将不胜感激。

编辑:更新get_parents(仍然不起作用):

 function get_parents (name, cb) { r_client.smembers('parents.' + name, function(err, reply) { for (var i = 0; i < reply.length; i++) { var name = reply[i].toString('utf8'); output.push( { label: name, parents: [] } ); output[i].parents = get_parents (output[i].parents.name, cb); } cb (output); }); } 

编辑:我决定使用承诺,所以我追求这个select 。 感谢所有的帮助!

TL; DR :我做了一个NodeJS模块( RedisTree )和一个博客文章解释了实现。


上面的代码是最初的实现

很好的挑战! 这里有一个匹配你的需求的实现,我添加了“.save(tree,f)”方法,它使用lodashasync ,当然还有node_redis

 var sampleTree = [{ label: 'label1', parents: [{ label: 'label2', parents: [{ label: 'label4', parents: [] }] }, { label: 'label3', parents: [] }] }]; // Note: it's required to use a set in order to retrieve data // SET: // sadd label1 label2 label3 // sadd label2 label4 var _ = require('lodash'); var async = require('async'); var redis = require('redis').createClient(); function RedisTree(){} /** * Iteratively & asynchronously retrieve an item from Redis * @param {String} label label name (set name) * @param {Function} f(err, arrayOfItems) */ RedisTree.prototype._getItem = function(label, f) { var parent = _.isArray(_.last(arguments)) ? _.last(arguments) : []; this.members(label, function(err, cards){ var item = { label: this.label(label), parents: [] }; parent.push(item); if(cards.length === 0){return f(null, parent);} async.map(cards, _.partialRight(this._getItem.bind(this), item.parents), function(e){f(e, parent);}); }.bind(this)); }; RedisTree.prototype._saveItem = function(item, f) { var labels = _.pluck(item.parents, 'label'); if(labels.length === 0){return f();} redis.sadd(item.label, labels, function(err){ if(err){return f(err);} this._saveItems(item.parents, f); }.bind(this)); }; /** * * @param {Array} arrToSave array of items * @param {Function} f(err) */ RedisTree.prototype._saveItems = function(arrToSave, f) { async.forEach(arrToSave, this._saveItem.bind(this), f); }; /** * Retrieve a name from the label * Can be overridden to provide namespace support * eg return label.substring(2); * @return {[type]} [description] */ RedisTree.prototype.label = function(label){return label;}; /** * Retrieve every members of the `label` set from redis * Can be overridden to provide namespace support * eg redis.smembers('ns.'+label, f); * @param {[type]} label [description] * @param {[type]} f [description] */ RedisTree.prototype.members = function(label, f) {redis.smembers(label, f);}; /** * Load a tree from Redis * @param {String} startLabel Were to start * @param {Function} f(err, tree) */ RedisTree.prototype.load = function(startLabel, f){this._getItem(startLabel, f);}; /** * Save a tree from Redis * @param {Array} treeArray * @param {Function} f(err, tree) */ RedisTree.prototype.save = function(treeArray, f){this._saveItems(treeArray, f);}; 

以下是如何使用它:

 var t = new RedisTree(); // Save the sampleTree t.save(sampleTree, function(err){ // or ... retrieve it starting at "label1" t.load('label1', function(err, tree){ console.log("sampleTree === ", JSON.stringify(tree, null, 1)); }); }); 

你确定你不能把它存储为磁盘或MongoDB的JSON? 此外,为什么你想要的结果列出父母而不是孩子?