Categories
MongoDB

Using MongoDB with Mongoose — Populate Virtuals and Count

Spread the love

To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.

In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.

Populate Virtuals: The Count Option

We can add the count option when we create a populate virtual to get the count of the number of children we retrieved.

For example, we can write:

async function run() {
  const { createConnection, Types, Schema } = require('mongoose');
  const db = createConnection('mongodb://localhost:27017/test');
  const PersonSchema = new Schema({
    name: String,
    band: String
  });

  const BandSchema = new Schema({
    name: String
  }, { toJSON: { virtuals: true } });

  BandSchema.virtual('numMembers', {
    ref: 'Person',
    localField: 'name',
    foreignField: 'band',
    count: true
  });

  const Person = db.model('Person', PersonSchema);
  const Band = db.model('Band', BandSchema);
  const person = new Person({ name: 'james', band: 'superband' });
  await person.save();
  const band = new Band({ name: 'superband' });
  await band.save();
  const doc = await Band.findOne({ name: 'superband' })
    .populate('numMembers');
  console.log(doc.numMembers);
}
run();

We created the PersonSchema and BandSchema schema objects.

We call the virtual method on the BandSchema schema with several options.

The ref property is the model that the Band model is referencing.

localField is the field in the BandSchema we want to join with PeronSchema .

foreignField is the field in the ForeignSchema we want to join with PersonSchema .

count set to true means that we get the count. numMembers is the field name that we get the count from.

Then we save a Person and Band document with the same name.

Then we call populate with the numMembers field to get the number of members.

And finally, we get the numMembers field from the retrieved result to get how many Person children entries are in the Band .

Populate in Middleware

We can add pre or post hooks to populate operations.

For example, we can write:

async function run() {
  const { createConnection, Types, Schema } = require('mongoose');
  const db = createConnection('mongodb://localhost:27017/test');
  const PersonSchema = new Schema({
    name: String,
    band: String
  });

  const BandSchema = new Schema({
    name: String
  }, { toJSON: { virtuals: true } });

  BandSchema.virtual('numMembers', {
    ref: 'Person',
    localField: 'name',
    foreignField: 'band',
    count: true
  });

  BandSchema.pre('find', function () {
   this.populate('person');
  });

  BandSchema.post('find', async (docs) => {
    for (const doc of docs) {
      await doc.populate('person').execPopulate();
    }
  });

  const Person = db.model('Person', PersonSchema);
  const Band = db.model('Band', BandSchema);
  const person = new Person({ name: 'james', band: 'superband' });
  await person.save();
  const band = new Band({ name: 'superband' });
  await band.save();
  const doc = await Band.findOne({ name: 'superband' })
    .populate('numMembers');
  console.log(doc.numMembers);
}
run();

to add the pre and post hooks to listen to the find operation.

We should always call populate with the given field to do the population.

Conclusion

We can add the count property to add the count and also add pre and post hooks for find operations with when we do the population.

Leave a Reply

Your email address will not be published. Required fields are marked *