Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

docs; add 2.8.x

  • Loading branch information...
commit 40eced0594351ca239e845bdd3bd595925502051 1 parent c659395
Aaron Heckmann aheckmann authored
Showing with 14,232 additions and 0 deletions.
  1. +6 −0 docs/2.8.x/announcement.html
  2. +6,613 −0 docs/2.8.x/docs/api.html
  3. +255 −0 docs/2.8.x/docs/defaults.html
  4. +306 −0 docs/2.8.x/docs/embedded-documents.html
  5. +283 −0 docs/2.8.x/docs/errors.html
  6. +339 −0 docs/2.8.x/docs/finding-documents.html
  7. +284 −0 docs/2.8.x/docs/getters-setters.html
  8. +276 −0 docs/2.8.x/docs/indexes.html
  9. +284 −0 docs/2.8.x/docs/methods-statics.html
  10. +290 −0 docs/2.8.x/docs/middleware.html
  11. +364 −0 docs/2.8.x/docs/migration-1x-2x.html
  12. +371 −0 docs/2.8.x/docs/model-definition.html
  13. +265 −0 docs/2.8.x/docs/plugins.html
  14. +386 −0 docs/2.8.x/docs/populate.html
  15. +912 −0 docs/2.8.x/docs/query.html
  16. +347 −0 docs/2.8.x/docs/querystream.html
  17. +290 −0 docs/2.8.x/docs/schema-options.html
  18. +480 −0 docs/2.8.x/docs/schematypes.html
  19. +2 −0  docs/2.8.x/docs/style/foot.html
  20. +28 −0 docs/2.8.x/docs/style/head.html
  21. +99 −0 docs/2.8.x/docs/style/style.css
  22. +278 −0 docs/2.8.x/docs/updating-documents.html
  23. +320 −0 docs/2.8.x/docs/validation.html
  24. +327 −0 docs/2.8.x/docs/virtuals.html
  25. BIN  docs/2.8.x/images/bg.png
  26. BIN  docs/2.8.x/images/groups.png
  27. BIN  docs/2.8.x/images/logo.png
  28. BIN  docs/2.8.x/images/pattern.png
  29. +592 −0 docs/2.8.x/index.html
  30. +234 −0 docs/2.8.x/template.html
  31. +1 −0  docs/releases
