Skip to content

Repository files navigation

This repository is no longer maintained. Check Ship.

Node Mongo

npm version

Node Mongo is reactive extension to MongoDB API.

Features

  • ️️Reactive. Fires events as document stored, updated or deleted from database
  • Paging. Implements high level paging API
  • Schema validation. Validates your data before save

Installation

npm i @paralect/node-mongo

Documentation

Migrate from v2 to v3

  1. Methods updateOne and updateMany were removed. You should use update to perform update of single document, matched by a query. There is no replacement for updateMany, normally you should just perform multiple individual updates.
  2. service.count() renamed into service.countDocuments to match MongoDB driver.
  3. Use service.atomic.updateMany instead service.atomic.update to match MongoDB.
  4. service.aggregate() now returns cursor instead of list of documents. You can add toArray()
  5. Service accepts schema object instead of validateSchema method.

Connect

Usually, you need to define a file called database is does two things:

  1. Creates database instance and connects to the database
  2. Exposed factory method createService to create different services to work with MongoDB.
importconfigfrom'config';import{Database,Service,ServiceOptions}from'@paralect/node-mongo';constconnectionString='mongodb://localhost:27017';constdbName='home-db';constdatabase=newDatabase(connectionString,dbName);database.connect();// Extended service can be used here.functioncreateService<T>(collectionName: string,options: ServiceOptions={}){returnnewService<T>(collectionName,database,options);}exportdefault{
database,
createService,};

See how to add additional functionality to base serivce

Schema validation

constJoi=require('Joi');constuserSchema=Joi.object({_id: Joi.string(),createdOn: Joi.date(),updatedOn: Joi.date(),deletedOn: Joi.date(),name: Joi.string(),status: Joi.string().valid('active','inactive'),});// Pass schema object to enable schema validationconstuserService=db.createService('users',{schema: userSchema});

Extend

The whole idea is to import service and extend it with custom methods:

import{Service}from'@paralect/node-mongo';classCustomService<T>extendsService<T>{createOrUpdate=async(query: any,updateCallback: (item?: T)=>Partial<T>)=>{constdocExists=awaitthis.exists(query);if(!docExists){constnewDoc=updateCallback();returnthis.create(newDoc);}returnthis.update(query,doc=>{returnupdateCallback(doc);});};}exportdefaultCustomService;

Query data

// find one documentconstuser=awaituserService.findOne({name: 'Bob'});// find many documents with paginationconst{results, pagesCount, count }=awaituserService.find({name: 'Bob'},{page: 1,perPage: 30},);

Create or update data (and publish CUD events)

The key difference of the @paralect/node-mongo sdk is that every create, update or remove operation peforms an udpate and also publeshes CUD event. Events are used to easily update denormalized data and also to implement complex business logic without tight coupling of different entities.

  • Reactive updates (every update publishes event)
    • create — create one or many documents, publishes document.created event
    • update — update one document, publishes document.updated event
    • remove — remove document, publishes document.removed
    • removeSoft — set deleteOn field and publish document.removed event

Atomic udpates do not publish events and usually used to update denormalized data. Most the time you should be using reactive updates.

  • Atomic updates (events are not published)
    • atomic.deleteMany
    • atomic.insertMany
    • atomic.updateMany
    • findOneAndUpdate

API Reference V2.

create

constusers=awaituserService.create([{name: 'Alex'},{name: 'Bob'},]);

update

Update using callback function:

constupdatedUser=awaituserService.update({_id: '1'},(doc)=>{doc.name='Alex';});

Update by returning fields you need to update:

constupdatedUser=awaituserService.update({_id: '1'},()=>({name: 'Alex'}));

remove

constremovedUser=awaituserService.remove({_id: '1'});

removeSoft

constremovedUser=awaituserService.removeSoft({_id: '1'});

Event handlers

SDK support two kind of events:

  • in memory events (published by default), can be lost on service failure, work out of the box.
  • transactional events guarantee that every database write will also produce an event. Transactional events can be enabled by setting { outbox: true } when creating service. Transactional events require additonal infrastructure components.

To subscribe to the in memory events you can just do following:

import{inMemoryEventBus,InMemoryEvent}from'@paralect/node-mongo';typeUserCreatedType=InMemoryEvent<any>;typeUserUpdatedType=InMemoryEvent<any>;typeUserRemovedType=InMemoryEvent<any>;inMemoryEventBus.on('user.created',(doc: UserCreatedType)=>{});inMemoryEventBus.on('user.updated',(doc: UserUpdatedType)=>{});inMemoryEventBus.on('user.removed',(doc: UserRemovedType)=>{});

Change Log

This project adheres to Semantic Versioning.

Every release is documented on the Github Releases page.

About

Node Mongo — is reactive 🚀 extension to MongoDB API

Topics

Resources

Stars

21 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages