Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose query 8x slower than shell

I have a collection with 200,000+ documents in that I'm filtering with a few where clauses.

Here's my query in Mongoose:

 const assets = await GpsLog
                          .where('gps_time')
                          .gte(first)
                          .lte(last)
                          .where('location')
                          .within()
                          .geometry(geoFence);

Where geofence is a GeoJSON polygon.

The shell query I'm running is:

db.gps_log.find({
  'gps_time': {
    $gte: first,
    $lte: last
  },
  'location': {
    '$geoIntersects': {
      '$geometry': {
        'type': 'Polygon',
        'coordinates': // polygon
      }
    }
  }
})

The Mongoose query completes in anywhere between 5 to 11 seconds, whereas the shell query completes in 0.5s.

I translated the shell query to execute in Mongoose as:

const res = await GpsLog.find({
  'gps_time': {
    $gte: 1539648000,
    $lte: 1539820800
  },
  'location': {
    '$geoIntersects': {
      '$geometry': geoFence
    }
  }
}).lean().exec();

But it's still taking 4+ seconds to execute.

Am I missing something with the speed difference?

like image 710
James Gould Avatar asked Feb 16 '26 04:02

James Gould


1 Answers

The Mongo shell, when you perform a query, returns a cursor and reads (at most) 20 results from it. After that, you need to exhaust the cursor (read all results) through one of various methods.

So what you're basically testing is how long it takes in the Mongo shell to return a cursor and read 20 results from it. In your case, that takes 0.5s.

However, Mongoose, by default, reads all results. So if you want to do a fair comparison between Mongoose and the shell, you should read all the results in the shell as well, for instance by using the toArray method on the cursor:

db.gps_log.find({ ... }).toArray()

Alternatively, you can ask Mongoose to return a cursor instead of reading all results immediately:

const cursor = GpsLog.find({ ... }).lean().cursor();

cursor.on('data', doc => { ... }).on('close', () => { ... });
like image 87
robertklep Avatar answered Feb 17 '26 21:02

robertklep



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!