Automattic / Automattic/mongoose
Populating virtuals with count: true fires a 'find' query instead of 'countDocuments' query
- Dominant language
- JavaScript
- Stars
- 27.5k
- Forks
- 4k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 35
Description
**Do you want to request a *feature* or report a *bug*?**
I want to suggest an optimisation for an existing feature.
**What is the current behavior?**
Here is the script that I'm using
```js
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017', { dbName: 'test-db', useNewUrlParser: true }, function (error) {
if (error) {
console.log('Error in mongo connection', error);
} else {
console.log('Mongo connection established');
}
});
mongoose.set('debug', true);
const PersonSchema = new mongoose.Schema({
name: String,
band: String,
});
let modelPerson = mongoose.model('person', PersonSchema);
const BandSchema = new mongoose.Schema({
name: String
}, { toJSON: { virtuals: true } });
BandSchema.virtual('numMembers', {
ref: 'person',
localField: 'name',
foreignField: 'band',
count: true
});
let modelBand = mongoose.model('band', BandSchema);
let main = async () => {
await modelPerson.insertMany([{ name: 'P1', band: 'B1' }, { name: 'P2', band: 'B1' }]);
await modelBand.create({ name: 'B1' });
let band = await modelBand.findOne({ name: 'B1' }).populate('numMembers');
console.log(band.numMembers);
};
main();
```
In the findOne query for modelBand, populating 'numMembers' fires a find query on modelPerson instead of a simple countDocuments query. This is hghly inefficient considering the count can go well above 1000 in many cases. Actually fetching all those documents will reduce the response time and consume more bandwidth.
In this case, since all we really need is a count of those documents, a countDocuments query is a perfect fit here.
**What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.**
Node.js: 8.10
MongoDb: 4.0.4
Mongoose: 5.6.11
Contributor guide
Research direction
Start with the modelBand.findOne().populate('numMembers') reproduction and trace virtual population for the count: true option. Verify the current query against modelPerson, then add coverage showing that population uses countDocuments and returns the member count without fetching all matching documents.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, mongodb, nodejs
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100