UNPKG

mongoose-bread

Version:

A pagination and softdelete library for mongoose

429 lines (311 loc) 14.9 kB
# mongoose-bread Options ## Default Options This list shows all mongoose-bread default Options followed by a explanation for each - defaultPageSize: 10 - maxPageSize: 100 - searchableFields: [] - enableAtlasSearch: false - atlasSearchIndex: '' - blacklistedFields: [] - paramsIdKey: 'id' - bulkIdsKey: '\_ids' - bulkDocsKey: '\_docs' - runUpdateTransaction: false - runUpdateValidators: true - softDelete: false - softDeleteOptions: - overrideMethods: true - validateBeforeDelete: true - indexFields: true - deletedAt: true - deletedBy: false - requestUserIdPath: '' Inherited from mongoose-paginate-v2 [Documentation](https://github.com/aravindnc/mongoose-paginate-v2#modelpaginatequery-options-callback) - select: '' - projection: {} - collation: {} - pagination: true - allowDiskUse: false - forceCountFn: false - useCustomCountFn: false 👈 **used by mongoose-bread helper for softDelete** - useEstimatedCount: false - lean: false - leanWithId: false 👈 **override mongoose-paginate-v2 default - was true** - leanWithout_id: false 👈 **additional mongoose-bread option to remove '\_id' from lean results** - customFind: 'find' - customLabels: - docs: 'docs' - meta: 'pagination' - limit: 'limit' - page: 'page' - pagingCounter: 'pagingCounter' - hasNextPage: 'hasNextPage' - hasPrevPage: 'hasPrevPage' - nextPage: 'nextPage' - prevPage: 'prevPage' - totalDocs: 'totalDocs' - totalPages: 'totalPages' - acknowledged: 'acknowledged' 👈 **additional mongoose-bread label** - modifiedCount: 'modifiedCount' 👈 **additional mongoose-bread label** - deletedCount: 'deletedCount' 👈 **additional mongoose-bread label** - createdCount: 'createdCount' 👈 **additional mongoose-bread label** - readCount: 'readCount' 👈 **additional mongoose-bread label** - options: DELETED 🚩 **NEVER USE THIS** leads to infinite loop in mongoose-paginate-v2 helper > mongoose-bread will delete the **options** property within the helper() methods > and avoids "Maximum Call Stack Size Exceeded" Error by doing so ### Explanations **defaultPageSize:`Number`** - default: 10 > limits queries to return 10 documents if no value is provided by request.query **maxPageSize:`Number`** - default: 100 > limits queries to return a maximum of 100 documents regardless of request.query value **searchableFields:`Array<String>`** - default: [] > 📢 **Disables search functionality if empty Array** > Contains the Schema property names to include in search query > in example > searchableFields = ['title', 'description', 'excerpt'] > request.query.search = "best js tutorials" > will search 'title', 'description' and 'excerpt' for **best** or **js** or **tutorials** **enableAtlasSearch:`Boolean`** - default: false > 📢 **Only suitable for MongoDB Atlas Cluster with $search support** > Runs a query with $search operator for fullText Search. [Docs](https://www.mongodb.com/docs/atlas/atlas-search/) > in example > enableAtlasSearch = true > atlasSearchIndex: 'my-fulltext-search-index' <- required > searchableFields = ['title', 'description', 'excerpt'] > request.query.search = "best js tutorials" > will search 'title', 'description' and 'excerpt' for **best js tutorials** and anything related **atlasSearchIndex:`String`** - default: '' > used in combination with enableAtlasSearch > is required if enableAtlasSearch is set to true > if ommited the search query will resolve in a regularExpression query > specifies the AtlasSearch Index created for fullText Search [Docs](https://www.mongodb.com/docs/atlas/atlas-search/) **blacklistedFields:`Array<String>`** - default: [] > creates projection > in example > blacklistedFields = ['name', 'age'] > results in: User.find({}, {name: 0, age: 0}) **paramsIdKey:`String`** - default: 'id' > expected **request.params[key]:`ObjectId`** to identify a single Resource > in example > url send: GET:https://test.org/books/6478d57784fabdbf127d0a2a > recieved by: router.get( books/:**id**, BookController.read ) > results in: request.params.**id** = 6478d57784fabdbf127d0a2a **bulkIdsKey:`String`** - default: '\_ids' > expected **request.body[key]:`Array<ObjectId>`** for bulk edit() add() destroy() softDelete() rehabilitate() > i.e. request.body: { **\_ids**: ['6478d57784fabdbf127d0a2a', '6478d57784fqwef127d0a2a'] } **bulkDocsKey:`String`** - default: '\_docs' > expected **request.body[key]:`Array<any>`** for bulk edit() add() destroy() softDelete() rehabilitate() > i.e. request.body: { **\_docs**: [{name: 'newDoc#1'}, {name: 'newDoc#2'}] } **runUpdateTransaction:`Boolean`** - default: false > If you run into the issue of old return values after edit and your db is running a replica set or sharded cluster, try enabling this option. > It wraps the update and find calls in their own session and transaction to ensure updates are made before read **runUpdateValidators:`Boolean`** - default: true > enables schema validation on the following mongoose update methods > 'findOneAndUpdate', 'updateMany', 'updateOne', 'update' **softDelete:`Boolean`** - default: false > disabled by default > If enabled it adds softDelete methods to Schema and helpers **softDeleteOptions:`Object`** > Is only necessary if softDelete = true **softDeleteOptions.overrideMethods:`Boolean`** - default: true > this value will always be true when softDelete is enabled > **find()** **findOne()** **count()** are strictly necessary to be overridden for mongoose-bread to work properly **softDeleteOptions.validateBeforeDelete:`Boolean`** - default: true > run Schema validators before deletion **softDeleteOptions.indexFields:`Boolean`** - default: true > creates indicies for > 'deleted' > and 'deletedAt' (if softDeleteOptions.deletedAt = true) > and 'deletedBy' (if softDeleteOptions.deletedBy = true) **softDeleteOptions.deletedAt:`Boolean`** - default: true > if true adds field 'deletedAt':Date to Schema **softDeleteOptions.deletedBy:`Boolean`** - default: false > if true adds field 'deletedBy':`ObjectId` to Schema > Must be used in combination with requestUserIdPath to work **softDeleteOptions.requestUserIdPath:`String`** - default: '' > If deletedBy is set to true provide a path to extract the id of a **User** from the request object > i.e. requestUserIdPath = 'auth.user.\_id' -> request.auth.user.\_id > This path must resolve a ObjectId For options inherited from mongoose-paginate-v2 consult the [Documentation](https://github.com/aravindnc/mongoose-paginate-v2#modelpaginatequery-options-callback) ## Set Global Options > If you're using VSCode the use of "bread" snippet "global Options" for quick setup of common options is recommended Snippet "global Options" Output: ```js /* use in server|main|index.js */ // set global mongoose-bread options const { mongooseBread } = require("mongoose-bread"); mongooseBread.options = { defaultPageSize: 10, // limits queries to return 10 documents - default: 10 maxPageSize: 100, // limits queries to return 100 documents max - default: 100 paramsIdKey: "id", // expected request.params.id to identify a single Resource - default: id // i.e. https://test.org/books/6478d57784fabdbf127d0a2a // => router.get(books/:id, BookController.read) // => request.params.id = 6478d57784fabdbf127d0a2a bulkIdsKey: "_ids", // expected request.body._ids - default: '_ids' // Used for bulk edit|add|destroy|softDelete|rehabilitate bulkDocsKey: "_docs", // expected request.body._docs with Array<any> - default: _docs // Used for bulk|edit|add // => request.body: { _docs: [{name: 'newDoc#1'}, {name: 'newDoc#2'}] } allowDiskUse: false, // allow MongoDB queries to use more than 100 MB - default: false customLabels: { // optional - set custom keys for results docs: "docs", // default: 'docs' meta: "pagination", // default: 'pagination' limit: "limit", // default: 'limit' page: "page", // default: 'page' pagingCounter: "pagingCounter", // default: 'pagingCounter' hasNextPage: "hasNextPage", // default: 'hasNextPage' hasPrevPage: "hasPrevPage", // default: 'hasPrevPage' nextPage: "nextPage", // default: 'nextPage' prevPage: "prevPage", // default: 'prevPage' totalDocs: "totalDocs", // default: 'totalDocs' totalPages: "totalPages", // default: 'totalPages' acknowledged: "acknowledged", // default: 'acknowledged' modifiedCount: "modifiedCount", // default: 'modifiedCount' deletedCount: "deletedCount", // default: 'deletedCount' createdCount: "createdCount", // default: 'createdCount' readCount: "readCount", // default: 'readCount' }, }; ``` ## Set Schema Options > If you're using VSCode the use of "bread" snippets "Model" or "softDelete Model" for quick setup of common options is recommended Snippet "Model" Output: ```js const mongoose = require("mongoose"); const bread = require("mongoose-bread"); const resourceSchema = new mongoose.Schema( { name: String, }, { timestamps: true, } ); resourceSchema.plugin(bread, { /* lean gets query results as plain js objects - can improve query speed */ // lean: false, // default: false // leanWithId: false, // default: false // leanWithout_id: false, // default: false /* if searchableFields is ommited search will be disabled for resource */ searchableFields: ["name"], /* exclude blacklistedFields from all query results */ blacklistedFields: ["__v", "createdAt", "updatedAt"], }); module.exports = mongoose.model("resource", resourceSchema); ``` Snippet "softDelete Model" Output: ```js const mongoose = require("mongoose"); const bread = require("mongoose-bread"); const resourceSchema = new mongoose.Schema( { name: String, }, { timestamps: true, } ); resourceSchema.plugin(bread, { /* lean gets query results as plain js objects - can improve query speed */ // lean: false, // default: false // leanWithId: false, // default: false // leanWithout_id: false, // default: false /* if searchableFields is ommited search will be disabled for resource */ searchableFields: ["name"], /* exclude blacklistedFields from all query results */ blacklistedFields: [ "__v", "deleted", "deletedAt", "deletedBy", "createdAt", "updatedAt", ], /* enables softDelete */ softDelete: true, softDeleteOptions: { deletedAt: true, // default: true deletedBy: true, // default: false requestUserIdPath: "auth.user.id", // default: '' }, }); module.exports = mongoose.model("resource", resourceSchema); ``` ## Reserved Options These are internally used Options. These will be set by the Resource.helper() methods. They can be overridden **after** a call to a helper method to force specific values. - customCount - query - offset - page - limit - sort - select - projection - collation - populate ### Explanation **customCount:'count'|'countDeleted'|'countWithDeleted'** > used for SoftDelete **query:`Object`** > contains the MongoDB query > heavily used by helper() methods **offset:`Number`** > "page" is the mongoose-bread way to to select a subset of documents. > "offset" takes precedence over "page" so it is available for hard overrides if needed. > Use offset or page exclusively **page:`Number`** > mongoose-bread intended way to to select a subset of documents. > if not set "page" will default to 1 **limit:`Number`** > if not set limit will be set to "defaultPageSize" by mongoose-bread helper() and is limited to a maximum value of options.maxPageSize **sort:`Object`|Array\<String>** > Determines sorting of a collection > i.e. "sort"='-name \_id' sorts results descending by name then ascending by \_id > sort as object: "sort"={ name: -1, \_id: 1 } **select:`Object`|String** > the fields to in- or exclude from resulting documents > 📢 if the "blacklistedFields" is set "select" only allows excluding of fields > To exclude fields preceed their names with "-" > "select"='-balance -creditscore' will exclude "balance" and "creditscore" from queried documents > It is recommended to define only exclusion of fields **projection:`Object`|String** > see: [Projection Documentation](<https://mongoosejs.com/docs/api/query.html#Query.prototype.projection()>) > used by "blacklistedFields" option to exclude fields from documents **collation:`Object`|String** > see: [Collation Documentation](<https://mongoosejs.com/docs/api/aggregate.html#Aggregate.prototype.collation()>) > Used for aggregations, which mongoose-bread is not build around > mongoose-bread may behave unexpected when "collation" is set **populate:`Object`|String** > see: [Populate Documentation](<https://mongoosejs.com/docs/api/query.html#Query.prototype.populate()>) > **String** `'bestFriend'` populates > `User.schema.bestFriend{ type:Schema.Types.ObjectId, ref:'User' }` > **String** `'friends.friend'` populates collection > `User.schema.friends[{ friend:{ type: Schema.Types.ObjectId, ref:'User' }}]` > **Array\<String>** `['bestFriend', 'friends.friend']` populates both > **Object** `{path: 'bestFriend'}` populates > `User.schema.bestFriend{ type:Schema.Types.ObjectId, ref:'User' }` > **Object** `{path: 'friends.friend'}` populates collection > `User.schema.friends[{friend:{type: Schema.Types.ObjectId, ref:'User'}}]` > **Array\<Object>** `[{path: 'bestFriend'}, {path: 'friends.friend'}]` populates both **options:`Object`** > 🚩 **NEVER USE THIS** > mongoose-bread will delete the **options** property within the helper() methods because it leads to infinite loop in mongoose&#8209;paginate&#8209;v2 pagination helper and by doings so avoids "Maximum Call Stack Size Exceeded" Error > inherited from mongoose-paginate-v2 - kept for documenting its strange behavior see: mongoose-paginate-v2 [Documentation](https://github.com/aravindnc/mongoose-paginate-v2#modelpaginatequery-options-callback) ## Advanced Options Sets read preferences for MongoDB Below are some references to understand more about preferences, - <https://github.com/Automattic/mongoose/blob/master/lib/query.js#L1008> - <https://docs.mongodb.com/manual/core/read-preference/> - <http://mongodb.github.io/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences> **read:`Object`** > Determines the MongoDB nodes from which to read > [Documentation](<https://mongoosejs.com/docs/api/query.html#Query.prototype.read()>) **read.pref:`'primary'|'p'|'primaryPreferred'|'pp'|'secondary'|'s'|'secondaryPreferred'|'sp'|'nearest'|'n'`** > [Documentation](<https://mongoosejs.com/docs/api/query.html#Query.prototype.read()>) **read.tags:`Array<Object>`** > optional Array of tags for the query > example from documentation: [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }] > [Documentation](<https://mongoosejs.com/docs/api/query.html#Query.prototype.read()>)