MongoDB $ graphLookup получить дочерний результат всех уровней - PullRequest
0 голосов
/ 08 июня 2018

Как показано в https://www.slideshare.net/mongodb/webinar-working-with-graph-data-in-mongodb, слайд 50 , можно использовать $graphLookup в представлении, чтобы получить древовидную структуру с 2 уровнями в вложенном формате .

У меня есть коллекция MongoDB с узлами дерева в виде документов следующего формата:

{ "_id" : { "$oid" : "5b1a952361c6fa3418a15660" }, 
"nodeId" : 23978995, 
"name" : "settings", 
"type" : "Node",
"parentId" : [ 23978893, 23979072, 23979081 ] }

Я создал вид как:

db.createView("treeView", "node", [
{
 $graphLookup: {
    from: "node",
    startWith: "$nodeId",
    connectFromField: "nodeId",
    connectToField: "parentId",
    maxDepth: 0,
    as: "children"
 }
}
]);

И явыполнить поиск в графе, например:

db.node.aggregate([ 
{ $match: {"nodeId": 23978786 } },
{
 $graphLookup: {
    from: "treeView",
    startWith: "$nodeId",
    connectFromField: "nodeId",
    connectToField: "parentId",
    maxDepth: 0,
    as: "children"
 }
}
]);

Мой вопрос: как мне получить всю иерархию, все уровни?

Ответы [ 2 ]

0 голосов
/ 08 марта 2019

@ kmandalas Я сталкиваюсь с такой проблемой за последние 2 дня, моя коллекция немного отличается, но концепция такая же, как ваша. Надеюсь, то, что я написал, поможет вам получить результат (я использую ссылку наSO ответы)

Моя схема сбора выглядит так:

const Category = new Schema({
    sTitle: { type: String, trim: true },
    iParentId: { type: mongoose.Schema.Types.ObjectId, ref: 'Category' },
    bStatus: { type: Boolean, default: true },
    dUpdatedAt: { type: Date },
    dCreatedAt: { type: Date, default: Date.now }
});

Во-первых, я использую $ graphLookup, затем я собрал всех детей в одного подходящего родителя, например:

{
  "_id": "5c6fa228c30bbf02cf12fe6c",
   "sTitle": "firstParent",
   "childrens":[{obj},{obj},{obj},{obj}]    // Childrens as well as grandChild
},
{
  "_id": "5c80d644ab57dd06d48cc474",
   "sTitle": "secondParent",
   "childrens":[]     //No Child
},
.....

Получив такой результат, я создаю дерево в узле js без использования сторонней библиотеки lib.древовидный логический код :(! note: docs - это вывод $ graphlooup больше ничего)

function list_to_tree(list) {
            var map = {}, node, roots = [], i;
            for (i = 0; i < list.length; i += 1) {
                map[list[i]._id] = i;
                list[i].children = [];
            }
            for (i = 0; i < list.length; i += 1) {
                node = list[i];
                if (node.iParentId !== null && map[node.iParentId] !== undefined) {
                    var node2 = {         //Because i need only _id,Title & childrens
                        _id: node._id,
                        Title: node.sTitle,
                        children: node.children
                    }
                    list[map[node.iParentId]].children.push(node2); //You can push direct "node"
                } else {
                    var node2 = {
                        _id: node._id,
                        Title: node.sTitle,
                        children: node.children
                    }
                    roots.push(node2);
                }
            }
            return roots;
        }
        let final_result = []     //For Storing all parent with childs
        if (docs.length >= 0) {   
            docs.map(single_doc => {  //For getting all parent Tree
                var single_child = list_to_tree(single_doc.children)
                var obj = {
                    _id: single_doc._id,
                    Title: single_doc.sTitle,
                    children: single_child
                }
                final_result.push(obj)
            })
        }
        console.log("Final Tree is : ",final_result)

Надеюсь, это поможет Вам

0 голосов
/ 12 июня 2018

К сожалению, вы не можете получить полную глубину во вложенном формате.Использование представления - это обходной путь, который позволяет вам выполнить эту операцию, но вам нужно будет создать новое представление для каждого необходимого уровня встраивания.Вместо этого я хотел бы рассмотреть выполнение graphLookup без предоставления глубины, начиная с корневого уровня, извлекая всю иерархию в одном запросе, прежде чем вычислять дерево на уровне приложения.

Это будет выглядеть примерно так:

db.node.aggregate([
    { $match: {
        parentId: null
    }},
    { $graphLookup: {
        from: "node",
        startWith: "$nodeId",
        connectFromField: "nodeId",
        connectToField: "parentId",
        depthField: "depth",
        as: "children"
    }}
]);

Это должно позволить вам извлечь всю иерархию за один раз, поэтому затем вам нужно вычислить дерево в вашем приложении, исходя из информации, которую вы будете иметь в массиве "children".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...