6 docs/2.8.x/announcement.html
View
@@ -0,0 +1,6 @@
+<h1>Mongoose 2.7.0</h1>
+<div id="announce"><strong>06-18-2012: Mongoose 2.7 is out</strong> which is a big
+ step towards the upcoming 3.0 release. The only change is the
+ deprecation of many methods.
+ Check out the <a href="https://groups.google.com/d/topic/mongoose-orm/syKlN2xL1EE/discussion">release notes</a> for details.
+</div>
6,613 docs/2.8.x/docs/api.html
View
6,613 additions, 0 deletions not shown
255 docs/2.8.x/docs/defaults.html
View
@@ -0,0 +1,255 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Defaults</h1>
+
+<p>Each <code>SchemaType</code> that you define (you can read more about them in the <a href="model-definition.html">model definition chapter</a> ) can have a default value.</p>
+
+<p>Default values are applied when the document skeleton is constructed. This means that if you create a new document (<code>new MyModel</code>) or if you find an existing document (<code>MyModel.findById</code>), both will have defaults provided that a certain key is missing.</p>
+
+<h2>Definition</h2>
+
+<p>You can define a default with a function:</p>
+
+<pre><code>new Schema({
+ date: { type: Date, default: Date.now }
+})
+</code></pre>
+
+<p>or a value:</p>
+
+<pre><code>new Schema({
+ date: { type: Date, default: '12/10/1990' }
+})
+</code></pre>
+
+<p>Notice that defaults are automatically casted. In both cases, the defaults will become actual <code>Date</code> objects, but we're passing a timestamp first, and a string date second.</p>
+ </div>
+
+ <div id="footer">
+
+ <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
+ <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
+ <span id="google-members-count">&nbsp;</span>
+ <div id="google-subscribe-input">
+ Email: <input type="text" name="email" id="google-subscribe-email">
+ <input type="submit" name="go" value="Subscribe">
+ </div>
+ </form>
+
+ <div>
+ Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
+ Released under the MIT license.<br>
+ Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
306 docs/2.8.x/docs/embedded-documents.html
View
@@ -0,0 +1,306 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Embedded Documents</h1>
+
+<p>Embedded documents are documents with schemas of their own that are part of other documents (as items within an array).</p>
+
+<p>Embedded documents enjoy all the same features as your models. Defaults, validators, middleware. Whenever an error occurs, it's bubbled to the <code>save()</code> error callback, so error handling is a snap!</p>
+
+<p>Mongoose interacts with your embedded documents in arrays <em>atomically</em>, out of the box.</p>
+
+<h2>Definition and initialization</h2>
+
+<p>When you define a Schema like this:</p>
+
+<pre><code>var Comments = new Schema({
+ title : String
+ , body : String
+ , date : Date
+});
+
+var BlogPost = new Schema({
+ author : ObjectId
+ , title : String
+ , body : String
+ , date : Date
+ , comments : [Comments]
+ , meta : {
+ votes : Number
+ , favs : Number
+ }
+});
+
+mongoose.model('BlogPost', BlogPost);
+</code></pre>
+
+<p>The <code>comments</code> key of your <code>BlogPost</code> documents will then be an instance of <code>DocumentArray</code>. This is a special subclassed <code>Array</code> that can deal with casting, and has special methods to work with embedded documents.</p>
+
+<h2>Adding an embedded document to an array</h2>
+
+<pre><code>// retrieve my model
+var BlogPost = mongoose.model('BlogPost');
+
+// create a blog post
+var post = new BlogPost();
+
+// create a comment
+post.comments.push({ title: 'My comment' });
+
+post.save(function (err) {
+ if (!err) console.log('Success!');
+});
+</code></pre>
+
+<h2>Removing an embedded document</h2>
+
+<pre><code>BlogPost.findById(myId, function (err, post) {
+ if (!err) {
+ post.comments[0].remove();
+ post.save(function (err) {
+ // do something
+ });
+ }
+});
+</code></pre>
+
+<h2>Finding an embedded document by id</h2>
+
+<p><code>DocumentArray</code>s have an special method <code>id</code> that filters your embedded documents by their <code>_id</code> property (each embedded document gets one):</p>
+
+<p>Consider the following snippet:</p>
+
+<pre><code>post.comments.id(my_id).remove();
+post.save(function (err) {
+ // embedded comment with id `my_id` removed!
+});
+</code></pre>
+ </div>
+
+ <div id="footer">
+
+ <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
+ <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
+ <span id="google-members-count">&nbsp;</span>
+ <div id="google-subscribe-input">
+ Email: <input type="text" name="email" id="google-subscribe-email">
+ <input type="submit" name="go" value="Subscribe">
+ </div>
+ </form>
+
+ <div>
+ Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
+ Released under the MIT license.<br>
+ Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
283 docs/2.8.x/docs/errors.html
View
@@ -0,0 +1,283 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Error handling</h1>
+
+<p>Errors returned after failed validation contain an <code>errors</code> object holding the actual ValidatorErrors. Each ValidatorError has a <code>type</code> and <code>path</code> property providing us with a little more error handling flexibility.</p>
+
+<pre><code>var ToySchema = new Schema({
+ color: String
+ , name: String
+});
+
+var Toy = db.model('Toy', ToySchema);
+
+Toy.schema.path('color').validate(function (value) {
+ return /blue|green|white|red|orange|periwinkel/i.test(value);
+}, 'Invalid color');
+
+var toy = new Toy({ color: 'grease'});
+
+toy.save(function (err) {
+ // previous behavior (v1x):
+
+ console.log(err.errors.color)
+ // prints 'Validator "Invalid color" failed for path color'
+
+ // new v2x behavior - err.errors.color is a ValidatorError object
+
+ console.log(err.errors.color.message)
+ // prints 'Validator "Invalid color" failed for path color'
+
+ // you can get v1 behavior back by casting error.color toString
+
+ console.log(String(err.errors.color))
+ // prints 'Validator "Invalid color" failed for path color'
+
+ console.log(err.errors.color.type);
+ // prints "Invalid color"
+
+ console.log(err.errors.color.path)
+ // prints "color"
+
+ console.log(err.name)
+ // prints "ValidationError"
+
+ console.log(err.message)
+ // prints "Validation failed"
+});
+</code></pre>
+
+<p>BTW, the <code>err.errors</code> object is also available on the model instance.</p>
+
+<pre><code>toy.errors.color.message === err.errors.color.message
+</code></pre>
+ </div>
+
+ <div id="footer">
+
+ <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
+ <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
+ <span id="google-members-count">&nbsp;</span>
+ <div id="google-subscribe-input">
+ Email: <input type="text" name="email" id="google-subscribe-email">
+ <input type="submit" name="go" value="Subscribe">
+ </div>
+ </form>
+
+ <div>
+ Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
+ Released under the MIT license.<br>
+ Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
339 docs/2.8.x/docs/finding-documents.html
View
@@ -0,0 +1,339 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Finding documents</h1>
+
+<p>Documents can be retrieved through <code>find</code>, <code>findOne</code> and <code>findById</code>. These<br />methods are executed on your <code>Model</code>s.</p>
+
+<h2>Model.find</h2>
+
+<pre><code>Model.find(query, fields, options, callback)
+
+// fields and options can be omitted
+</code></pre>
+
+<h3>Simple query:</h3>
+
+<pre><code>Model.find({ 'some.value': 5 }, function (err, docs) {
+ // docs is an array
+});
+</code></pre>
+
+<h3>Retrieving only certain fields</h3>
+
+<pre><code>Model.find({}, 'first last', function (err, docs) {
+ // docs is an array of partially-`init`d documents
+ // defaults are still applied and will be "populated"
+})
+</code></pre>
+
+<h2>Model.findOne</h2>
+
+<p>Same as <code>Model#find</code>, but only receives a single document as second parameter:</p>
+
+<pre><code>Model.findOne({ age: 5}, function (err, doc){
+ // doc is a Document
+});
+</code></pre>
+
+<h2>Model.findById</h2>
+
+<p>Same as <code>findOne</code>, but receives a value to search a document by their <code>_id</code><br />key. This value is subject to casting, so it can be a hex string or a proper ObjectId.</p>
+
+<pre><code>Model.findById(obj._id, function (err, doc){
+ // doc is a Document
+});
+</code></pre>
+
+<h2>Model.count</h2>
+
+<p>Counts the number of documents matching <code>conditions</code>.</p>
+
+<pre><code>Model.count(conditions, callback);
+</code></pre>
+
+<h2>Model.remove</h2>
+
+<p>Removes documents matching <code>conditions</code>.</p>
+
+<pre><code>Model.remove(conditions, callback);
+</code></pre>
+
+<h2>Model.distinct</h2>
+
+<p>Finds distinct values of <code>field</code> for documents matching <code>conditions</code>.</p>
+
+<pre><code>Model.distinct(field, conditions, callback);
+</code></pre>
+
+<h2>Model.where</h2>
+
+<p>Creates a <a href="query.html">Query</a> for this model. Handy when expressing complex directives.</p>
+
+<pre><code>Model
+.where('age').gte(25)
+.where('tags').in(['movie', 'music', 'art'])
+.select('name', 'age', 'tags')
+.skip(20)
+.limit(10)
+.asc('age')
+.slaveOk()
+.hint({ age: 1, name: 1 })
+.exec(callback);
+</code></pre>
+
+<h2>Model.$where</h2>
+
+<p>Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via find({$where: javascript}), or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.</p>
+
+<pre><code>Model.$where('this.firstname === this.lastname').exec(callback)
+</code></pre>
+
+<h2>Model.update</h2>
+
+<p>See the <a href="updating-documents.html">updating docs</a> page.</p>
+
+<h2>Query API</h2>
+
+<p>Each of these methods returns a <a href="query.html">Query</a>. If you don't pass a callback to these methods, the Query can be continued to be modified (such as adding options, fields, etc), before it's <code>exec</code>d.</p>
+
+<pre><code>var query = Model.find({});
+
+query.where('field', 5);
+query.limit(5);
+query.skip(100);
+
+query.exec(function (err, docs) {
+ // called when the `query.complete` or `query.error` are called
+ // internally
+});
+</code></pre>
+ </div>
+
+ <div id="footer">
+
+ <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
+ <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
+ <span id="google-members-count">&nbsp;</span>
+ <div id="google-subscribe-input">
+ Email: <input type="text" name="email" id="google-subscribe-email">
+ <input type="submit" name="go" value="Subscribe">
+ </div>
+ </form>
+
+ <div>
+ Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
+ Released under the MIT license.<br>
+ Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
284 docs/2.8.x/docs/getters-setters.html
View
@@ -0,0 +1,284 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Getters and Setters</h1>
+
+<p>Getters and setters help you change how you get and set the attributes defined by the keys and values in the underlying raw document.</p>
+
+<h2>Setters</h2>
+
+<p>Setters allow you to transform the mongoose document's data before it gets to the raw mongodb document and is set as a value on an actual key.</p>
+
+<p>Suppose you are implementing user registration for a website. User provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, <a href='mailto:avenue@q.com'>avenue@q.com</a> can be registered for 2 accounts via <a href='mailto:avenue@q.com'>avenue@q.com</a> and <a href='mailto:AvEnUe@Q.CoM'>AvEnUe@Q.CoM</a>.</p>
+
+<p>You can set up email lower case normalization easily via a Mongoose setter. Note in the following snippet that setters (and also getters) are defined in the <code>Schema</code>:</p>
+
+<pre><code>function toLower (v) {
+ return v.toLowerCase();
+}
+
+var UserSchema = new Schema({
+ email: { type: String, set: toLower }
+});
+
+var User = mongoose.model('User', UserSchema);
+var user = new User({email: '<a href='mailto:AVENUE@Q.COM'>AVENUE@Q.COM</a>'});
+
+console.log(user.email); // '<a href='mailto:avenue@q.com'>avenue@q.com</a>'
+</code></pre>
+
+<p>As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.</p>
+
+<h2>Getters</h2>
+
+<p>Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.</p>
+
+<p>Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way (again, notice that getters are defined in the <code>Schema</code>):</p>
+
+<pre><code>function obfuscate (cc) {
+ return '****-****-****-' + cc.slice(cc.length-4, cc.length);
+}
+
+var AccountSchema = new Schema({
+ creditCardNumber: { type: String, get: obfuscate }
+});
+
+var Account = mongoose.model('Account', AccountSchema);
+
+Account.findById( someId, function (err, found) {
+ console.log(found.creditCardNumber); // '****-****-****-1234'
+});
+</code></pre>
+
+<h2>Summary</h2>
+
+<p>Setters are intended to modify the underlying raw data. Getters are intended to transform (but not modify at the raw data level) the underlying raw data into something that the user expects to see. They are both defined in the <code>Schema</code> definition.</p>
+ </div>
+
+ <div id="footer">
+
+ <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
+ <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
+ <span id="google-members-count">&nbsp;</span>
+ <div id="google-subscribe-input">
+ Email: <input type="text" name="email" id="google-subscribe-email">
+ <input type="submit" name="go" value="Subscribe">
+ </div>
+ </form>
+
+ <div>
+ Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
+ Released under the MIT license.<br>
+ Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
276 docs/2.8.x/docs/indexes.html
View
@@ -0,0 +1,276 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Indexes</h1>
+
+<p>Indexes are defined through <code>ensureIndex</code> every time a model is compiled for a certain connection / database. This means that indexes will only be ensured once during the lifetime of your app.</p>
+
+<h2>Definition</h2>
+
+<p>Regular indexes:</p>
+
+<pre><code>var User = new Schema({
+ name: { type: String, index: true }
+})
+</code></pre>
+
+<p><a href="http://www.mongodb.org/display/DOCS/Indexes#Indexes-SparseIndexes">Sparse</a> indexes:</p>
+
+<pre><code>var User = new Schema({
+ name: { type: String, sparse: true }
+})
+</code></pre>
+
+<p>Unique indexes:</p>
+
+<pre><code>var User = new Schema({
+ name: { type: String, unique: true }
+})
+
+// or
+
+var User = new Schema({
+ name: { type: String, index: { unique: true } }
+})
+</code></pre>
+
+<p>Unique sparse indexes:</p>
+
+<pre><code>var User = new Schema({
+ name: { type: String, unique: true, sparse: true }
+})
+</code></pre>
+
+<p>Compound indexes are defined on the <code>Schema</code> itself.</p>
+
+<pre><code>User.index({ first: 1, last: -1 }, { unique: true })
+</code></pre>
+ </div>
+
+ <div id="footer">
+
+ <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
+ <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
+ <span id="google-members-count">&nbsp;</span>
+ <div id="google-subscribe-input">
+ Email: <input type="text" name="email" id="google-subscribe-email">
+ <input type="submit" name="go" value="Subscribe">
+ </div>
+ </form>
+
+ <div>
+ Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
+ Released under the MIT license.<br>
+ Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
284 docs/2.8.x/docs/methods-statics.html
View
@@ -0,0 +1,284 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Methods and Statics</h1>
+
+<p>Each <code>Schema</code> can define instance and static methods for its model.</p>
+
+<h2>Methods</h2>
+
+<p>Methods are easy to define:</p>
+
+<pre><code>var AnimalSchema = new Schema({
+ name: String
+ , type: String
+});
+
+AnimalSchema.methods.findSimilarType = function findSimilarType (cb) {
+ return this.model('Animal').find({ type: this.type }, cb);
+};
+</code></pre>
+
+<p>Now when we have an instance of <code>Animal</code> we can call our <code>findSimilarType</code> method and find all animals with a matching <code>type</code>.</p>
+
+<pre><code>var Animal = mongoose.model('Animal', AnimalSchema);
+var dog = new Animal({ name: 'Rover', type: 'dog' });
+
+dog.findSimilarType(function (err, dogs) {
+ if (err) return ...
+ dogs.forEach(..);
+})
+</code></pre>
+
+<p>Note that we return what <code>.find()</code> returns in our method. The advantages are two-fold. First, by passing <code>cb</code> into <code>find</code> we are making it optional b/c <code>find</code> called without a callback will not run the query. Secondly, <code>this.find</code>, <code>this.where</code>, and other Model methods return instances of <a href="finding-documents.html">Query</a> which allow us to further utilize its expressive capabilities.</p>
+
+<pre><code>dog
+.findSimilarType()
+.where('name': /rover/i)
+.limit(20)
+.exec(function (err, rovers) {
+ if (err) ...
+})
+</code></pre>
+
+<h2>Statics</h2>
+
+<p>Statics are pretty much the same as methods but allow for defining functions that exist directly on your Model.</p>
+
+<pre><code>AnimalSchema.statics.search = function search (name, cb) {
+ return this.where('name', new RegExp(name, 'i')).exec(cb);
+}
+
+Animal.search('Rover', function (err) {
+ if (err) ...
+})
+</code></pre>
+ </div>
+
+ <div id="footer">
+
+ <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
+ <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
+ <span id="google-members-count">&nbsp;</span>
+ <div id="google-subscribe-input">
+ Email: <input type="text" name="email" id="google-subscribe-email">
+ <input type="submit" name="go" value="Subscribe">
+ </div>
+ </form>
+
+ <div>
+ Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
+ Released under the MIT license.<br>
+ Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
290 docs/2.8.x/docs/middleware.html
View
@@ -0,0 +1,290 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Mongoose ODM</title>
+ <style>
+ body {
+ background: url('/docs/2.7.x/images/bg.png');
+ padding: 0 30px 30px;
+ margin-top: 0;
+ }
+
+ #wrap {
+ background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
+ min-height: 600px;
+ padding-top: 30px;
+ }
+
+ #page {
+ width: 650px;
+ margin: auto;
+ position: relative;
+ }
+
+ #footer {
+ font: 13px Helvetica;
+ padding-top: 15px;
+ border-top: 1px solid #000;
+ color: #666;
+ margin-top: 25px;
+ }
+
+ #footer > div {
+ padding-top: 8px;
+ float: right;
+ text-align: right;
+ padding-bottom: 20px;
+ }
+
+ #content {
+ color: #111;
+ font: 15px Courier;
+ }
+
+ #content h1, #content h2, #content h3 {
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ #announce {
+ background: #2A758A;
+ border: 10px solid black;
+ border-radius: 7px;
+ padding: 30px;
+ font-size: 125%;
+ color: white;
+ text-shadow: none;
+ font-family: Arial;
+ }
+
+ #announce a {
+ color: orange;
+ text-shadow: none;
+ }
+
+ pre {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ padding: 10px;
+ border-radius: 3px;
+ box-shadow: 1px 3px 6px #ddd;
+ }
+
+ code {
+ background: rgba(255,255,255,.8);
+ border: 1px solid #c6c6c6;
+ color: #333;
+ border-radius: 3px
+ }
+
+ pre code {
+ border: 0 none;
+ }
+
+ form {
+ font: bold 12px Helvetica;
+ text-shadow: 0 1px 0 #fff;
+ float: left;
+ padding-bottom: 25px;
+ }
+
+ form img {
+ margin-right: 5px
+ }
+
+ #google-members-count {
+ vertical-align: top;
+ line-height: 32px;
+ }
+
+ h1 a {
+ background: url('/docs/2.7.x/images/logo.png');
+ width: 404px;
+ height: 47px;
+ margin-bottom: 40px;
+ text-indent: -500em;
+ display: block;
+ }
+
+ a {
+ color: #2a758a;
+ text-shadow: 0 1px 0 #fff;
+ text-decoration: none;
+ }
+
+ a:hover {
+ opacity: 0.8;
+ }
+
+ #menu {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background-color: rgba(0,0,0,0.3);
+ font: bold 15px Helvetica;
+ border-right: 1px solid rgba(0,0,0,0.2);
+ }
+
+ #menu ul {
+ margin: 0;
+ padding: 50px 0;
+ }
+
+ #menu ul li {
+ list-style-type: none;
+ padding-left: 15px;
+ padding-right: 20px;
+ }
+
+ #menu ul li a {
+ color: #fff;
+ text-shadow: none;
+ }
+ #menu ul li a:hover {
+ text-decoration: underline;
+ }
+ #wild { margin-top: 10px; }
+ </style>
+
+ <script>
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-1122274-9']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+ function getMembers(data){
+ if (!(data && data.query && data.query.results && data.query.results.p)) return;
+ var members = document.createElement('span');
+ members.id = 'google-members-count';
+ members.innerHTML = '('+ data.query.results.p +' members)';
+ document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
+ };
+
+ window.onload = function(){
+ // lame jsonp
+ var script = document.createElement('script');
+ script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
+ document.head.appendChild(script);
+ };
+ </script>
+ </head>
+ <body>
+ <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
+ <div id="wrap">
+ <div id="page">
+ <div id="menu">
+ <ul>
+ <li><a href="../index.html">Home</a></li>
+ <li><a href="model-definition.html">Models/Schemas</a></li>
+ <li><a href="schematypes.html">Schema Types</a></li>
+ <li><a href="schema-options.html">Schema Options</a></li>
+ <li><a href="middleware.html">Middleware</a></li>
+ <li><a href="finding-documents.html">Finding Docs</a></li>
+ <li><a href="updating-documents.html">Updating Docs</a></li>
+ <li><a href="query.html">Queries</a></li>
+ <li><a href="querystream.html">Query Streams</a></li>
+ <li><a href="methods-statics.html">Methods &amp; Statics</a>
+ <li><a href="defaults.html">Defaults</a></li>
+ <li><a href="indexes.html">Indexes</a></li>
+ <li><a href="validation.html">Validation</a></li>
+ <li><a href="virtuals.html">Virtuals</a></li>
+ <li><a href="getters-setters.html">Getters / Setters</a></li>
+ <li><a href="embedded-documents.html">Embedded Docs</a></li>
+ <li><a href="populate.html">Populate (DBRef-like)</a></li>
+ <li><a href="plugins.html">Plugins</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
+ <li><a href="api.html">API</a></li>
+ </ul>
+ </div>
+
+ <h1><a href="../index.html">Mongoose</a></h1>
+
+ <div id="content">
+ <!-- ANNOUNCE -->
+ <h1>Middleware</h1>
+
+<p>Middleware are defined at the Schema level and are applied when the methods <code>init</code> (when a document is initialized with data from MongoDB), <code>save</code>, and <code>remove</code> are called on a document instance.</p>
+
+<p>There are two types of middleware, serial and parallel.</p>
+
+<p>Serial middleware are defined like:</p>
+
+<pre><code>schema.pre('save', function (next) {
+ // ...
+})
+</code></pre>
+
+<p>They're executed one after the other, when each middleware calls <code>next</code>.</p>
+
+<p>Parallel middleware offer more fine-grained flow control, and are defined like</p>
+
+<pre><code>schema.pre('remove', true, function (next, done) {
+ // ...
+})
+</code></pre>
+
+<p>Parallel middleware can <code>next()</code> immediately, but the final argument will be called when all the parallel middleware have called <code>done()</code>.</p>
+
+<h2>Use cases</h2>
+
+<p>Middleware are useful for:</p>
+
+<ul>
+<li>Complex validation</li>
+<li>Removing dependent documents when a certain document is removed (eg:
+removing a user removes all his blogposts)</li>
+<li>Asynchronous defaults</li>
+<li>Asynchronous tasks that a certain action triggers. For example:
+<ul><li>Triggering custom events</li>
+<li>Creating notifications</li>
+<li>Emails</li></ul></li>
+</ul>
+
+<p>and many other things. They're specially useful for atomizing model logic and avoiding nested blocks of async code.