{"id":1928,"date":"2013-08-26T07:44:10","date_gmt":"2013-08-26T12:44:10","guid":{"rendered":"http:\/\/www.wiredprairie.us\/blog\/?p=1928"},"modified":"2022-06-29T10:26:05","modified_gmt":"2022-06-29T15:26:05","slug":"mongoose-plugin-runs-for-every-new-schema","status":"publish","type":"post","link":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1928","title":{"rendered":"Mongoose plugin runs for every new Schema"},"content":{"rendered":"\n

If you want to consistently apply changes to every Schema<\/a> in Mongoose<\/a>, it\u2019s simple. Below is an example.<\/p>\n\n\n\n

var<\/span> mongoose = require('mongoose'<\/span>);\n\nvar<\/span> checkForHexRegExp = new<\/span> RegExp(\"^[0-9a-fA-F]{24}<\/span>\");\nmongoose.plugin(function<\/span>(schema, opts) { \n    schema.statics.isObjectId = function<\/span>(id) { \n        if<\/span>(id) { \n            return<\/span> checkForHexRegExp.test(id); \n        } \n        return<\/span> false<\/span>; \n    }; \n}); \nvar<\/span> AnimalSchema = mongoose.Schema({ name: String }); \nvar<\/span> Animal = mongoose.model(\"Animal\"<\/span>, AnimalSchema); if<\/span>(Animal.isObjectId(\"521b4891039857e07aae695a\"<\/span>)) { \n    var<\/span> animal = new<\/span> Animal(); \/\/ something more interesting here ...<\/span> \n}<\/pre>\n\n\n\n

The code above uses the plugin<\/strong> function on the global mongoose object to add a new plugin. When you add a plugin using that technique, it runs for every schema that is constructed.<\/p>\n\n\n\n

So, in this case, I\u2019ve added a static function to every Schema called isObjectId<\/strong> which uses a simple regular expression (liberally borrowed<\/a> straight from the bson ObjectId source code) to test whether a string looks like a valid ObjectId (in fact, a 24 character HEX string).<\/p>\n\n\n\n

Now, as new models are created (mongoose.model)<\/strong>, the Schema is first passed to any defined plugins. The plugin adds the new function isObjectId<\/strong>. As you can see, the new Model<\/strong> has a static method called isObjectId<\/strong>.<\/p>\n\n\n\n

The plugin will not affect any Schemas\/Models that were defined before the plugin was added.<\/p>\n\n\n\n

Using this technique, you could add standardized fields, indexes, etc. without repeating the same code to all Schemas. Of course, you can also use the plugin<\/strong> method defined on a Schema to selectively add functionality.<\/p>\n\n\n\n

var<\/span> isObjectIdPlugin = function<\/span>(schema, opts) {\n    schema.statics.isObjectId = function<\/span>(id) {\n        if<\/span>(id) {\n            return<\/span> checkForHexRegExp.test(id);\n        }\n        return<\/span> false<\/span>;\n    };\n};\n\n\nvar<\/span> AnimalSchema = mongoose.Schema({\n    name: String\n});\n\nAnimalSchema.plugin(isObjectIdPlugin);\n\nvar<\/span> Animal = mongoose.model(\"Animal\"<\/span>, AnimalSchema);\n\nif<\/span>(Animal.isObjectId(\"521b4891039857e07aae695a\"<\/span>)) {\n    var<\/span> animal = new<\/span> Animal();\n    \/\/ something more interesting here ...<\/span>\n}<\/pre>\n\n\n\n

<\/p>\n\n\n\n

Above, the code applies the plugin to only the AnimalSchema using the plugin<\/strong> method.<\/p>\n\n\n\n

Of course, adding the same method statically may not be very useful \u2013 instead it probably belongs somewhere in a utility class (and really it\u2019s too bad it\u2019s not just exposed directly by the BSON ObjectId class).<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"

If you want to consistently apply changes to every Schema in Mongoose, it\u2019s simple. Below is an example. var mongoose = require(‘mongoose’); var checkForHexRegExp = new RegExp(“^[0-9a-fA-F]{24}”); mongoose.plugin(function(schema, opts) { schema.statics.isObjectId = function(id) { if(id) { return checkForHexRegExp.test(id); } return false; }; }); var AnimalSchema = mongoose.Schema({ name: String }); var Animal = mongoose.model(“Animal”, AnimalSchema); […]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[4],"tags":[129,146],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pd5QIe-v6","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1820,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1820","url_meta":{"origin":1928,"position":0},"title":"Knockout binding for JavaScript route fixup","date":"January 25, 2013","format":false,"excerpt":"Part one. After the first round, I felt compelled to KnockOut the code a bit more. I\u2019d mentioned I wasn\u2019t pleased with the code exactly. It needed some refactoring. So, I\u2019ve created a new Knockout binding handler. This binding handler replaces\u00a0 named parameters with a model\u2019s properties in a path.\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1442,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1442","url_meta":{"origin":1928,"position":1},"title":"Nest Thermostat API\/Protocol","date":"January 8, 2012","format":false,"excerpt":"While Nest Labs hasn\u2019t released a formal (documented & supported) API, I thought I\u2019d do a bit of digging to see how they\u2019re using the network and what might be achievable. A few things are going on, the majority as you\u2019d probably expect. The web interface is using a long\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"image","src":"https:\/\/i0.wp.com\/www.wiredprairie.us\/blog\/wp-content\/uploads\/2012\/01\/image_thumb7.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1833,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1833","url_meta":{"origin":1928,"position":2},"title":"How to view the MongoDB Query when using the C# LINQ Provider","date":"January 26, 2013","format":false,"excerpt":"If you\u2019re using the Official MongoDB C# Driver from 10gen, you may want to occasionally verify that the generated query matches your LINQ query (or at least that it\u2019s building something efficient). Take for example this query: var query = (from r in DataLayer.Database.GetCollection().AsQueryable() where !r.Deleted select new { Id\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1835,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1835","url_meta":{"origin":1928,"position":3},"title":"How to rewrite a MongoDB C# LINQ with a Projection Requirement using a MongoCursor","date":"January 26, 2013","format":false,"excerpt":"The LINQ Provider for MongoDB does not currently take into account data projections efficiently when returning data. This could mean that you\u2019re unnecessarily returning more data from the database than is needed. So, I\u2019m going to show you the pattern I applied as a replacement for the LINQ queries when\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1345,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1345","url_meta":{"origin":1928,"position":4},"title":"Creating a simple Entity Reference system for Ember.js","date":"December 28, 2011","format":false,"excerpt":"I had some data stored in a structure similar to this: Nothing too fancy. A table of Gift(s) and a table of Person(s). Each gift had a foreign key relationship to a Person (the person who \u201cgave\u201d the gift). Since some people may give several gifts, I didn\u2019t want to\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1895,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1895","url_meta":{"origin":1928,"position":5},"title":"Using $inc to increment a field in a sub-document in an array and a field in main document","date":"July 14, 2013","format":false,"excerpt":"(Blog post inspired by question I answered on StackOverflow) Lets say you have a schema in MongoDB that looks something like this: { '_id' : 'star_wars', 'count' : 1234, 'spellings' : [ { spelling: 'Star wars', total: 10}, { spelling: 'Star Wars', total : 15}, { spelling: 'sTaR WaRs', total\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1928"}],"collection":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/comments?post=1928"}],"version-history":[{"count":6,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1928\/revisions"}],"predecessor-version":[{"id":2386,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1928\/revisions\/2386"}],"wp:attachment":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/media?parent=1928"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/categories?post=1928"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/tags?post=1928"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}