MongoDB $ graphLookup получает детей на всех уровнях глубоко - вложенный результат

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

У меня есть коллекция 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"
 }
}
]);

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


person kmandalas    schedule 08.06.2018    source источник
comment
$graphLookup не возвращает вложенный формат. Вы получаете результат в точности так, как вы бы видели, и при желании можете добавить свойство, чтобы указать найденную глубину совпадения. Если вы ищете бесконечную глубину, тогда должна быть довольно ясная причина, по которой этого не существует для базы данных. Вы, конечно, можете указать maxDepth, на сколько глубинных рекурсий вам действительно нужно пройти.   -  person Neil Lunn    schedule 09.06.2018
comment
@NeilLunn, пожалуйста, взгляните на предоставленные мной источники. Благодаря созданию представления и запуску $graphLookup в представлении достигается вложение. Я получаю это в действии. Теперь о чем я спрашиваю, могу ли я получить это во всей глубине.   -  person kmandalas    schedule 09.06.2018
comment
Я думаю, что этот ответ является полным ответом GraphQL Hierarchy   -  person Mehran Ishanian    schedule 10.05.2021


Ответы (2)


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

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

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

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

person Charles Sarrazin    schedule 12.06.2018

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

My Collection Schema is like :

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
},
.....

Получив такой результат, я создаю дерево в node js без использования сторонней библиотеки. код древовидной логики :(! примечание: 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)

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

person vajid khokhar    schedule 08.03.2019