Mongoless
Elegant MongoDB driver for Node.js.
Installation
$ npm i mongoless --save
Usage
const Mongoless = const mongoless = mongoless// const mongoless = new Mongoless('mongodb://localhost:27017/test') const User = mongoless User
Or use optional schema:
const Mongoless = const Schema = MongolessSchemaconst mongoless = 'mongodb://admin:123456@localhost:27017/admin' dbName: 'testdb' const UserSchema = 'UserSchema' name: type: 'string' required: true age: type: 'number' default: 18 const User = mongoless /*equal to:const User = mongoless.model('User', { name: { type: 'string', required: true }, age: { type: 'number', default: 18 }})will create inner schema named `UserSchema`.*/ User /*{ TypeError: ($.age: "wrong age") ✖ (type: number) at Model.insertOne (/Users/nswbmw/Desktop/test/node_modules/mongoless/lib/query.js:101:16) at Object.<anonymous> (/Users/nswbmw/Desktop/test/app.js:21:4) at Module._compile (module.js:635:30) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module.js:497:12) at Function.Module._load (module.js:489:3) at Function.Module.runMain (module.js:676:10) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:608:3 validator: 'type', path: '$.age', actual: 'wrong age', expected: { type: 'number', default: 18 }, schema: 'UserSchema', model: 'User', op: 'insertOne', args: [ { name: 'nswbmw', age: 'wrong age' } ], pluginName: 'MongolessSchema', pluginOp: 'beforeInsertOne', pluginArgs: [] }*/
ObjectId schema:
'use strict' const Mongoless = const mongoless = 'mongodb://localhost:27017/test' const Post = mongoless Post /*[ { _id: 57caed24ecda6ffb15962591, author: 111111111111111111111111 } ] */
NB: You can pass collName
as collection name.
API
Same as node-mongodb-native.
Mongoless vs Mongoose
I've been using Mongoose for years, it's great but complex sucks, so i wrote Mongoless. Mongoless is not simply mimicking Mongoose, but rather draw on the advantages of mongoose redesigned the architecture. Mongoless has some exciting features different from Mongoose:
- Pure Schema. In Mongoose, Schema and Model and Entity are confused.
Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware.
In Mongoless, Schema is only used for defining the structure of your document and casting of properties, Model used for retrievaling data from mongodb and register plugins, Entity(as result) is plain object. Schema is also optional.
- Awesome plugin system. Mongoose plugin system is not strong enough, eg:
.pre
,.post
, use asyncnext()
. In Mongoless, we can register a plugin for Model or global mongoless instance. like:
User
Above added two hook functions for User
, when User.find().xx().exec()
is called, the execution order is as follows:
beforeFind(handle query args) -> retrieve data from mongodb -> afterFind(handle query result)
Mongoless's plugins could be substituted for Mongoose's (document instance methods + static Model methods + plugins).
- Detailed error informations. see usage.
User /*{ TypeError: ($.age: "wrong age") ✖ (type: number) at Model.insertOne (/Users/nswbmw/Desktop/test/node_modules/mongoless/lib/query.js:105:16) at Object.<anonymous> (/Users/nswbmw/Desktop/test/app.js:23:4) at Module._compile (module.js:573:30) at Object.Module._extensions..js (module.js:584:10) at Module.load (module.js:507:32) at tryModuleLoad (module.js:470:12) at Function.Module._load (module.js:462:3) at Function.Module.runMain (module.js:609:10) at startup (bootstrap_node.js:158:16) at bootstrap_node.js:598:3 validator: 'type', actual: 'wrong age', expected: { type: 'number' }, path: '$.age', schema: 'UserSchema', model: 'User', op: 'insertOne', args: [ { name: 'nswbmw', age: 'wrong age' } ], pluginName: 'MongolessSchema', pluginOp: 'beforeInsertOne', pluginArgs: [] }*/
According to the error instance, esay to know age
expect a number but got a string, from error stack know it's broken on app.js:23:4
and the operator is Model.insertOne
.
Schema
see another-json-schema, support default
and required
.
required
const Mongoless = const mongoless = 'mongodb://localhost:27017/test' const User = mongoless ; { await User}
Output:
TypeError: $name: undefined ✖ required: true at Model at /Users/nswbmw/Desktop/test/appjs:10:14 at Object<anonymous> /Users/nswbmw/Desktop/test/appjs:11:3 at Module at ObjectModule_extensions at Module at at FunctionModule at FunctionModule at validator: 'required' path: '$.name' actual: undefined expected: type: 'string' required: true schema: 'UserSchema' model: 'User' op: 'insert' args: age: 17 pluginName: 'MongolessSchema' pluginOp: 'beforeInsert' pluginArgs:
default
const Mongoless = const mongoless = 'mongodb://localhost:27017/test' const User = mongoless ; { await User const user = await User console // { _id: 5a530c5d39d9a4eb3aa57856, name: 'nswbmw', age: 18, createdAt: 2019-01-10T09:50:26.831Z }}
Types
- string
- number
- boolean
- Mongoless.Types.ObjectId
- Mongoless.Types.String
- Mongoless.Types.Number
- Mongoless.Types.Date
- Mongoless.Types.Buffer
- Mongoless.Types.Boolean
- Mongoless.Types.Mixed
What's difference between number
and Mongoless.Types.Number
?
number
only check type, Mongoless.Types.Number
will try to convert value to a number, if failed then throw error.
Plugins
mongoless// register global pluginUser// register model plugin
example:
const moment = const Mongoless = const mongoless = 'mongodb://localhost:27017/test'const User = mongoless mongoless User ; { // when use await, .exec() is omissible. await User console // { _id: 5850186544c3b82d23a82e45, // firstname: 'san', // lastname: 'zhang', // createdAt: '2016-12-13', // fullname: 'san-zhang' } console // [ { _id: 5850186544c3b82d23a82e45, // firstname: 'san', // lastname: 'zhang', // createdAt: '2016-12-13', // fullname: 'san zhang' } ]}
NOTE: Different order of calling plugins will output different results. The priority of Model's plugins is greater than global's.
example:
const Mongoless = const mongoless = 'mongodb://localhost:27017/test'const User = mongoless UserUser ; { await User console // { _id: 58501a8a7cc264af259ca691, name: '123' } console // { _id: 58501a8a7cc264af259ca691, name: '132' }}
see mongoless-plugin-populate.
Built-in plugins
Mongoless has some built-in plugins, only for find
and findOne
.
- limit
- sort
- projection(alias: select)
- fields(alias: select)
- skip
- hint
- populate
- explain
- snapshot
- timeout
- tailable
- batchSize
- returnKey
- maxScan
- min
- max
- showDiskLoc
- comment
- raw
- promoteLongs
- promoteValues
- promoteBuffers
- readPreference
- partial
- maxTimeMS
- collation
- session
example:
const Mongoless = const mongoless = 'mongodb://localhost:27017/test'const User = mongoless ; { await User await User const result = await User console // [ { _id: 58501c1281ea915a2760a2ee, name: '2' } ]}
Test
$ npm test
License
MIT