Mongoose: Mongoose dynamic pre find

Created on 1 Apr 2020  路  1Comment  路  Source: Automattic/mongoose

This is not an issue it simply is a question , can I use pre hooks to query my database before any find query but with dynamic input? For example take the query input from the request

help

Most helpful comment

Welcome @mohamadelhinamy

Yes, you can do that, take the code below for example where you find documents with the filter used for a findOne operation, and increment their searchCount

// 8756
const mongoose = require('mongoose');
const { Schema } = mongoose;
const assert = require('assert');

mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true });

const userSchema = new Schema({
  name: { type: String },
  searchCount: { type: Number, default: 0 }
});

userSchema.pre('findOne', incrementSearchCount);

const User = mongoose.model('User', userSchema);

async function run () {
  await User.deleteMany();

  const userBeforeSearch = await User.create({ name: 'Hafez' });

  const user = await User.findOne({ name: 'Hafez' });

  assert.equal(user.searchCount, userBeforeSearch.searchCount + 1);

  console.log('Done.');
}


async function incrementSearchCount (next) {
  const options = this.getOptions();

  // in order to avoid an infinite loop, pass { skipMiddleware: true }
  // in the findOne operations that happen inside the middleware
  const { skipMiddleware } = options;
  if (skipMiddleware) return next();

  const Model = this.model;
  const filter = this.getFilter();

  const document = await Model.findOne(filter, null, { skipMiddleware: true });

  document.searchCount++;

  await document.save();

  next();
}

run().catch(console.error);

Does that answer your question?

>All comments

Welcome @mohamadelhinamy

Yes, you can do that, take the code below for example where you find documents with the filter used for a findOne operation, and increment their searchCount

// 8756
const mongoose = require('mongoose');
const { Schema } = mongoose;
const assert = require('assert');

mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true });

const userSchema = new Schema({
  name: { type: String },
  searchCount: { type: Number, default: 0 }
});

userSchema.pre('findOne', incrementSearchCount);

const User = mongoose.model('User', userSchema);

async function run () {
  await User.deleteMany();

  const userBeforeSearch = await User.create({ name: 'Hafez' });

  const user = await User.findOne({ name: 'Hafez' });

  assert.equal(user.searchCount, userBeforeSearch.searchCount + 1);

  console.log('Done.');
}


async function incrementSearchCount (next) {
  const options = this.getOptions();

  // in order to avoid an infinite loop, pass { skipMiddleware: true }
  // in the findOne operations that happen inside the middleware
  const { skipMiddleware } = options;
  if (skipMiddleware) return next();

  const Model = this.model;
  const filter = this.getFilter();

  const document = await Model.findOne(filter, null, { skipMiddleware: true });

  document.searchCount++;

  await document.save();

  next();
}

run().catch(console.error);

Does that answer your question?

Was this page helpful?
0 / 5 - 0 ratings