skip to Main Content

Mongo graphLookup problem.

I want the num of degrees separation between jerry and superman, the answer should be 2.

In my bi-directional node structure, jerry is connected to lois, louis is connected to superman.

My data

{
    "from" : "jerry",
    "to" : "lois"
}
{
    "from" : "lois",
    "to" : "jerry"
}
{
    "from" : "superman",
    "to" : "lois"
}
{
    "from" : "lois",
    "to" : "superman"
}

The query below returns 4 documents with "degreeOfSeparation" : 4, this represent the bi-directional connections to superman.

db.getCollection("connections").aggregate([
    {
        $graphLookup : {
            from: "connections",
            startWith: "$from",
            connectFromField: "from",
            connectToField: "to",
            maxDepth:5,
            as: "connections"
        }
    },
    {
        $match: {
            "connections.from": "jerry",
            "connections.to": "superman"
        }
    },
    {
        $project: {
            degreeOfSeparation: { $size: "$connections" }
        }
    }

2

Answers


  1. This might works only on level of Grouped nodes

    Mongodb playground

    db.collection.aggregate([
      {
        $graphLookup: {
          from: "collection",
          startWith: "$to",
          connectFromField: "from",
          connectToField: "from",
          depthField: "connects",
          as: "connections"
        }
      },
      {
        "$match": {
          "$and": [
            {
              from: "superman"
            },
            {
              $or: [
                {
                  "connections.to": "jerry"
                },
                {
                  to: "jerry"
                }
              ]
            }
          ]
        }
      },
      {
        $project: {
          degreeOfSeparation: {
            $size: "$connections"
          }
        }
      }
    ])
    
    Login or Signup to reply.
  2. Here’s a way to get your "degreeOfSeparation" "from": "jerry" "to": "superman" and all of the degrees of separation using "$graphLookup"‘s "depthField".

    db.collection.aggregate([
      {
        "$match": {
          "from": "jerry"  // from here
        }
      },
      {
        $graphLookup: {
          from: "collection",
          startWith: "$to",
          connectFromField: "to",
          connectToField: "from",
          depthField: "depth",
          as: "connections"
        }
      },
      {
        "$set": {
          "allDegsOfSep": {
            "$map": {
              "input": {
                "$filter": {
                  "input": "$connections",
                  "as": "conn",
                  "cond": {"$eq": ["$$conn.to", "superman"]}  // to here
                }
              },
              "as": "toSuperman",
              "in": {
                "$sum": [
                  {"$toInt": "$$toSuperman.depth"},
                  // +1 zero-based, +1 "to" field
                  2
                ]
              }
            }
          }
        }
      },
      { // maybe doc has target, i.e., degOfSep = 1
        "$set": {
          "allDegsOfSep": {
            "$cond": [
              {"$eq": ["$to", "superman"]},
              {"$concatArrays": [[1], "$allDegsOfSep"]},
              "$allDegsOfSep"
            ]
          }
        }
      },
      {
        "$project": {
          "_id": 0,
          "allDegsOfSep": 1,
          "degreeOfSeparation": {"$min": "$allDegsOfSep"}
        }
      }
    ])
    

    Try it on mongoplayground.net.

    Output using extended collection:

    [
      {
        "allDegsOfSep": [5, 2],
        "degreeOfSeparation": 2
      }
    ]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search