forked from Automattic/mongoose
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlean.html
More file actions
261 lines (232 loc) · 23.4 KB
/
lean.html
File metadata and controls
261 lines (232 loc) · 23.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Mongoose v5.6.4-pre: Mongoose Tutorials: Faster Mongoose Queries With Lean</title><link rel="apple-touch-icon" sizes="57x57" href="images/favicon/apple-icon-57x57.png"><link rel="apple-touch-icon" sizes="60x60" href="images/favicon/apple-icon-60x60.png"><link rel="apple-touch-icon" sizes="72x72" href="images/favicon/apple-icon-72x72.png"><link rel="apple-touch-icon" sizes="76x76" href="images/favicon/apple-icon-76x76.png"><link rel="apple-touch-icon" sizes="114x114" href="images/favicon/apple-icon-114x114.png"><link rel="apple-touch-icon" sizes="120x120" href="images/favicon/apple-icon-120x120.png"><link rel="apple-touch-icon" sizes="144x144" href="images/favicon/apple-icon-144x144.png"><link rel="apple-touch-icon" sizes="152x152" href="images/favicon/apple-icon-152x152.png"><link rel="apple-touch-icon" sizes="180x180" href="images/favicon/apple-icon-180x180.png"><link rel="icon" type="image/png" sizes="192x192" href="images/favicon/android-icon-192x192.png"><link rel="icon" type="image/png" sizes="32x32" href="images/favicon/favicon-32x32.png"><link rel="icon" type="image/png" sizes="96x96" href="images/favicon/favicon-96x96.png"><link rel="icon" type="image/png" sizes="16x16" href="images/favicon/favicon-16x16.png"><link rel="stylesheet" href="https://unpkg.com/[email protected]/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous"><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans"><link rel="stylesheet" href="/docs/css/github.css"><link rel="stylesheet" href="/docs/css/mongoose5.css"><link rel="apple-touch-icon" sizes="57x57" href="images/favicon/apple-icon-57x57.png"><link rel="apple-touch-icon" sizes="60x60" href="images/favicon/apple-icon-60x60.png"><link rel="apple-touch-icon" sizes="72x72" href="images/favicon/apple-icon-72x72.png"><link rel="apple-touch-icon" sizes="76x76" href="images/favicon/apple-icon-76x76.png"><link rel="apple-touch-icon" sizes="114x114" href="images/favicon/apple-icon-114x114.png"><link rel="apple-touch-icon" sizes="120x120" href="images/favicon/apple-icon-120x120.png"><link rel="apple-touch-icon" sizes="144x144" href="images/favicon/apple-icon-144x144.png"><link rel="apple-touch-icon" sizes="152x152" href="images/favicon/apple-icon-152x152.png"><link rel="apple-touch-icon" sizes="180x180" href="images/favicon/apple-icon-180x180.png"><link rel="icon" type="image/png" sizes="192x192" href="images/favicon/android-icon-192x192.png"><link rel="icon" type="image/png" sizes="32x32" href="images/favicon/favicon-32x32.png"><link rel="icon" type="image/png" sizes="96x96" href="images/favicon/favicon-96x96.png"><link rel="icon" type="image/png" sizes="16x16" href="images/favicon/favicon-16x16.png"><link rel="manifest" href="images/favicon/manifest.json"><meta name="msapplication-TileColor" content="#ffffff"><meta name="msapplication-TileImage" content="images/favicon/ms-icon-144x144.png"><meta name="theme-color" content="#ffffff"><link rel="stylesheet" href="/docs/css/inlinecpc.css"><script type="text/javascript" src="/docs/js/native.js"></script><style>p { line-height: 1.5em }
</style></head><body><div id="layout"><div id="mobile-menu"><a class="menu-link" id="menuLink" href="#menu"><span></span></a><div id="mobile-logo-container"><a href="/"><img id="logo" src="/docs/images/mongoose5_62x30_transparent.png"><span class="logo-text">mongoose</span></a></div></div><div id="menu"><div class="pure-menu"><div class="pure-menu-heading" id="logo-container"><a href="/"><img id="logo" src="/docs/images/mongoose5_62x30_transparent.png"><span class="logo-text">mongoose</span></a></div><ul class="pure-menu-list" id="navbar"><li class="pure-menu-horizontal pure-menu-item pure-menu-has-children pure-menu-allow-hover version"><a class="pure-menu-link" href="#">Version 5.6.4-pre</a><ul class="pure-menu-children"><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/4.x">Version 4.13.19</a></li><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/3.8.x">Version 3.8.40</a></li></ul></li><li class="pure-menu-item search"><input id="search-input-nav" type="text" placeholder="Search"><button id="search-button-nav"><img src="/docs/images/search.svg"></button></li><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/index.html">Quick Start</a></li><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/guides.html">Guides</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/guide.html">Schemas</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/schematypes.html">SchemaTypes</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/connections.html">Connections</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/models.html">Models</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/documents.html">Documents</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/subdocs.html">Subdocuments</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/queries.html">Queries</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/validation.html">Validation</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/middleware.html">Middleware</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/populate.html">Populate</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/discriminators.html">Discriminators</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/plugins.html">Plugins</a></li><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/api.html">API</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/mongoose.html">Mongoose</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/schema.html">Schema</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/connection.html">Connection</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/document.html">Document</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/model.html">Model</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/query.html">Query</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/aggregate.html">Aggregate</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/schematype.html">SchemaType</a></li><li class="pure-menu-item sub-item"><a class="pure-menu-link" href="/docs/api/virtualtype.html">VirtualType</a></li><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/compatibility.html">Version Compatibility</a></li><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/faq.html">FAQ</a></li><li class="pure-menu-item"><a class="pure-menu-link" href="/docs/further_reading.html">Further Reading</a></li></ul><div class="cpc-ad"><script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=mongoosejscom" id="_carbonads_js"></script></div></div></div><div class="container"><div id="content"><h1 id="faster-mongoose-queries-with-lean">Faster Mongoose Queries With Lean</h1>
<script>
_native.init("CK7DT53U",{
targetClass: 'native-inline'
});
</script>
<div class="native-inline">
<a href="#native_link#"><span class="sponsor">Sponsor</span> #native_company# — #native_desc#</a>
</div>
<p>The <a href="/docs/api.html#query_Query-lean">lean option</a> tells Mongoose to skip
<a href="/docs/api.html#model_Model.hydrate">hydrating</a> the result documents. This
makes queries faster and less memory intensive, but the result documents are
plain old JavaScript objects (POJOs), <strong>not</strong> <a href="/docs/documents.html">Mongoose documents</a>.
In this tutorial, you'll learn more about the tradeoffs of using <code>lean()</code>.</p>
<ul>
<li><a href="#using-lean">Using Lean</a></li>
<li><a href="#lean-and-populate">Lean and Populate</a></li>
<li><a href="#when-to-use-lean">When to Use Lean</a></li>
</ul>
<h2 id="using-lean"><a href="#using-lean">Using Lean</a></h2>
<p>By default, Mongoose queries return an instance of the
<a href="/docs/api.html#Document">Mongoose <code>Document</code> class</a>. Documents are much
heavier than vanilla JavaScript objects, because they have a lot of internal
state for change tracking. Enabling the <code>lean</code> option tells Mongoose to skip
instantiating a full Mongoose document and just give you the POJO.</p>
<pre><code class="language-javascript"><span class="hljs-keyword">const</span> leanDoc = <span class="hljs-keyword">await</span> MyModel.findOne().lean();</code></pre>
<p>How much smaller are lean documents? Here's a comparison.</p>
<pre><code class="language-javascript"><span class="hljs-keyword">const</span> schema = <span class="hljs-keyword">new</span> mongoose.Schema({ name: <span class="hljs-built_in">String</span> });
<span class="hljs-keyword">const</span> MyModel = mongoose.model(<span class="hljs-string">'Test'</span>, schema);
<span class="hljs-keyword">await</span> MyModel.create({ name: <span class="hljs-string">'test'</span> });
<span class="hljs-comment">// Module that estimates the size of an object in memory</span>
<span class="hljs-keyword">const</span> sizeof = <span class="hljs-built_in">require</span>(<span class="hljs-string">'object-sizeof'</span>);
<span class="hljs-keyword">const</span> normalDoc = <span class="hljs-keyword">await</span> MyModel.findOne();
<span class="hljs-comment">// To enable the `lean` option for a query, use the `lean()` function.</span>
<span class="hljs-keyword">const</span> leanDoc = <span class="hljs-keyword">await</span> MyModel.findOne().lean();
sizeof(normalDoc); <span class="hljs-comment">// >= 1000</span>
sizeof(leanDoc); <span class="hljs-comment">// 86, 10x smaller!</span>
<span class="hljs-comment">// In case you were wondering, the JSON form of a Mongoose doc is the same</span>
<span class="hljs-comment">// as the POJO. This additional memory only affects how much memory your</span>
<span class="hljs-comment">// Node.js process uses, not how much data is sent over the network.</span>
<span class="hljs-built_in">JSON</span>.stringify(normalDoc).length === <span class="hljs-built_in">JSON</span>.stringify(leanDoc.length); <span class="hljs-comment">// true</span></code></pre>
<p>Under the hood, after executing a query, Mongoose converts the query results
from POJOs to Mongoose documents. If you turn on the <code>lean</code> option, Mongoose
skips this step.</p>
<pre><code class="language-javascript"><span class="hljs-keyword">const</span> normalDoc = <span class="hljs-keyword">await</span> MyModel.findOne();
<span class="hljs-keyword">const</span> leanDoc = <span class="hljs-keyword">await</span> MyModel.findOne().lean();
normalDoc <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// true</span>
normalDoc.constructor.name; <span class="hljs-comment">// 'model'</span>
leanDoc <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// false</span>
leanDoc.constructor.name; <span class="hljs-comment">// 'Object'</span></code></pre>
<p>The downside of enabling <code>lean</code> is that lean docs don't have:</p>
<ul>
<li>Change tracking</li>
<li>Casting and validation</li>
<li>Getters and setters</li>
<li>Virtuals</li>
<li><code>save()</code></li>
</ul>
<p>For example, the following code sample shows that the <code>Person</code> model's getters
and virtuals don't run if you enable <code>lean</code>.</p>
<pre><code class="language-javascript"><span class="hljs-comment">// Define a `Person` model. Schema has 2 custom getters and a `fullName`</span>
<span class="hljs-comment">// virtual. Neither the getters nor the virtuals will run if lean is enabled.</span>
<span class="hljs-keyword">const</span> personSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
firstName: {
type: <span class="hljs-built_in">String</span>,
get: capitalizeFirstLetter
},
lastName: {
type: <span class="hljs-built_in">String</span>,
get: capitalizeFirstLetter
}
});
personSchema.virtual(<span class="hljs-string">'fullName'</span>).get(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${this.firstName}</span> <span class="hljs-subst">${this.lastName}</span>`</span>;
});
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">capitalizeFirstLetter</span>(<span class="hljs-params">v</span>) </span>{
<span class="hljs-comment">// Convert 'bob' -> 'Bob'</span>
<span class="hljs-keyword">return</span> v.charAt(<span class="hljs-number">0</span>).toUpperCase() + v.substr(<span class="hljs-number">1</span>);
}
<span class="hljs-keyword">const</span> Person = mongoose.model(<span class="hljs-string">'Person'</span>, personSchema);
<span class="hljs-comment">// Create a doc and load it as a lean doc</span>
<span class="hljs-keyword">await</span> Person.create({ firstName: <span class="hljs-string">'benjamin'</span>, lastName: <span class="hljs-string">'sisko'</span> });
<span class="hljs-keyword">const</span> normalDoc = <span class="hljs-keyword">await</span> Person.findOne();
<span class="hljs-keyword">const</span> leanDoc = <span class="hljs-keyword">await</span> Person.findOne().lean();
normalDoc.fullName; <span class="hljs-comment">// 'Benjamin Sisko'</span>
normalDoc.firstName; <span class="hljs-comment">// 'Benjamin', because of `capitalizeFirstLetter()`</span>
normalDoc.lastName; <span class="hljs-comment">// 'Sisko', because of `capitalizeFirstLetter()`</span>
leanDoc.fullName; <span class="hljs-comment">// undefined</span>
leanDoc.firstName; <span class="hljs-comment">// 'benjamin', custom getter doesn't run</span>
leanDoc.lastName; <span class="hljs-comment">// 'sisko', custom getter doesn't run</span></code></pre>
<h2 id="lean-and-populate"><a href="#lean-and-populate">Lean and Populate</a></h2>
<p><a href="/docs/populate.html">Populate</a> works with <code>lean()</code>. If you
use both <code>populate()</code> and <code>lean()</code>, the <code>lean</code> option propagates to the
populated documents as well. In the below example, both the top-level
'Group' documents and the populated 'Person' documents will be lean.</p>
<pre><code class="language-javascript"><span class="hljs-comment">// Create models</span>
<span class="hljs-keyword">const</span> Group = mongoose.model(<span class="hljs-string">'Group'</span>, <span class="hljs-keyword">new</span> mongoose.Schema({
name: <span class="hljs-built_in">String</span>,
members: [{ type: mongoose.ObjectId, ref: <span class="hljs-string">'Person'</span> }]
}));
<span class="hljs-keyword">const</span> Person = mongoose.model(<span class="hljs-string">'Person'</span>, <span class="hljs-keyword">new</span> mongoose.Schema({
name: <span class="hljs-built_in">String</span>
}));
<span class="hljs-comment">// Initialize data</span>
<span class="hljs-keyword">const</span> people = <span class="hljs-keyword">await</span> Person.create([
{ name: <span class="hljs-string">'Benjamin Sisko'</span> },
{ name: <span class="hljs-string">'Kira Nerys'</span> }
]);
<span class="hljs-keyword">await</span> Group.create({
name: <span class="hljs-string">'Star Trek: Deep Space Nine Characters'</span>,
members: people.map(p => p._id)
});
<span class="hljs-comment">// Execute a lean query</span>
<span class="hljs-keyword">const</span> group = <span class="hljs-keyword">await</span> Group.findOne().lean().populate(<span class="hljs-string">'members'</span>);
group.members[<span class="hljs-number">0</span>].name; <span class="hljs-comment">// 'Benjamin Sisko'</span>
group.members[<span class="hljs-number">1</span>].name; <span class="hljs-comment">// 'Kira Nerys'</span>
<span class="hljs-comment">// Both the `group` and the populated `members` are lean.</span>
group <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// false</span>
group.members[<span class="hljs-number">0</span>] <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// false</span>
group.members[<span class="hljs-number">1</span>] <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// false</span></code></pre>
<p><a href="/docs/populate.html#populate-virtuals">Virtual populate</a> also works with lean.</p>
<pre><code class="language-javascript"><span class="hljs-comment">// Create models</span>
<span class="hljs-keyword">const</span> groupSchema = <span class="hljs-keyword">new</span> mongoose.Schema({ name: <span class="hljs-built_in">String</span> });
groupSchema.virtual(<span class="hljs-string">'members'</span>, {
ref: <span class="hljs-string">'Person'</span>,
localField: <span class="hljs-string">'_id'</span>,
foreignField: <span class="hljs-string">'groupId'</span>
});
<span class="hljs-keyword">const</span> Group = mongoose.model(<span class="hljs-string">'Group'</span>, groupSchema);
<span class="hljs-keyword">const</span> Person = mongoose.model(<span class="hljs-string">'Person'</span>, <span class="hljs-keyword">new</span> mongoose.Schema({
name: <span class="hljs-built_in">String</span>,
groupId: mongoose.ObjectId
}));
<span class="hljs-comment">// Initialize data</span>
<span class="hljs-keyword">const</span> g = <span class="hljs-keyword">await</span> Group.create({ name: <span class="hljs-string">'DS9 Characters'</span> });
<span class="hljs-keyword">const</span> people = <span class="hljs-keyword">await</span> Person.create([
{ name: <span class="hljs-string">'Benjamin Sisko'</span>, groupId: g._id },
{ name: <span class="hljs-string">'Kira Nerys'</span>, groupId: g._id }
]);
<span class="hljs-comment">// Execute a lean query</span>
<span class="hljs-keyword">const</span> group = <span class="hljs-keyword">await</span> Group.findOne().lean().populate({
path: <span class="hljs-string">'members'</span>,
options: { sort: { name: <span class="hljs-number">1</span> } }
});
group.members[<span class="hljs-number">0</span>].name; <span class="hljs-comment">// 'Benjamin Sisko'</span>
group.members[<span class="hljs-number">1</span>].name; <span class="hljs-comment">// 'Kira Nerys'</span>
<span class="hljs-comment">// Both the `group` and the populated `members` are lean.</span>
group <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// false</span>
group.members[<span class="hljs-number">0</span>] <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// false</span>
group.members[<span class="hljs-number">1</span>] <span class="hljs-keyword">instanceof</span> mongoose.Document; <span class="hljs-comment">// false</span></code></pre>
<h2 id="when-to-use-lean"><a href="#when-to-use-lean">When to Use Lean</a></h2>
<p>If you're executing a query and sending the results without modification to,
say, an <a href="http://expressjs.com/en/4x/api.html#res">Express response</a>, you should
use lean. In general, if you do not modify the query results and do not use
<a href="/docs/api.html#schematype_SchemaType-get">custom getters</a>, you should use
<code>lean()</code>. If you modify the query results or rely on features like getters
or <a href="/docs/api.html#document_Document-toObject">transforms</a>, you should not
use <code>lean()</code>.</p>
<p>Below is an example of an <a href="http://expressjs.com/en/guide/routing.html">Express route</a>
that is a good candidate for <code>lean()</code>. This route does not modify the <code>person</code>
doc and doesn't rely on any Mongoose-specific functionality.</p>
<pre><code class="language-javascript"><span class="hljs-comment">// As long as you don't need any of the Person model's virtuals or getters,</span>
<span class="hljs-comment">// you can use `lean()`.</span>
app.get(<span class="hljs-string">'/person/:id'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) </span>{
Person.findOne({ _id: req.params.id }).lean().
then(person => res.json({ person })).
<span class="hljs-keyword">catch</span>(error => res.json({ error: error.message }));
});</code></pre>
<p>Below is an example of an Express route that should <strong>not</strong> use <code>lean()</code>. As
a general rule of thumb, <code>GET</code> routes are good candidates for <code>lean()</code> in a
<a href="https://en.wikipedia.org/wiki/Representational_state_transfer">RESTful API</a>.
On the other hand, <code>PUT</code>, <code>POST</code>, etc. routes generally should not use <code>lean()</code>.</p>
<pre><code class="language-javascript"><span class="hljs-comment">// This route should **not** use `lean()`, because lean means no `save()`.</span>
app.put(<span class="hljs-string">'/person/:id'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) </span>{
Person.findOne({ _id: req.params.id }).
then(person => {
assert.ok(person);
<span class="hljs-built_in">Object</span>.assign(person, req.body);
<span class="hljs-keyword">return</span> person.save();
}).
then(person => res.json({ person })).
<span class="hljs-keyword">catch</span>(error => res.json({ error: error.message }));
});</code></pre>
<p>Remember that virtuals do <strong>not</strong> end up in <code>lean()</code> query results. Use the
<a href="http://plugins.mongoosejs.io/plugins/lean-virtuals">mongoose-lean-virtuals plugin</a>
to add virtuals to your lean query results.</p>
</div></div><script type="text/javascript">var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://g0a3nbw0xa.execute-api.us-east-1.amazonaws.com/prod/track', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function() {};
xhr.send(JSON.stringify({
path: window.location.pathname,
hostname: window.location.hostname,
hash: window.location.hash
}));</script><script type="text/javascript" src="/docs/js/navbar-search.js"></script><script type="text/javascript">(function (window, document) {
var layout = document.getElementById('layout'),
menu = document.getElementById('menu'),
menuLink = document.getElementById('menuLink'),
content = document.getElementById('content');
function toggleClass(element, className) {
var classes = element.className.split(/\s+/),
length = classes.length,
i = 0;
for(; i < length; i++) {
if (classes[i] === className) {
classes.splice(i, 1);
break;
}
}
// The className is not found
if (length === classes.length) {
classes.push(className);
}
element.className = classes.join(' ');
}
function toggleAll(e) {
var active = 'active';
e.preventDefault();
toggleClass(layout, active);
toggleClass(menu, active);
toggleClass(menuLink, active);
}
menuLink.onclick = function (e) {
toggleAll(e);
};
content.onclick = function(e) {
if (menu.className.indexOf('active') !== -1) {
toggleAll(e);
}
};
}(this, this.document));</script></div></body></html>