我希望外面的人能用这个来救我。由于某些原因,我无法思考node.js中的递归问题。如果有其他方法的话,它甚至不必是递归的。
我使用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 ))} );我基本上想这么做:
任何帮助都将不胜感激。
编辑:更新的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);
});
}编辑:我决定使用承诺,所以I pursued that option。谢谢你的帮助!
发布于 2013-09-17 16:09:09
TL;DR:我制作了一个NodeJS模块(RedisTree)和一个解释实现的blog post。
上面的代码是最初的实现
不错的挑战!下面是一个与您的需求相匹配的实现,我添加了一个".save(tree,f)“方法,它使用了lodash、async,当然还有node。
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);};下面是如何使用它:
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));
});
});发布于 2013-09-17 17:42:45
您确定不能将它作为JSON存储在磁盘上或使用MongoDB吗?另外,为什么你想要的结果是父母而不是孩子呢?
https://stackoverflow.com/questions/18826583
复制相似问题