James Gould
James Gould

Reputation: 4702

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?

Upvotes: 3

Views: 1011

Answers (1)

robertklep
robertklep

Reputation: 203359

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', () => { ... });

Upvotes: 2

Related Questions