monastery 1.36.0 → 1.36.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +2 -1
- package/.travis.yml +1 -1
- package/changelog.md +23 -0
- package/docs/{schema/rules.md → definition/field-rules.md} +6 -4
- package/docs/definition/index.md +338 -0
- package/docs/image-plugin.md +16 -16
- package/docs/manager/index.md +8 -8
- package/docs/manager/model.md +4 -3
- package/docs/manager/models.md +1 -1
- package/docs/model/find.md +31 -29
- package/docs/model/findOne.md +3 -4
- package/docs/model/findOneAndUpdate.md +42 -0
- package/docs/model/index.md +2 -2
- package/docs/model/insert.md +22 -20
- package/docs/model/remove.md +3 -3
- package/docs/model/update.md +11 -10
- package/docs/model/validate.md +22 -25
- package/docs/readme.md +7 -6
- package/lib/model-crud.js +32 -20
- package/lib/model-validate.js +4 -4
- package/lib/util.js +13 -1
- package/package.json +1 -1
- package/test/blacklisting.js +132 -177
- package/test/crud.js +98 -27
- package/test/mock/blacklisting.js +122 -0
- package/test/test.js +2 -0
- package/test/validate.js +35 -3
- package/docs/schema/index.md +0 -313
package/.eslintrc.json
CHANGED
package/.travis.yml
CHANGED
package/changelog.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [1.36.3](https://github.com/boycce/monastery/compare/1.36.2...1.36.3) (2022-05-27)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* order maintained when mixing of formData/dotNotation with normal key values ([898fa90](https://github.com/boycce/monastery/commit/898fa90a25e81ae1d2413e32ca67173fdef733a9))
|
|
11
|
+
|
|
12
|
+
### [1.36.2](https://github.com/boycce/monastery/compare/1.36.1...1.36.2) (2022-05-26)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* nullObjects were skipping required rules ([315af00](https://github.com/boycce/monastery/commit/315af000ea274a165e58a39b850508bd3a417642))
|
|
18
|
+
* refactored tests (oid) ([439aa27](https://github.com/boycce/monastery/commit/439aa279c5073d1652b8a6b81f2fce7ae403b0d5))
|
|
19
|
+
* tests (oid) ([bd92970](https://github.com/boycce/monastery/commit/bd92970957c9cb0bd5e0a4b4c4433fd4b6c6b7d7))
|
|
20
|
+
|
|
21
|
+
### [1.36.1](https://github.com/boycce/monastery/compare/1.36.0...1.36.1) (2022-04-16)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
* findOneAndUpdate population, blacklisting, etc ([19c4fc9](https://github.com/boycce/monastery/commit/19c4fc96d8c94d9dd68af2a74af693c8dc7a4c17))
|
|
27
|
+
|
|
5
28
|
## [1.36.0](https://github.com/boycce/monastery/compare/1.35.0...1.36.0) (2022-04-15)
|
|
6
29
|
|
|
7
30
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Rules
|
|
2
|
+
title: Field Rules
|
|
3
3
|
nav_order: 5
|
|
4
|
-
parent:
|
|
4
|
+
parent: Model Definition
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# Field Rules
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- Field rules are ignored if the value is **undefined**, **null**, or an **empty string** (except `required` and `type`)
|
|
10
|
+
- `type` is only ignored if the value is **undefined**
|
|
11
|
+
- `required` is never ignored
|
|
10
12
|
|
|
11
13
|
Rule | Rule argument
|
|
12
14
|
- | -
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Model Definition
|
|
3
|
+
nav_order: 4
|
|
4
|
+
has_children: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Model Definition
|
|
8
|
+
|
|
9
|
+
Model definition object.
|
|
10
|
+
|
|
11
|
+
### Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Fields](#fields)
|
|
14
|
+
- [Field blacklisting](#field-blacklisting)
|
|
15
|
+
- [Field options](#field-options)
|
|
16
|
+
- [MongoDB indexes](#mongodb-indexes)
|
|
17
|
+
- [Custom field rules](#custom-field-rules)
|
|
18
|
+
- [Custom error messages](#custom-error-messages)
|
|
19
|
+
- [Operation hooks](#operation-hooks)
|
|
20
|
+
- [Full example](#full-example)
|
|
21
|
+
|
|
22
|
+
### Fields
|
|
23
|
+
|
|
24
|
+
1. Fields can either be a field-type, embedded document, or an array of field-types or embedded documents
|
|
25
|
+
2. Field-types are recognised by having a `type` property defined as a string
|
|
26
|
+
3. Field-types can contain [custom](#custom-field-rules) and [default field rules](./rules), e.g. `{ minLength: 2 }`
|
|
27
|
+
4. Field-types can contain [field options](#field-options).
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
{
|
|
31
|
+
fields: {
|
|
32
|
+
name: { // Field-type
|
|
33
|
+
type: 'string',
|
|
34
|
+
required: true,
|
|
35
|
+
},
|
|
36
|
+
address: { // embedded document
|
|
37
|
+
line1: { type: 'string', required: true },
|
|
38
|
+
city: { type: 'string', minLength: 2 },
|
|
39
|
+
},
|
|
40
|
+
names: [ // array of field-types
|
|
41
|
+
{ type: 'string' },
|
|
42
|
+
],
|
|
43
|
+
pets: [{ // array of embedded documents
|
|
44
|
+
name: { type: 'string' },
|
|
45
|
+
type: { type: 'string' },
|
|
46
|
+
}]
|
|
47
|
+
// You can add a rule on the embedded document or array using the following structure
|
|
48
|
+
pets: {
|
|
49
|
+
type: [{
|
|
50
|
+
name: { type: 'string' },
|
|
51
|
+
type: { type: 'string' },
|
|
52
|
+
}],
|
|
53
|
+
minLength: 1,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The fields below implicitly get assigned and take presidence over any input data when [`manager.timestamps`](./manager) is true (default). You can override the `timestamps` value per operation, e.g. `db.user.update({ ..., timestamps: false})`. These fields use unix timestamps in seconds (by default), but can be configured to use use milliseconds via the manager [`useMilliseconds` ](./manager) option.
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
{
|
|
63
|
+
fields: {
|
|
64
|
+
createdAt: {
|
|
65
|
+
type: 'date',
|
|
66
|
+
insertOnly: true,
|
|
67
|
+
default: function() { return Math.floor(Date.now() / 1000) }
|
|
68
|
+
},
|
|
69
|
+
updatedAt: {
|
|
70
|
+
type: 'date',
|
|
71
|
+
default: function() { return Math.floor(Date.now() / 1000) }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Field blacklisting
|
|
78
|
+
|
|
79
|
+
You are able to provide a list of fields to blacklist per model operation.
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
{
|
|
83
|
+
// The 'password' field will be removed from the results returned from `model.find`
|
|
84
|
+
findBL: ['password'],
|
|
85
|
+
|
|
86
|
+
// The 'password' field will be removed before inserting via `model.insert`
|
|
87
|
+
insertBL: ['password'],
|
|
88
|
+
|
|
89
|
+
// The 'password' and 'createdAt' fields will be removed before updating via `model.update`
|
|
90
|
+
updateBL: ['createdAt', 'password'],
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
You are also able to blacklist fields on embedded documents and arrays of embedded documents.
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
{
|
|
98
|
+
// Embedded document example: `address.city` will be excluded from the response
|
|
99
|
+
findBL: ['address.city']
|
|
100
|
+
|
|
101
|
+
// Array of embedded documents example: `meta` will be removed from each comment in the array
|
|
102
|
+
findBL: ['addresses.city']
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Field options
|
|
107
|
+
|
|
108
|
+
Here are some other special field options that can be used alongside field rules.
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
fieldType: {
|
|
112
|
+
|
|
113
|
+
// Enables population, you would save the foreign document _id on this field.
|
|
114
|
+
model: 'pet',
|
|
115
|
+
|
|
116
|
+
// Field will only be allowed to be set on insert when calling model.insert
|
|
117
|
+
insertOnly: true,
|
|
118
|
+
|
|
119
|
+
// Default will always override any passed value (it has some use-cases)
|
|
120
|
+
defaultOverride: true,
|
|
121
|
+
|
|
122
|
+
// Default value
|
|
123
|
+
default: 12,
|
|
124
|
+
|
|
125
|
+
// Default value can be returned from a function. `this` refers to the data object, but be
|
|
126
|
+
// sure to pass any referenced default fields along with insert/update/validate, e.g. `this.age`
|
|
127
|
+
default: function(fieldName, model) { return `I'm ${this.age} years old` },
|
|
128
|
+
|
|
129
|
+
// Monastery will automatically create a mongodb index for this field, see "MongoDB indexes"
|
|
130
|
+
// below for more information
|
|
131
|
+
index: true|1|-1|'text'|'unique'|Object,
|
|
132
|
+
|
|
133
|
+
// The field won't stored, handy for fields that get populated with documents, see ./find for more details
|
|
134
|
+
virtual: true
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### MongoDB indexes
|
|
140
|
+
|
|
141
|
+
You are able to automatically setup MongoDB indexes via the `index` field option.
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
fieldType: {
|
|
145
|
+
|
|
146
|
+
// This will create an ascending / descending index for this field
|
|
147
|
+
index: true|1|-1,
|
|
148
|
+
|
|
149
|
+
// This will create an ascending unique index which translates:
|
|
150
|
+
// { key: { [fieldName]: 1 }, unique: true }
|
|
151
|
+
index: 'unique',
|
|
152
|
+
|
|
153
|
+
// Text indexes are handled a little differently in which all the fields on the model
|
|
154
|
+
// definition that have a `index: 'text` set are collated into one index, e.g.
|
|
155
|
+
// { key: { [fieldName1]: 'text', [fieldName2]: 'text', .. }}
|
|
156
|
+
index: 'text'
|
|
157
|
+
|
|
158
|
+
// You can also pass an object if you need to use mongodb's index options
|
|
159
|
+
// https://docs.mongodb.com/manual/reference/command/createIndexes/
|
|
160
|
+
// https://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html#createIndexes
|
|
161
|
+
index: { type: 1, ...(any mongodb index option) },
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
And here's how you would use a 2dsphere index, e.g.
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
{
|
|
170
|
+
fields: {
|
|
171
|
+
location: {
|
|
172
|
+
index: '2dsphere',
|
|
173
|
+
type: { type: 'string', default: 'Point' },
|
|
174
|
+
coordinates: [{ type: 'number' }] // lng, lat
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Inserting a 2dsphere point
|
|
180
|
+
await db.user.insert({
|
|
181
|
+
data: {
|
|
182
|
+
location: {
|
|
183
|
+
coordinates: [170.2628528648167, -43.59467883784971]
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Since unique indexes by default don't allow multiple documents with `null`, you use a partial index (less performant), e.g.
|
|
190
|
+
|
|
191
|
+
```js
|
|
192
|
+
{
|
|
193
|
+
fields: {
|
|
194
|
+
// So, instead of...
|
|
195
|
+
email: {
|
|
196
|
+
type: 'string',
|
|
197
|
+
index: 'unique',
|
|
198
|
+
},
|
|
199
|
+
// You would use...
|
|
200
|
+
email: {
|
|
201
|
+
type: 'string',
|
|
202
|
+
index: {
|
|
203
|
+
type: 'unique',
|
|
204
|
+
partialFilterExpression: {
|
|
205
|
+
email: { $type: 'string' }
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Custom field rules
|
|
214
|
+
|
|
215
|
+
You are able to define custom field rules to use. (`this` will refer to the data object passed in)
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
{
|
|
219
|
+
rules: {
|
|
220
|
+
// Basic definition
|
|
221
|
+
isGrandMaster: function(value, ruleArgument, path, model) {
|
|
222
|
+
return (value == 'Martin Luther')? true : false
|
|
223
|
+
},
|
|
224
|
+
// Full definition
|
|
225
|
+
isGrandMaster: {
|
|
226
|
+
message: function(value, ruleArgument, path, model) {
|
|
227
|
+
return 'Only grand masters are permitted'
|
|
228
|
+
},
|
|
229
|
+
fn: function(value, ruleArgument, path, model) {
|
|
230
|
+
return (value == 'Martin Luther' || this.age > 100)? true : false
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// And referencing is the same as any other builtin rule
|
|
237
|
+
{
|
|
238
|
+
fields: {
|
|
239
|
+
user: {
|
|
240
|
+
name: {
|
|
241
|
+
type: 'string'
|
|
242
|
+
isGrandMaster: true, // true is the ruleArgument
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Additionally, you can define custom messages here
|
|
249
|
+
{
|
|
250
|
+
messages: {
|
|
251
|
+
'user.name': {
|
|
252
|
+
isGrandMaster: 'Only grand masters are permitted'
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Custom error messages
|
|
259
|
+
|
|
260
|
+
You are able to define custom error messages for each field rule.
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
{
|
|
264
|
+
messages: {
|
|
265
|
+
'name': {
|
|
266
|
+
required: 'Sorry, even a monk cannot be nameless'
|
|
267
|
+
type: 'Sorry, your name needs to be a string'
|
|
268
|
+
},
|
|
269
|
+
'address.city': {
|
|
270
|
+
minLength: function(value, ruleArgument, path, model) {
|
|
271
|
+
return `Is your city of residence really only ${ruleArgument} characters long?`
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
// Assign custom error messages for arrays
|
|
275
|
+
'pets': {
|
|
276
|
+
minLength: `Please add at least one pet pet group.`
|
|
277
|
+
},
|
|
278
|
+
// You can assign custom error messages for all fields on embedded documents in an array
|
|
279
|
+
// e.g. pets = [{ name: { type: 'string' }}]
|
|
280
|
+
'pets.name': {
|
|
281
|
+
required: `Your pet's name needs to be a string.`
|
|
282
|
+
},
|
|
283
|
+
// To target a specific array item
|
|
284
|
+
'pets.0.name': {
|
|
285
|
+
required: `You first pet needs a name`
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Operation hooks
|
|
292
|
+
|
|
293
|
+
You are able provide an array of callbacks to these model operation hooks. If you need to throw an error asynchronously, please pass an error as the first argument to `next()`, e.g. `next(new Error('Your error here'))`. You can also access the operation details via `this` in each callback.
|
|
294
|
+
|
|
295
|
+
```js
|
|
296
|
+
{
|
|
297
|
+
afterFind: [function(data, next) {}],
|
|
298
|
+
afterInsert: [function(data, next) {}],
|
|
299
|
+
afterInsertUpdate: [function(data, next) {}],
|
|
300
|
+
afterUpdate: [function(data, next) {}],
|
|
301
|
+
afterRemove: [function(next) {}],
|
|
302
|
+
beforeInsert: [function(data, next) {}],
|
|
303
|
+
beforeInsertUpdate: [function(data, next) {}],
|
|
304
|
+
beforeUpdate: [function(data, next) {}],
|
|
305
|
+
beforeRemove: [function(next) {}],
|
|
306
|
+
beforeValidate: [function(data, next) {}],
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Definition example
|
|
311
|
+
|
|
312
|
+
```js
|
|
313
|
+
{
|
|
314
|
+
fields: {
|
|
315
|
+
email: { type: 'email', required: true, index: 'unique' },
|
|
316
|
+
firstName: { type: 'string', required: true },
|
|
317
|
+
lastName: { type: 'string' }
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
messages: {
|
|
321
|
+
email: { required: 'Please enter an email.' }
|
|
322
|
+
},
|
|
323
|
+
|
|
324
|
+
updateBL: ['email'],
|
|
325
|
+
|
|
326
|
+
beforeValidate: [function (data, next) {
|
|
327
|
+
if (data.firstName) data.firstName = util.ucFirst(data.firstName)
|
|
328
|
+
if (data.lastName) data.lastName = util.ucFirst(data.lastName)
|
|
329
|
+
next()
|
|
330
|
+
}],
|
|
331
|
+
|
|
332
|
+
afterFind: [function(data) {// Synchronous
|
|
333
|
+
data = data || {}
|
|
334
|
+
data.name = data.firstName + ' ' + data.lastName
|
|
335
|
+
}],
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
```
|
package/docs/image-plugin.md
CHANGED
|
@@ -7,8 +7,6 @@ nav_order: 7
|
|
|
7
7
|
|
|
8
8
|
To use the default image plugin shipped with monastery, you need to use the options below when initialising a manager
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
10
|
```js
|
|
13
11
|
let db = monastery('localhost/mydb', {
|
|
14
12
|
imagePlugin: {
|
|
@@ -21,22 +19,24 @@ To use the default image plugin shipped with monastery, you need to use the opti
|
|
|
21
19
|
})
|
|
22
20
|
```
|
|
23
21
|
|
|
24
|
-
Then in your model
|
|
22
|
+
Then in your model definition, e.g.
|
|
25
23
|
|
|
26
24
|
```js
|
|
27
|
-
let user = db.model('user', {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
25
|
+
let user = db.model('user', {
|
|
26
|
+
fields: {
|
|
27
|
+
logo: {
|
|
28
|
+
type: 'image', // required
|
|
29
|
+
formats: ['bmp', 'gif', 'jpg', 'jpeg', 'png', 'tiff'],
|
|
30
|
+
filename: 'avatar',
|
|
31
|
+
filesize: 1000 * 1000 * 5, // max size in bytes
|
|
32
|
+
getSignedUrl: true, // get a s3 signed url after every `find()` operation (can be overridden per request)
|
|
33
|
+
params: {}, // upload params, https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property
|
|
34
|
+
},
|
|
35
|
+
logos: [{
|
|
36
|
+
type: 'image'
|
|
37
|
+
}],
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Then when inserting or updating a document you need to set `files` to an obkect containing containing your parsed files, [express-fileupload](https://github.com/richardgirges/express-fileupload) works great with an express setup, e.g.
|
package/docs/manager/index.md
CHANGED
|
@@ -10,16 +10,16 @@ Monastery constructor, same as the [monk constructor](https://automattic.github.
|
|
|
10
10
|
|
|
11
11
|
### Arguments
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
`uri` *(string\|array)*: A [mongo connection string URI](https://docs.mongodb.com/manual/reference/connection-string/). Replica sets can be an array or comma separated.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
[`options`] *(object)*:
|
|
16
|
+
- [`defaultObjects=false`] *(boolean)*: when [inserting](../model/insert.html#defaults-example), undefined embedded documents and arrays are defined
|
|
17
|
+
- [`nullObjects=false`] *(boolean)*: embedded documents and arrays can be set to null or an empty string (which gets converted to null). You can override this per field via `nullObject: true`.
|
|
18
|
+
- [`timestamps=true`] *(boolean)*: whether to use [`createdAt` and `updatedAt`](../definition), this can be overridden per operation
|
|
19
|
+
- [`useMilliseconds=false`] *(boolean)*: by default the `createdAt` and `updatedAt` fields that get created automatically use unix timestamps in seconds, set this to true to use milliseconds instead.
|
|
20
|
+
- [`mongo options`](http://mongodb.github.io/node-mongodb-native/3.2/reference/connecting/connection-settings/)...
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
[`callback`] *(function)*: You may optionally specify a callback which will be called once the connection to the mongo database is opened or throws an error.
|
|
23
23
|
|
|
24
24
|
### Returns
|
|
25
25
|
|
package/docs/manager/model.md
CHANGED
|
@@ -9,13 +9,14 @@ Sets up a model, retrieves a collection, and sets up any required indexes
|
|
|
9
9
|
|
|
10
10
|
### Arguments
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
`name` *(string)*: name of the mongo collection
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
[`definition`] *(object)*: [definition](../definition)
|
|
15
15
|
|
|
16
16
|
### Returns
|
|
17
17
|
|
|
18
18
|
A [model](../model) instance, the model instance will also be avaliable at:
|
|
19
|
+
|
|
19
20
|
```js
|
|
20
21
|
db.user
|
|
21
22
|
db.model.user
|
|
@@ -24,5 +25,5 @@ db.model.user
|
|
|
24
25
|
### Example
|
|
25
26
|
|
|
26
27
|
```js
|
|
27
|
-
const user = db.model('user',
|
|
28
|
+
const user = db.model('user', definition)
|
|
28
29
|
```
|
package/docs/manager/models.md
CHANGED
|
@@ -9,7 +9,7 @@ Setup model definitions from a folder location
|
|
|
9
9
|
|
|
10
10
|
### Arguments
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
`path` *(string)*: path to model definitions, the filenames are used as the corresponding model name.
|
|
13
13
|
|
|
14
14
|
### Returns
|
|
15
15
|
|
package/docs/model/find.md
CHANGED
|
@@ -5,18 +5,18 @@ parent: Model
|
|
|
5
5
|
|
|
6
6
|
# `model.find`
|
|
7
7
|
|
|
8
|
-
Find document(s) in a collection and call
|
|
8
|
+
Find document(s) in a collection and call the model hook: `afterFind`
|
|
9
9
|
|
|
10
10
|
### Arguments
|
|
11
11
|
|
|
12
12
|
`options` *(object)*
|
|
13
13
|
|
|
14
|
-
- `
|
|
15
|
-
- [[`
|
|
16
|
-
- [`
|
|
17
|
-
- [`
|
|
18
|
-
- [`
|
|
19
|
-
- [`
|
|
14
|
+
- `query` *(object\|id)*
|
|
15
|
+
- [[`blacklist`](#blacklisting)] *(array\|string\|false)*: augment `definition.findBL`. `false` will remove all blacklisting
|
|
16
|
+
- [`getSignedUrls`] *(boolean)*: get signed urls for all image objects
|
|
17
|
+
- [[`populate`](#populate)] *(array)*
|
|
18
|
+
- [`project`] *(string\|array\|object)*: return only these fields, ignores blacklisting
|
|
19
|
+
- [`sort`] *(string\|array\|object)*: same as the mongodb option, but allows string parsing e.g. 'name', 'name:1'
|
|
20
20
|
- [[`any mongodb option`](http://mongodb.github.io/node-mongodb-native/3.2/api/Collection.html#find)] *(any)*
|
|
21
21
|
|
|
22
22
|
[`callback`] *(function)*: pass instead of return a promise
|
|
@@ -28,27 +28,24 @@ A promise if no callback is passed in.
|
|
|
28
28
|
### Example
|
|
29
29
|
|
|
30
30
|
```js
|
|
31
|
-
user.find({ query: "5ebdd6677466b95109aa278e" })
|
|
32
|
-
|
|
33
|
-
})
|
|
31
|
+
await user.find({ query: "5ebdd6677466b95109aa278e" })
|
|
32
|
+
// {..}
|
|
34
33
|
|
|
35
|
-
user.find({ query: { name: "Martin Luther" }})
|
|
36
|
-
|
|
37
|
-
})
|
|
34
|
+
await user.find({ query: { name: "Martin Luther" }})
|
|
35
|
+
// [{..}]
|
|
38
36
|
|
|
39
|
-
user.find({ query: { name: "Martin Luther" }, limit: 100 })
|
|
40
|
-
|
|
41
|
-
})
|
|
37
|
+
await user.find({ query: { name: "Martin Luther" }, limit: 100 })
|
|
38
|
+
// [{..}]
|
|
42
39
|
```
|
|
43
40
|
|
|
44
41
|
### Blacklisting
|
|
45
42
|
|
|
46
|
-
You can augment the model's `
|
|
43
|
+
You can augment the model's `definition.findBL` blacklist by passing a custom `blacklist`:
|
|
47
44
|
|
|
48
45
|
```js
|
|
49
46
|
// Prevents `name` and `pets.$.name` (array) from being returned.
|
|
50
47
|
user.find({ query: {}, blacklist: ['name', 'pets.name'] })
|
|
51
|
-
// You can also whitelist any blacklisted fields found in
|
|
48
|
+
// You can also whitelist any blacklisted fields found in definition.findBL
|
|
52
49
|
user.find({ query: {}, blacklist: ['-name', '-pet'] })
|
|
53
50
|
```
|
|
54
51
|
|
|
@@ -57,13 +54,15 @@ user.find({ query: {}, blacklist: ['-name', '-pet'] })
|
|
|
57
54
|
You are able to populate document references to other collections. Behind the scenes
|
|
58
55
|
this uses mongodb's [$lookup](https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/) aggregation operator which can also be passed full $lookup syntax for more control.
|
|
59
56
|
|
|
60
|
-
Populate is first enabled by including a reference to another document in the
|
|
57
|
+
Populate is first enabled by including a reference to another document in the field-type via `model`.
|
|
61
58
|
The value of the model reference should be an ID, e.g. `myBook = id`
|
|
62
59
|
|
|
63
60
|
```js
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
{
|
|
62
|
+
fields: {
|
|
63
|
+
myBook: {
|
|
64
|
+
model: 'book'
|
|
65
|
+
}
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
68
|
```
|
|
@@ -74,7 +73,7 @@ You are then able to easily populate returned results via a find operation.
|
|
|
74
73
|
user.find({ query: {...}, populate: ['myBook'] })
|
|
75
74
|
```
|
|
76
75
|
|
|
77
|
-
You can also populate within
|
|
76
|
+
You can also populate within embedded document fields. Although at this time arrays are not supported,
|
|
78
77
|
you would need to use the [example below](#more-control).
|
|
79
78
|
```js
|
|
80
79
|
user.find({ query: {...}, populate: ['myBooks.book'] })
|
|
@@ -85,7 +84,8 @@ user.find({ query: {...}, populate: ['myBooks.book'] })
|
|
|
85
84
|
If you would like more control you can either use monk's native
|
|
86
85
|
[aggregate](https://automattic.github.io/monk/docs/collection/aggregate.html) function via
|
|
87
86
|
`user._aggregate`, or simply pass a MongoDB lookup object to populate. When passing a lookup object, the
|
|
88
|
-
populated field still needs to be defined
|
|
87
|
+
populated field still needs to be defined in `definition.fields` if you want to call any related hooks,
|
|
88
|
+
and prune any blacklisted fields. See the examples below,
|
|
89
89
|
|
|
90
90
|
#### Populate a single document
|
|
91
91
|
|
|
@@ -109,11 +109,13 @@ Below populates all books into `user.myBooks` with a `bookOwnerId` equal to the
|
|
|
109
109
|
isn't stored on the user, you will need define it as virtual field
|
|
110
110
|
|
|
111
111
|
```js
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
{
|
|
113
|
+
fields: {
|
|
114
|
+
myBooks: [{
|
|
115
|
+
model: 'book',
|
|
116
|
+
virtual: true
|
|
117
|
+
}],
|
|
118
|
+
},
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
user.find({
|
package/docs/model/findOne.md
CHANGED
|
@@ -5,7 +5,7 @@ parent: Model
|
|
|
5
5
|
|
|
6
6
|
# `model.findOne`
|
|
7
7
|
|
|
8
|
-
Find a single document and call
|
|
8
|
+
Find a single document and call the model hook: `afterFind`
|
|
9
9
|
|
|
10
10
|
### Arguments
|
|
11
11
|
|
|
@@ -18,7 +18,6 @@ A promise if no callback is passed in.
|
|
|
18
18
|
### Example
|
|
19
19
|
|
|
20
20
|
```js
|
|
21
|
-
user.findOne({ query: { name: "Martin Luther" }})
|
|
22
|
-
|
|
23
|
-
})
|
|
21
|
+
await user.findOne({ query: { name: "Martin Luther" }})
|
|
22
|
+
// {..}
|
|
24
23
|
```
|