I am attaching a pre find
middleware to Schema.
Inside the handler I want to check whether the given query set has a strict property (say 'companyId'), if the query misses that property then I would call next
callback with error object.
It would be great if I can access the plain query object which I pass during find
function call.
Example:
Item Schema:
var ItemSchema = mongoose.Schema({
name: { type: String, },
companyId: { type :mongoose.Schema.Types.ObjectId, ref: 'Company', required: true, },
});
ItemSchema.pre('find', function () {
if (this.queryHas('companyId')) { // Something like this
next();
} else {
next(new Error('query misses companyId.'))
}
});
Item.find({ name: 'car' }).then(function (err, itemDocs) {
if (err) {
console.error('Failed to query items. Error:', err);
} else {
console.error('Items:', itemDocs);
}
});
Expected Output:
Failed to query items: Error: [query misses companyId.]
So when I query item collection without companyId
the middleware should throw me an error like the above example.
How do I achieve the above?
Inside query middleware, the context is the Query
. Each query has a getQuery()
method: http://mongoosejs.com/docs/api.html#query_Query-getQuery
so inside the hook if you call this.getQuery()
, you'll get all the fields passed in in the query.
Thanks @varunjayaraman.
I read through lib/query.js
file and came to know about getQuery
method. It serves my purpose. 馃憤
I am facing a different problem now.
Problem: pre find
hooks are invoked for populate
queries as well.
Example:
// Item Schema
var ItemSchema = mongoose.Schema({
name: { type: String, },
companyId: { type :mongoose.Schema.Types.ObjectId, ref: 'Company', required: true, },
category: { type :mongoose.Schema.Types.ObjectId, ref: 'Category', required: true, },
});
ItemSchema.pre('find', function () {
if (this.getQuery().companyId) {
next();
} else {
next(new Error('Item query misses companyId.'))
}
});
ItemModel = mongoose.model('Item', ItemSchema);
// Category Schema
var CategorySchema = mongoose.Schema({
name: { type: String, },
companyId: { type :mongoose.Schema.Types.ObjectId, ref: 'Company', required: true, },
});
CategorySchema.pre('find', function () {
if (this.getQuery().companyId) {
next();
} else {
next(new Error('Category query misses companyId.'))
}
});
CategoryModel = mongoose.model('Category', CategorySchema);
ItemModel.find({
name: 'car',
companyId: '58914ea17beda294fae143dd'
})
.populate('category') // <-- NOTE
.exec(function (err, itemDocs) {
if (err) {
console.error('Failed to query items. Error:', err);
} else {
console.error('Items:', itemDocs);
}
});
Output:
Failed to query items. Error: [Category query misses companyId.]
From the output you can see that populate query hits pre find
hook of Category Schema and checks for companyId
.
Inside pre find
hook, is there a way to differentiate whether the query is a populate query or normal query?
So that if its a populate query I can bypass companyId
check.
I have the same problem as @Sundarasan has, how to check whether the query is a populate query or normal query. This issue is closed, but there's no answer to the question?
@bojanbass @Sundarasan You'll need to use getPopulatedPaths: https://mongoosejs.com/docs/api.html#query_Query-getPopulatedPaths
Most helpful comment
Inside query middleware, the context is the
Query
. Each query has agetQuery()
method: http://mongoosejs.com/docs/api.html#query_Query-getQueryso inside the hook if you call
this.getQuery()
, you'll get all the fields passed in in the query.