cod*_*ero 1 recursion redis node.js
我希望那里有人可以用这个来解救我.出于某种原因,我无法理解node.js中的递归.如果有另一种方式,它甚至不必是递归.
我正在使用redis集来存储集合中的层次结构:
SADD parents.<name> <parent1> <parent2>
Run Code Online (Sandbox Code Playgroud)
那么,parent1和parent2也将有条目,然后是up.我想将它转换为JSON对象数组.
JSON将如下所示:
[
{
label: <name>,
parents: [
{ label: <parent1>,
parents: [ {label: <grandparent1>}] },
{ label: <parent2> }
]
}
]
Run Code Online (Sandbox Code Playgroud)
等等等等.这应该能够适用于任何深度,尽管平均来说它只有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 ))} );
Run Code Online (Sandbox Code Playgroud)
我基本上想要这样做:
任何帮助将不胜感激.
编辑:更新了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);
});
}
Run Code Online (Sandbox Code Playgroud)
编辑:我决定使用Promises,所以我追求那个选项.感谢您的帮助!
TL; DR:我制作了一个NodeJS模块(RedisTree)和一篇解释实现的博客文章.
上面的代码是初始实现
好挑战!这是一个符合您要求的实现,我添加了一个".save(tree,f)"方法,它使用了lodash,async,当然还有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
* e.g. 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
* e.g. 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);};
Run Code Online (Sandbox Code Playgroud)
以下是如何使用它:
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));
});
});
Run Code Online (Sandbox Code Playgroud)