
A very thin TypeScript-based MongoDB helper with optional, rich ODM (Object Document Mapper) convenience features
Check out the sample full-stack project Lemon Mart Server
Check out my book Angular 6 for Enterprise-Ready Web Applications. Get it on http://AngularForEnterprise.com.
Looking to containerize MongoDB? Checkout excellalabs/mongo for a fully featured Mongo container (with Auth & SSL) inherited from the official Mongo Docker image and instructions on how to deploy it on AWS.
Major Features
-
connect()`
MongoDB async connection harness
It can be a challenge to ensure that database connectivity exists, when writing an fully async web application.
connect()
makes it easy to connect to a MongoDB instance and makes it safe to be called simultanously from multiple threads starting up at the same time. -
Document
andIDocument
Base Class and Interface to help define your own models
-
CollectionFactory
Define collections, organize indexes and aggregate queries alongside collection implementation. Below are the convenience features of a DocumentTS collection
get collection
returns the navtive MongoDB collection, so you can directly operate on it
get : ICollectionProvider<TDocument>aggregate
allows you run a MongoDB aggregation pipeline
: AggregationCursor<TDocument>findOne
andfindOneAndUpdate
simplifies the operation of commonly used database functionality, automatically hydrating the models it returns
asyncasync: Promise<TDocument | null>findWithPagination
is by far the best feature of DocumentTS, allowing you filter, sort, and paginate large collections of data. This function is geared towards use with data tables, so you specifies searchable properties, turn off hydration, and use a debug feature to fine tune your queries.
async findWithPagination<TReturnType extends IDbRecord>queryParams: Partial<IQueryParameters> & objectaggregationCursorFunc?: Func<AggregationCursor<TReturnType>>query?: string | objectsearchableProperties?: stringhydrate = truedebugQuery = false: Promise<IPaginationResult<TReturnType>>
Quick Start
Supports MongoDB v4+, Mongo Driver 3.3+ and TypeScript 3.7+
- Add DocumentTS to your project with
npm install document-ts mongodb
- Connect to your Mongo database using
connect()
- Connect will retry connecting to the database 10 times every 2 seconds
- Set
connectionRetryWait
(in seconds) andconnectionRetryMax
to modify this behavior
- Set
- Specify
isProd
andcertFileUri
to connect using an SSL certificate
{ // If isProd is set to true and a .pem file is provided, SSL will be used to connect: i.e. connect(config.mongoUri, isProd, 'server/compose-ca.pem') await }
- If you use
connect()
then you don't have to worry about having your Database Instance initialized during an asynchoronous start up sequence.getDbInstance
gives you access to the native MongoDB driver to perform custom functions like creating indexes.
// assuming this is called within an async functionawait dbInstance
- Define the interface for your first model
See
tests\user.ts
for sample Model implementation
- Define the class for your model
See
tests\user.ts
for sample Model implementation
<IUser> implements IUser static collectionName = 'users' private password: string public email: string public firstName: string public lastName: string public role: string { superUsercollectionName user } ...
- Implement
getCalculatedPropertiesToInclude()
which will ensure that yourget
properties that are "calculate" on the fly will be serialized when sending the model down to the client, but it will not be saved in the database.
: string return 'fullName'
- Implement
getPropertiesToExclude()
which will ensure that certain properties like passwords will not be serialized when sending the model down to the client, but it will still be saved in the database.
: string return 'password'
- Implement the
CollectionFactory
class, so that you can run Mongo queries without having to callgetDbInstance
or specify the collection and TypeScript type name every time you run a query. CollectionFactory provides convenience functions likefind
,findOne
,findOneAndUpdate
,findWithPagination
and similar, while also handlinghydration
tasks, such as serializing getters and child documents.
<User> { superUsercollectionName docType 'firstName' 'lastName' 'email' } let UserCollection = User
-
CollectionFactory
is powerful and flexible. In your custom class, you can implement MongoDB aggregate queries to run advance join-like queries, geo queries and whatever MongoDB supports.findWithPagination
itself is very powerful and will enable you to implement paginated dashboards with easse. -
findWithPagination
leverage query parameters for pagination and configuration
- Optionally implement
toJSON()
to customize serialization/hydration behavior or extendISerializable
{ let keys = Object return }
- Optionally implement
toBSON()
to customize database serialization behavior or extendISerializable
toBSON() {
let keys = Object.keys(this).concat(['fullAddress', 'localAddress'])
return Serialize(SerializationStrategy.BSON, this, keys)
}
- To debug the default serialization behavior, implement
{ // drop a breakpoint here or console.log(this) return super } { return super }
See the Lemon Mart Server sample project for usage - https://github.com/duluca/lemon-mart-server
Goals
- Reliable
- Rely on the rock-solid Native Node.js MongoDB drivers
- Don't inject custom code into DB calls without explicit intent by the developer
- Don't hide new MongoDB features, so you don't have to wait DocumentTS to be updated before you can use them
- Optional
- Stays out of the way, so developers can slowly transition
- If performance becomes a concern easily switch to native MongoDB calls for the best performance
- Async
- Ensure developers can write simpler and more reliable code by surfaceing promises and async/await features
- Convienient
- Developers define their own models through simple Interfaces
- Choose fields that you want to automatically hydrate, such as child or related objects
- Serialize calculated fields with every request
- Protect certain fields (like passwords) from serialization, so they aren't accidently sent across the wire
- Promote Good Patterns
- Suggest/enable easy to understand and implement patters for developers, so their code can scale and remain organized
- Prevent Bloat
- Leverage TypeScript types, interfaces, generics and inheritance to achieve development-time certainty of proper database access
- Keep the code smart, readable and lean
- Be very selective about any new features
What It Isn't
Not a full-fledged ODM or ORM replacement and doesn't aspire to be one like Mongoose or Camo. Databases are HARD. MongoDB took many years to mature, Microsoft has been trying for a really long time to build a reliable ORM with Entity Framework, Mongoose and many other ODMs are ridden with bugs (no offense) when you push them beyond the basics. It takes great resources to deliver a solid data access experience, so with DocumentTS you can developer directly against MongoDB while enjoying some conveniences as you choose.
Inspirations
Although DocumentTS doesn't aspire to replace Mongoose or Camo, it most definitely is inspired by them in the way they've solved certain problems such as hydration. Check out the source code for those projects here:
- Mongoose
- Camo
Building This Project
- Run
npm install
- Run
npm test