Home > database >  Trying to write a recursive asynchronous search in JavaScript
Trying to write a recursive asynchronous search in JavaScript

Time:11-17

I am trying to write some code that searches through a bunch of objects in a MongoDB database. I want to pull the objects from the database by ID, then those objects have ID references. The program should be searching for a specific ID through this process, first getting object from id, then ids from the object.

async function objectFinder(ID1, ID2, depth, previousList = []) {
    let route = []
    if (ID1 == ID2) {
        return [ID2]
    } else {
        previousList.push(ID1)
        let obj1 = await findObjectByID(ID1)
        let connectedID = obj1.connections.concat(obj1.inclusions) //creates array of both references to object and references from object
        let mapPromises = connectedID.map(async (id) => {
            return findID(id) //async function
        })
        let fulfilled = await Promise.allSettled(mapPromises)
        let list = fulfilled.map((object) => {
            return object.value.main, object.value.included
        })
        list = list.filter(id => !previousList.includes(id))
        for (id of list) {
            await objectFinder(id, ID2, depth - 1, previousList).then(result => {
                route = [ID1].concat(result)
                if (route[route.length - 1] == ID2) {
                    return route
                }})
        }
    }
    if (route[route.length - 1] == ID2) {
        return route
    }
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

I am not sure how to make it so that my code works like a tree search, with each object and ID being a node.

CodePudding user response:

I didn't look too much into your code as I strongly believe in letting your database do the work for you if possible.

In this case Mongo has the $graphLookup aggregation stage, which allows recursive lookups. here is a quick example on how to use it:

db.collection.aggregate([
  {
    $match: {
      _id: 1,
      
    }
  },
  {
    "$graphLookup": {
      "from": "collection",
      "startWith": "$inclusions",
      "connectFromField": "inclusions",
      "connectToField": "_id",
      "as": "matches",
      
    }
  },
  {
    //the rest of the pipeline is just to restore the original structure you don't need this
    $addFields: {
      matches: {
        "$concatArrays": [
          [
            {
              _id: "$_id",
              inclusions: "$inclusions"
            }
          ],
          "$matches"
        ]
      }
    }
  },
  {
    $unwind: "$matches"
  },
  {
    "$replaceRoot": {
      "newRoot": "$matches"
    }
  }
])

Mongo Playground

If for whatever reason you want to keep this in code then I would take a look at your for loop:

for (id of list) {
    await objectFinder(id, ID2, depth - 1, previousList).then(result => {
        route = [ID1].concat(result);
        if (route[route.length - 1] == ID2) {
            return route;
        }
    });
}

Just from a quick glance I can tell you're executing this:

route = [ID1].concat(result);

Many times at the same level. Additional I could not understand your bottom return statements, I feel like there might be an issue there.

  • Related