Конвертируйте плоские данные в иерархию mongodb, используя Mongoose
Я создал модель, которая имеет следующие свойства:
- Я бы
- дети
- родитель
Если для родителя задано значение NULL, документ будет считаться родителем верхнего уровня. Каждый документ может иметь или не иметь список дочерних элементов, который просто содержит идентификаторы другого документа.
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;
});
};
1 ответ
Вы можете попробовать позвонить lean()
метод после 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>