【问题标题】:Convert flat data into hierarchy in mongodb using Mongoose使用 Mongoose 将平面数据转换为 mongodb 中的层次结构
【发布时间】:2015-09-25 08:53:58
【问题描述】:

我创建了一个具有以下属性的模型:

  1. 身份证
  2. 孩子们
  3. 父母

如果父级设置为空,文档将被视为顶级父级。每个文档可能有也可能没有子列表,其中仅包含其他文档的 ID。

db.categories.insert( { _id: "MongoDB", children: [],name: '', parent: 'Databases'} )
db.categories.insert( { _id: "dbm", children: [], parent: 'Databases' } )
db.categories.insert( { _id: "Databases", children: [ "MongoDB", "dbm" ], parent: 'Programming' } )
db.categories.insert( { _id: "Languages", children: [], parent: 'Programming' } )
db.categories.insert( { _id: "Programming", children: [ "Databases", "Languages" ],parent: 'books' } )
db.categories.insert( { _id: "Books", children: [ "Programming" ],parent: null } )

从上面的模型中,我需要生成这样的输出:

{
    name: "books",
    nodes: [
        {
            name: "Programming",
            nodes: [
                {
                    name: "Databases",
                    nodes: [
                        {
                            name: "MonogoDB"
                        },
                        {
                            name: "dbm"
                        }
                    ]
                },
                {
                    name: "Languages"
                }
            ]
        }
    ]
}

到目前为止我已经尝试过了,但是由于 findByID() 的异步性质,我没有得到想要的结果。请提出更改建议。

myDoc.find({
    parent: null
  }, function (err, topics) {
    if (err) {
      return handleError(res, err);
    }
    var docTree = [];
    _.each(document, function(parentDoc) {
       var doc = {};
       doc.text = parentDoc.name;
      doc.nodes = [];
      _.each(parentDoc.children, function(child) {
        doc.nodes.push(processChildren(child));
      });
      docTree.push(doc);

    });



function processChildren(child) {

  myDoc.findById(child, function (err,item) {
    var doc = {};
    doc.name = item._doc.name;
    doc.nodes = [];
    if (item._doc.children === null) {
      return topic;
    } else {
      _.each(item._doc.children, function (chld) {
        processChildren(chld);
      });
    }
    return doc;
  });

};

【问题讨论】:

    标签: node.js mongodb mongoose promise asynccallback


    【解决方案1】:

    您可以尝试在 find() 方法之后调用 lean() 方法,因为启用了精简选项的查询返回的文档是纯 JavaScript 对象。然后,您可以操纵这些对象以获得所需的层次结构。以下内容可能无法给出确切的预期结果,但会将您推向正确的方向:

    Model.find({}).lean().exec(function (err, docs) {
        if (err) {
          return handleError(res, err);
        }
        var i, len, temp, top_level, id, parent, hierarchical, nodePendingObj, doc, _id, _parent, _children;
        i = 0;
        top_level = [];
        temp = {};
        obj = {};
        nodePendingObj = {};
        _id = '_id';
        _parent = 'parent';
        _children = 'children';
    
        _.each(docs, function(doc) {
            id = doc['_id'];
            parent = doc[_parent];
            temp[id] = doc;
            if (parent === undefined || parent === null) {      
                obj["name"] = id;
                obj["nodes"] = doc[_children];
                top_level.push(obj);
            } 
            else {
                if (temp[parent] !== undefined) {           
                    if (temp[parent][_children] === undefined) {
                        temp[parent][_children] = [];
                    }
                    var o = {};
                    o["name"] = id;
                    if (doc[_children].length !== 0) o["nodes"] = doc[_children];
                    temp[parent][_children].push(o);
                } else {            
                    if (nodePendingObj[parent] === undefined) {
                        nodePendingObj[parent] = [];
                    }
                    var o = {};
                    o["name"] = id;
                    if (doc[_children].length !== 0) o["nodes"] = doc[_children];
                    nodePendingObj[parent].push(o);             
                }    
                delete doc[_parent];
            }
    
            if (nodePendingObj[id] !== undefined) {     
    
                var len = nodePendingObj[id].length;
                if (doc[_children] === undefined) {
                    doc[_children] = [];
                }
                while (len-- > 0) {
                    doc[_children].push(nodePendingObj[id].shift());
                }
            }
        });
    
        if (top_level.length === 1) {
            hierarchical = top_level[0];
        } else if (top_level.length > 1) {
            hierarchical = {};
            hierarchical[_children] = top_level;
        } else {
            hierarchical = {};
        }
        console.log(JSON.stringify(hierarchical));
    });
    

    查看下面的演示。

    var documents = [
    	{
    		"_id" : "MongoDB",
    		"children" : [],
    		"name" : "",
    		"parent" : "Databases"
    	},{
    		"_id" : "dbm",
    		"children" : [],
    		"parent" : "Databases"
    	},{
    		"_id" : "Databases",
    		"children" : [ 
    			"MongoDB", 
    			"dbm"
    		],
    		"parent" : "Programming"
    	},{
    		"_id" : "Languages",
    		"children" : [],
    		"parent" : "Programming"
    	},{
    		"_id" : "Programming",
    		"children" : [ 
    			"Databases", 
    			"Languages"
    		],
    		"parent" : "books"
    	},{
    		"_id" : "books",
    		"children" : [ 
    			"Programming"
    		],
    		"parent" : null
    	}
    ];
    var i, len, temp, top_level, id, parent, hierarchical, nodePendingObj, doc, _id, _parent, _children;
    i = 0;
    top_level = [];
    temp = {};
    obj = {};
    nodePendingObj = {};
    _id = '_id';
    _parent = 'parent';
    _children = 'children';
    
    
    _.each(documents, function(doc) {	
    	id = doc['_id'];
    	parent = doc[_parent];
    	temp[id] = doc;
    	if (parent === undefined || parent === null) {		
    		obj["name"] = id;
    		obj["nodes"] = doc[_children];
    		top_level.push(obj);
    	} 
    	else {
    		if (temp[parent] !== undefined) {			
    			if (temp[parent][_children] === undefined) {
    				temp[parent][_children] = [];
    			}
    			var o = {};
    			o["name"] = id;
    			if (doc[_children].length !== 0) o["nodes"] = doc[_children];
    			temp[parent][_children].push(o);
    		} else {			
    			if (nodePendingObj[parent] === undefined) {
    				nodePendingObj[parent] = [];
    			}
    			var o = {};
    			o["name"] = id;
    			if (doc[_children].length !== 0) o["nodes"] = doc[_children];
    			nodePendingObj[parent].push(o);
    			
    		}    
    		delete doc[_parent];
    	}
    	
    	if (nodePendingObj[id] !== undefined) {		
    		
    		var len = nodePendingObj[id].length;
    		if (doc[_children] === undefined) {
    			doc[_children] = [];
    		}
    		while (len-- > 0) {
    			doc[_children].push(nodePendingObj[id].shift());
    		}
    	}
    });
    
    if (top_level.length === 1) {
    	hierarchical = top_level[0];
    } else if (top_level.length > 1) {
    	hierarchical = {};
    	hierarchical[_children] = top_level;
    } else {
    	hierarchical = {};
    }
    
    pre.innerHTML = JSON.stringify(hierarchical, null, 4);
    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
    <pre id="pre"></pre>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多