How do I cancel a running query?

My front-end app makes requests to my Express.js app. The Express app uses the MongoDB Node.js driver to make queries to my (Atlas) MongoDB. When the front-end app cancels a request (e.g. AbortController, CancelToken) how do I make the Express endpoint kill the corresponding MongoDB query?

Relevant endpoint code:

export default async function search(req, res) {
  try {
    const payload = await collection.aggregate(pipeline).toArray()
    return res.status(200).send(payload)
  } catch ({ message, stack }) {
    return res.status(400).send({ message, stack })
  }
}

Hi @Tarun_Gaur,

I had not found a solution so am grateful for your reply.

The suggestion you describe is not automatable, if I understand it correctly. Users of my web app cancel many requests they send to my Express app. To implement your approach, I would have to manually enter commands into a Mongo shell. That won’t work for me, because I need this to happen in real time – in the Express app.

Scenario: As the user pans/zooms a map, the web app requests new data from the Express app. Users often pan/zoom multiple times per second. Some queries can take several seconds for Mongo to process. I want to cancel/abort all of the orphan Mongo queries to conserve resources.

This seems like a fairly typical use case. Is the solution really as you suggest? That is, in a separate process from the running Express app manually open a Mongo shell and run commands to search for and abort these wasteful queries?

Thank you for sharing your expertise.

Hi @Mask_Hoski

You can use the killOp command to kill an existing operation. In node, it will look something like:

    const res = await client.db('admin').command({
      killOp: 1,
      op: 1234  //operation id to kill here
    });

See Run a Command for more examples on running a command using the node driver.

However to know which operation to kill, you’ll need to know it’s operation id first :slight_smile:

You can use the $currentOp aggregation stage to do this. For example:

    const currentop = await client.db('admin').aggregate([
      {'$currentOp': {}}
    ]).toArray()
    console.log(currentop)

You probably need to wrap these two command/aggregation in separate endpoints in your app.

Hope this helps!

Best regards
Kevin

1 Like