I'm trying to create a mongoose query that can query either by slug or id, however the problem comes in that I don't know which one I'm going to be handling as I have this as an Express route:
app.get('/animals/dogs/:id', function (req, res, next) {
Dogs.find({$or: [{slug: id}, {_id: id}]}, function (err, docs) {
if (err) {
return next(err);
}
// ....
});
});
I'd like to have ability to search by either, however this approach above throws up an Invalid ObjectId
error.
Another approach would be to nest the queries, however this feels a bit cumbersome:
app.get('/animals/dogs/:id', function (req, res, next) {
Dogs.find({slug: id}, function (err, docs) {
if (err) {
return next(err);
}
if (!docs) {
Dogs.findById(id, function (err, docs) {
// ...
});
}
// ....
});
});
Is there a any other approach I have not considered? I know I could turn my slug into the ObjectId, but I'd rather avoid this if possible.
Test if id
is a valid ObjectId and then only include that term in the query if it's valid:
app.get('/animals/dogs/:id', function (req, res, next) {
var query = {$or: [{slug: id}]};
if (id.match(/^[0-9a-fA-F]{24}$/)) {
query.$or.push({_id: id});
}
Dogs.find(query, function (err, docs) {
if (err) {
return next(err);
}
// ....
});
});
I definitely prefer the following syntax (the use of Mongoose validator for ObjectId
):
const mongoose = require('mongoose');
const isObjectId = mongoose.ObjectId.isValid;
app.get('/animals/dogs/:id', function (req, res, next) {
const id = req.params.id;
const promise = isObjectId(id) ? Dogs.find(id) : Dogs.findOne({ slug: id });
promise.then(dog => res.send(dog)).catch(next)
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With