Questions related to $graphLookup

Hi Support Team,

I have few questions related to graphLookup. I am not clear about the different use of startWith and connectFromField. In all the available lectures on this topic, the field used for both these parameters was the same. Then what is the use of having two different parameters in the syntax. And if both these parameters are different and are used differently, then please provide an example. Also I would encourage you to please have this incorporated into the lecture too since the lecture does not bring out the difference properly

Additionally startWith had the ‘$’ sign which was further confusing. We did not ‘$’ sign with either the connectFrom or connectToField but we did it use it for startWith why?

One more thing I know that when we use ‘$’ sign it refers to field path. But what is field path and why we some times use the ‘$’ sign but sometimes we don’t like for eg even in match stages we don’t use ‘$’ sign along with field name but in few cases in project I saw the use of ‘$’ sign. When exactly is the ‘$’ sign used and when is it not used.

Regards,
Harpreet

When at the left of the colon, it is always a field name, so never need . When it is on the right of the colon, it is a value, the allows the software to know that the value is a field name rather than a string value.

Take a look at https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/ for the difference between startWith and connectFromField. Take particular attention to the type of startWith and connectFromField. The first is <expression> while the second is <string>. The second one is always a field name, so no . The first one is an expression, so if the expression is a field name we put to indicate that it is a field name.

1 Like

Hi @KaurPreet,

Thanks for sharing this feedback!!

Please feel free to reach out if you still have any questions.

Thanks,
Sonali

Hi Steeve,

That is exactly my whole point. Even on the right side of the colon, the fields sometimes have a ‘$’ sign and sometimes don’t. It is very difficult to remember with which operator one should and one shouldn’t. Even within one single operator for eg graphLookup ‘$’ sign is used with startWith but not with connectFromField or connectToField. If there is some logic/formula to remember when to use and when not to that will be great.

It looks like you miss the whole point of my post.

startWith is of type so a $ is needed to refer to a field name
connectFromField and connectToField are of type and with a name ending with Field the string is a field name.

This is the whole logic. When the doc. says it is a string and it is a field name, you do not need a . When the doc. says it is an expression then you need to specify a field.

@Sonali_Mamgain How I can use $project with $graphLookup?
I found

db.people.aggregate( [
  { $match: { "name": "Tanya Jordan" } },
  { $graphLookup: {
      from: "people",
      startWith: "$friends",
      connectFromField: "friends",
      connectToField: "name",
      as: "golfers",
      restrictSearchWithMatch: { "hobbies" : "golf" }
    }
  },
  { $project: {
      "name": 1,
      "friends": 1,
      "connections who play golf": "$golfers.name"
    }
  }
] )

Output like that:

{
   "_id" : 1,
   "name" : "Tanya Jordan",
   "friends" : [
      "Shirley Soto",
      "Terry Hawkins",
      "Carole Hale"
   ],
   "connections who play golf" : [
      "Joseph Dennis",
      "Tanya Jordan",
      "Angelo Ward",
      "Carole Hale"
   ]
}

But I want output look like:

{
   "_id" : 1,
   "name" : "Tanya Jordan",
   "friends" : [
      "Shirley Soto",
      "Terry Hawkins",
      "Carole Hale"
   ],
   "connections who play golf" : [
      {_id: 1, name: "Joseph Dennis"},
      {_id: 2, name: "Tanya Jordan"},
      {_id: 3, name: "Angelo Ward"},
      {_id: 4, name: "Carole Hale"}
   ]
}

First, thanks for using the proper markup for your code. It is really appreciated.

Try replacing

"connections who play golf": "$golfers.name"

with

"connections who play golf": {
"_id" : "$golfers._id ,
"name" , "$golfers.name"
}

I did not test it yet, so sorry in advance, if it is not appropriate.

Thanks for your response. I try it before but it did not work well
Look like that

{
   "_id" : 1,
   "name" : "Tanya Jordan",
   "friends" : [
      "Shirley Soto",
      "Terry Hawkins",
      "Carole Hale"
   ],
   "connections who play golf" : {id: [1, 2, 3, 4], name: [
      "Joseph Dennis",
      "Tanya Jordan",
      "Angelo Ward",
      "Carole Hale"
   ]
}

I will look into it. Please be patient. Nice problem as it challenges my knowledge.

One more thing, the order of child nodes is not fixed. If you have a model tree and you want to get the full path to one node, $graphLookup seems not to work well. How I can resolve this?

hi:
I study from doc: Across Multiple Collections
A collection airports with the following documents:
{ “_id” : 0, “airport” : “JFK”, “connects” : [ “BOS”, “ORD” ] }
{ “_id” : 1, “airport” : “BOS”, “connects” : [ “JFK”, “PWM” ] }
{ “_id” : 2, “airport” : “ORD”, “connects” : [ “JFK” ] }
{ “_id” : 3, “airport” : “PWM”, “connects” : [ “BOS”, “LHR” ] }
{ “_id” : 4, “airport” : “LHR”, “connects” : [ “PWM” ] }

A collection travelers with the following documents:
{ “_id” : 1, “name” : “Dev”, “nearestAirport” : “JFK” }
{ “_id” : 2, “name” : “Eliot”, “nearestAirport” : “JFK” }
{ “_id” : 3, “name” : “Jeff”, “nearestAirport” : “BOS” }

SQL:
db.travelers.aggregate( [
{
$graphLookup: {
from: “airports”,
startWith: “$nearestAirport”,
connectFromField: “connects”,
connectToField: “airport”,
maxDepth: 2,
depthField: “numConnections”,
as: “destinations”
}
}
] )

how to resolve endless loop?
for example:
{
“_id” : 1,
“name” : “Dev”,
“nearestAirport” : “JFK”,
“destinations” : [
{ “_id” : 3,
“airport” : “PWM”,
“connects” : [ “BOS”, “LHR” ],
“numConnections” : NumberLong(2) },
{ “_id” : 2,
“airport” : “ORD”,
“connects” : [ “JFK” ],
“numConnections” : NumberLong(1) },
{ “_id” : 1,
“airport” : “BOS”,
“connects” : [ “JFK”, “PWM” ],
“numConnections” : NumberLong(1) },
{ “_id” : 0,
“airport” : “JFK”,
“connects” : [ “BOS”, “ORD” ],
“numConnections” : NumberLong(0) }
]
}

from “nearestAirport” : “JFK” —>airport:JFK – “connects” : [ “BOS”, “ORD” ]–>“airport” : “BOS”, “connects” : [ “JFK”, “PWM” ] and “airport” : “ORD”, “connects” : [ “JFK” ].–> “airport” : “PWM”,
“connects” : [ “BOS”, “LHR” ],
so connects has JFK,why not connects to airport:JFK ?rather than ignore two JFK. just connects:PWM match next airport?

I had some time to look at that but I could not find the collection you are using in the aggregations database. Which database and which collections are you using?

If you could provide some sample documents it will be easier and faster.