Search code examples
mongodbaggregation-frameworkgraph-traversal

Problems using MongoDB's $graphLookup


I have two collections. sources:

[
  {
    "_id": "0001",
    "name": "John Doe"
  },
  {
    "_id": "0002",
    "address": "123 Some Place"
  },
  {
    "_id": "0003",
    "phone": "5555555555"
  }
]

and connections:

[
  {
    "_id": "0001.0002",
    "_from": "0001",
    "_to": "0002",
    "probability": 0.8
  },
  {
    "_id": "0002.0003",
    "_from": "0002",
    "_to": "0003",
    "probability": 0.6
  }
]

I'm attempting to do graph traversal with $graphLookup to get a list of all the sources connections. This is the code I have:

db.sources.aggregate([
    {
      $match: {
        '_id': '0001'
      }
    },
    {
      $graphLookup: {
        from: 'connections',
        startWith: '_id',
        connectFromField: '_from',
        connectToField: '_to',
        maxDepth: 2,
        depthField: 'numConnections',
        as: 'destinations'
      }
    }
])

This returns the destinations array that is empty. I would expect it to contain two records (0002 and 0003).

I'd like additionally to multiply probabilities during traversal so that 0001 -> 0002 = 0.8 and 0001 -> 0003 = 0.48 (0.8 * 0.6). I must be missing something simple here as I've tried to follow exactly how it's represented in the documentation (https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/).


Solution

  • You can try the below query.

    You will need two $graphlookup, one for connections for each sources and the other for calculating the probability for each connection.

    $unwind with $graphlookup to get all the probability for each connection.

    $reduce to $multiply all the array elements for each collection.

    $group to group source documents with respective connections and its probability.

    db.sources.aggregate([
      {
        "$match": {
          "_id": "0001"
        }
      },
      {
        "$graphLookup": {
          "from": "connections",
          "startWith": "$_id",
          "connectFromField": "_to",
          "connectToField": "_from",
          "maxDepth": 2,
          "depthField": "numConnections",
          "as": "destinations"
        }
      },
      {
        "$unwind": "$destinations"
      },
      {
        "$graphLookup": {
          "from": "connections",
          "startWith": "$destinations._to",
          "connectFromField": "_from",
          "connectToField": "_to",
          "maxDepth": 2,
          "as": "destinations.probabilities"
        }
      },
      {
        "$addFields": {
          "destinations.probabilities": {
            "$reduce": {
              "input": "$destinations.probabilities.probability",
              "initialValue": 1,
              "in": {
                "$multiply": [
                  "$$value",
                  "$$this"
                ]
              }
            }
          }
        }
      },
      {
        "$group": {
          "_id": "$_id",
          "name": {
            "$first": "$name"
          },
          "destinations": {
            "$push": "$destinations"
          }
        }
      }
    ])