node-mongo
Lightweight reactive extension to official Node.js MongoDB driver.
Features
- ObjectId mapping. Automatically converts the
_id
field from theObjectId
to astring
. - ️️Reactive. Fires events as a document created, updated, or deleted from the database;
- CUD operations timestamps. Automatically sets
createdOn
,updatedOn
, anddeletedOn
timestamps for CUD operations; - Schema validation. Validates your data before saving;
- Paging. Implements high-level paging API;
- Soft delete. By default, documents don’t remove from the collection, but are marked with the
deletedOn
field; - Extendable. API is easily extendable, you can add new methods or override existing ones;
- Outbox support. node-mongo can create collections with
_outbox
postfix that stores all CUD events for implementing the transactional outbox pattern;
The following example shows some of these features:
Installation
Connect to Database
Usually, you need to define a file called db
that does two things:
- Creates database instance and connects to the database;
- Exposes factory method
createService
to create different Services to work with MongoDB;
Services
Service is a collection wrapper that adds all node-mongo features. Under the hood it uses Node.js MongoDB native methods.
createService
method returns the service instance. It accepts two parameters: collection name and ServiceOptions.
Schema validation
Node-mongo supports any schema library, but we recommend Zod, due to this ability to generate TypeScript types from the schemas.
Zod
Joi
Node-mongo validates documents before save.
Reactivity
The key feature of the node-mongo
is that each create, update or delete operation publishes a CUD event.
${collectionName}.created
${collectionName}.updated
${collectionName}.deleted
Events are used to easily update denormalized data and also to implement complex business logic without tight coupling of different entities.
SDK support two type of events:
In-memory events
- Enabled by default;
- Events can be lost on service failure;
- Events are stored in
eventBus
(Node.js EventEmitter instance); - For handling these events type you will use Events API;
- Designed for transferring events inside a single Node.js process. Events handlers listens node-mongo
eventBus
.
Transactional events
- Can be enabled by setting
{ outbox: true }
when creating a service; - Guarantee that every database write will produce an event;
- Events are stored in special collections with
_outbox
postfix; - For handling these events type you will use
watch
(method for working with Change Streams) on the outbox table; - Designed for transferring events to messages broker like Kafka. Events handlers should listen to message broker events (You need to implement this layer yourself).
On the project start, we recommend using in-memory
events. When your application becomes tougher you should migrate to transactional
events.
Service API
find
Fetches documents that matches the filter. Returns an object with the following fields(FindResult
):
Field | Description |
---|---|
results | documents, that matches the filter |
count | total number of documents, that matches the filter |
pagesCount | total number of documents, that matches the filter divided by the number of documents per page |
Pass page
and perPage
params to get a paginated result. Otherwise, all documents will be returned.
Parameters
- filter:
Filter<T>
; - readConfig:
ReadConfig
& { page?: number; perPage?: number }
; - findOptions:
FindOptions
;
Returns Promise<FindResult<T>>
.
findOne
Fetches the first document that matches the filter. Returns null
if document was not found.
Parameters
- filter:
Filter<T>
; - readConfig:
ReadConfig
; - findOptions:
FindOptions
;
Returns Promise<T | null>
.
updateOne
Updates a single document and returns it. Returns null
if document was not found.
Parameters
- filter:
Filter<T>
; - updateFn:
(doc: T) => Partial<T>
;
Function that accepts current document and returns object containing fields to update. - updateConfig:
UpdateConfig
; - updateOptions:
UpdateOptions
;
Returns Promise<T | null>
.
updateMany
Updates multiple documents that match the query. Returns array with updated documents.
Parameters
- filter:
Filter<T>
; - updateFn:
(doc: T) => Partial<T>
;
Function that accepts current document and returns object containing fields to update. - updateConfig:
UpdateConfig
; - updateOptions:
UpdateOptions
;
Returns Promise<T[]>
.
insertOne
Inserts a single document into a collection and returns it.
Parameters
- object:
Partial<T>
; - createConfig:
CreateConfig
; - insertOneOptions:
InsertOneOptions
;
Returns Promise<T>
.
insertMany
Inserts multiple documents into a collection and returns them.
Parameters
- objects:
Partial<T>[]
; - createConfig:
CreateConfig
; - bulkWriteOptions:
BulkWriteOptions
;
Returns Promise<T[]>
.
deleteSoft
Adds deletedOn
field to the documents that match the query and returns them.
Parameters
- filter:
Filter<T>
; - deleteConfig:
DeleteConfig
; - deleteOptions:
DeleteOptions
;
Returns Promise<T[]>
.
deleteOne
Deletes a single document and returns it. Returns null
if document was not found.
Parameters
- filter:
Filter<T>
; - deleteConfig:
DeleteConfig
; - deleteOptions:
DeleteOptions
;
Returns Promise<T | null>
.
deleteMany
Deletes multiple documents that match the query. Returns array with deleted documents.
Parameters
- filter:
Filter<T>
; - deleteConfig:
DeleteConfig
; - deleteOptions:
DeleteOptions
;
Returns Promise<T[]>
.
replaceOne
Replaces a single document within the collection based on the filter. Doesn’t validate schema or publish events.
Parameters
- filter:
Filter<T>
; - replacement:
Partial<T>
; - readConfig:
ReadConfig
; - replaceOptions:
ReplaceOptions
;
Returns Promise<
UpdateResult |
Document>
.
atomic.updateOne
Updates a single document. Doesn’t validate schema or publish events.
Parameters
- filter:
Filter<T>
; - updateFilter:
UpdateFilter<T>
; - readConfig:
ReadConfig
; - updateOptions:
UpdateOptions
;
Returns Promise<
UpdateResult>
.
atomic.updateMany
Updates all documents that match the specified filter. Doesn’t validate schema or publish events.
Parameters
- filter:
Filter<T>
; - updateFilter:
UpdateFilter<T>
; - readConfig:
ReadConfig
; - updateOptions:
UpdateOptions
;
Returns Promise<
UpdateResult |
Document>
.
exists
Returns true if document exists, otherwise false.
Parameters
- filter:
Filter<T>
; - readConfig:
ReadConfig
; - findOptions:
FindOptions
;
Returns Promise<boolean>
.
countDocuments
Returns amount of documents that matches the query.
Parameters
- filter:
Filter<T>
; - readConfig:
ReadConfig
; - countDocumentOptions:
CountDocumentsOptions
;
Returns Promise<number>
.
distinct
Returns distinct values for a specified field across a single collection or view and returns the results in an array.
Parameters
- key:
string
; - filter:
Filter<T>
; - readConfig:
ReadConfig
; - distinctOptions:
DistinctOptions
;
Returns Promise<any[]>
.
aggregate
Executes an aggregation framework pipeline and returns array with aggregation result of documents.
Parameters
- pipeline:
any[]
; - options:
AggregateOptions
;
Returns Promise<any[]>
.
watch
Creates a new Change Stream, watching for new changes and returns a cursor.
Parameters
- pipeline:
Document[] | undefined
; - options:
ChangeStreamOptions
;
Returns Promise<any>
.
drop
Removes a collection from the database. The method also removes any indexes associated with the dropped collection.
Parameters
- recreate:
boolean
; Should create collection after deletion.
Returns Promise<void>
.
indexExists
Checks if one or more indexes exist on the collection, fails on first non-existing index.
Parameters
- indexes:
string | string[]
; - indexInformationOptions:
IndexInformationOptions
;
Returns Promise<string | void>
.
createIndex
Creates collection index.
Parameters
- indexSpec:
IndexSpecification
; - options:
CreateIndexesOptions
;
Returns Promise<string | void>
.
createIndexes
Creates one or more indexes on a collection.
Parameters
- indexSpecs:
IndexDescription[]
; - options:
CreateIndexesOptions
;
Returns Promise<string[] | void>
.
dropIndex
Removes the specified index from a collection.
Parameters
- indexName:
string
; - options:
DropIndexesOptions
;
Returns Promise<void | Document>
.
dropIndexes
Removes all but the _id
index from a collection.
Parameters
- options:
DropIndexesOptions
;
Returns Promise<void | Document>
.
Events API
eventBus.on
In-memory events handler that listens for a CUD events.
Parameters
- eventName:
string
;
Events names to listen.
Valid format:${collectionName}.created
,${collectionName}.updated
,${collectionName}.deleted
. - handler:
InMemoryEventHandler
;
Returns void
.
eventBus.once
In-memory events handler that listens for a CUD events. It will be called only once.
Parameters
- eventName:
string
;
Events names to listen.
Valid format:${collectionName}.created
,${collectionName}.updated
,${collectionName}.deleted
. - handler:
InMemoryEventHandler
;
Returns void
.
eventBus.onUpdated
In-memory events handler that listens for specific fields updates. It will be called when one of the provided properties
updates.
Parameters
- entity:
string
;
Collection name for events listening. - properties:
OnUpdatedProperties
;
Properties whose update will trigger the event. - handler:
InMemoryEventHandler
;
Returns void
.
Transactions API
withTransaction
Runs callbacks and automatically commits or rollbacks transaction.
Parameters
- transactionFn:
(session: ClientSession) => Promise<TRes>
;
Function that accepts a client session and manages some business logic. Must return aPromise
.
Returns Promise<TRes>
.
Options and Types
ServiceOptions
Option | Description | Default value |
---|---|---|
skipDeletedOnDocs | Skip documents with the deletedOn field | true |
schemaValidator | Validation function that will be called on data save | - |
publishEvents | Publish CUD events on save. | true |
addCreatedOnField | Set the createdOn field to the current timestamp on document creation. | true |
addUpdatedOnField | Set updateOne field to the current timestamp on the document update. | true |
outbox | Use transactional events instead of in-memory events | false |
collectionOptions | MongoDB CollectionOptions | {} |
collectionCreateOptions | MongoDB CreateCollectionOptions | {} |
CreateConfig
Overrides ServiceOptions
parameters for create operations.
ReadConfig
Overrides ServiceOptions
parameters for read operations.
UpdateConfig
Overrides ServiceOptions
parameters for update operations.
DeleteConfig
Overrides ServiceOptions
parameters for delete operations.
InMemoryEvent
InMemoryEventHandler
OnUpdatedProperties
Extending API
Extending API for a single service.
Extending API for all services.