So what I want to do is make findOne
work more like it does in Meteor, but through the Mongo shell. In short I want to be able to do something like this db.collection.findOne("thisIsAnId")
and have it lookup that id in that collection.
I tried loading a file that has this in it...
db.collection.findOne = function(query, fields, options){
if(typeof query === "string") {
return db.collection.originalFindOne({_id : query}, fields, options);
}
return db.collection.originalFindOne(query, fields, options);
}
Where originalFindOne
would just chain to the default findOne
, this didn't work at all. So after having no luck finding a way to override a default function I thought maybe I could create a new function like db.collection.simpleFindOne()
or something, but I can't find a way to attach it to the mongo shell so that it will be available to any collection.
Anyone have some insight on how mongo internals work that could give me some help?
Try adding this snippet to one of your Mongo config files:
(function() {
// Duck-punch Mongo's `findOne` to work like Meteor's `findOne`
if (
typeof DBCollection !== "undefined" && DBCollection &&
DBCollection.prototype && typeof DBCollection.prototype.findOne === "function" &&
typeof ObjectId !== "undefined" && ObjectId
) {
var _findOne = DBCollection.prototype.findOne,
_slice = Array.prototype.slice;
DBCollection.prototype.findOne = function() {
var args = _slice.call(arguments);
if (args.length > 0 && (typeof args[0] === "string" || args[0] instanceof ObjectId)) {
args[0] = { _id: args[0] };
}
return _findOne.apply(this, args);
};
}
})();
I originally found the DBCollection
object/class by typing db.myCollection.constructor
into the Mongo shell. I then confirmed that findOne
was defined on its prototype by verifying that (a) DBCollection
was globally accessible, (b) that DBCollection.prototype
existed, and (c) that typeof DBCollection.prototype.findOne === "function"
(much like the snippet does).
Edit: Added a logic branch to also cover ObjectId-based IDs.