Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use graph lookup aggregation in a embedded array document

Here is my sample document from NetworkInfo collection.

{
"_id" : ObjectId("5a37595bd2d9ce37f86d612e"),
"edgeList" : [ 
    {
        "networkSource" : {
            "sourceId" : "pump1"
        },
        "networkRelationship" : {},
        "networkTarget" : {
            "targetId" : "chiller1",
            "parentId" : "pump1"
        }
    }, 
    {
        "networkSource" : {
            "sourceId" : "chiller1"
        },
        "networkRelationship" : {},
        "networkTarget" : {
            "targetId" : "secondaryPump1",
            "parentId" : "chiller1"
        }
    }, 
    {
        "networkSource" : {
            "sourceId" : "secondaryPump1"
        },
        "networkRelationship" : {},
        "networkTarget" : {
            "targetId" : "ahu1",
            "parentId" : "secondaryPump1"
        }
    }
]

}

I tried to create a graph lookup for the above document using the below code:

pump1->chiller1->secondary pump1->ahu1

db.getCollection("NetworkInfo").aggregate([ {$project:{_id:0}},{ $unwind : "$edgeList" }, { $out : "FlattenedNetwork" } ])
db.FlattenedNetwork.aggregate( [
{
  $graphLookup: {
     from: "FlattenedNetwork",
     startWith: "$edgeList.networkTarget.parentId",
     connectFromField: "edgeList.networkTarget.parentId",
     connectToField: "edgeList.networkTarget.targetId",
     as: "reportingHierarchy"
  }}])

This works fine. But, I wish to avoid using the temporary collection "FlattenedNetwork". I tried adding multiple aggregation functions but it didn't help.

like image 219
S.patil Avatar asked Dec 19 '17 10:12

S.patil


People also ask

What is graph lookup in MongoDB?

mongodb. MongoDB has added a new feature in its version 3.4 $graphLookup, Its is an extended version of $lookup and has enhanced capabilities which are used to perform a recursive search on a collection in an array with multiple values/fields.

Which functionality is used for aggregation framework?

8. Which of the following functionality is used for aggregation framework? Explanation: For related projection functionality in the aggregation framework pipeline, use the $project pipeline stage.

How does MongoDB lookup work?

The MongoDB Lookup operator, by definition, “Performs a left outer join to an unshared collection in the same database to filter in documents from the “joined” collection for processing.” Simply put, using the MongoDB Lookup operator makes it possible to merge data from the document you are running a query on and the ...

What is aggregation in mongoose?

What is the Aggregation Framework? Syntactically, an aggregation framework query is an array of stages. A stage is an object description of how MongoDB should transform any document coming into the stage. The first stage feeds documents into the second stage, and so on, so you can compose transformations using stages.


1 Answers

I made several tries but I did not find a real solution to this. I also watched the Webinar and this case is not covered. For this reason I decided to put a bounty on this question, with the hope that someone else could share a solution better than mine. However, the only way out (in my opinion) is using a view, that I declared like this:

db.createView("unwounded_docs", "NetworkInfo", [ 
        {
            $unwind : "$edgeList"
        }, 
        {
            $replaceRoot : {
                newRoot : "$edgeList"
            }
        }, 
        {
            $project : {
                "networkTarget" : 1
            }
        },
        {
            $addFields: {
                "_id": "$networkTarget.targetId"
            }
        }
    ]
);

I removed all useless fields just for clarity. The view will have this output:

{
    "networkTarget" : {
        "targetId" : "chiller1",
        "parentId" : "pump1"
    },
    "_id" : "chiller1"
},
{
    "networkTarget" : {
        "targetId" : "secondaryPump1",
        "parentId" : "chiller1"
    },
    "_id" : "secondaryPump1"
},
{
    "networkTarget" : {
        "targetId" : "ahu1",
        "parentId" : "secondaryPump1"
    },
    "_id" : "ahu1"
}

Since you can refer to a view in the from field of the $graphLookup stage, this is the pipeline (at least shorter than before):

db.unwounded_docs.aggregate( [
{
  $graphLookup: {
     from: "unwounded_docs",
     startWith: "$networkTarget.parentId",
     connectFromField: "networkTarget.parentId",
     connectToField: "networkTarget.targetId",
     as: "reportingHierarchy"
  }
}])
like image 179
Marco Luzzara Avatar answered Sep 19 '22 14:09

Marco Luzzara