1.2.0 • Published 2 years ago

mongocat v1.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

Easy to use, configuration based Denormalization mongoose plugin for read heavy applications. Mongocat will reduce your write complexity too.

Installation

  • npm i mongocat

Why mongocat?

  • When a mid scale application are so read heavy and need an emergency solution.

Advantages

  • application performs well for many requests

  • easy to find, filter read operations

  • easy to setup

  • declarative approach

  • maintainability - you have to manage configuration only

  • very easy to sync

  • frequently requirement change is not nightmare here

  • Denormalize as you really need

  • Single source of truth. Third party source of document updates is easily synced by mongocat

Disadvantages

  • write operations are so slow

  • too much abstraction- denormalizable operations are hidden from business logic.

  • write operations are expensive & have to handle sensitively

  • it's behave like sql for strict mode. If foreign key doesn't exist write operation will fail. ( it's a good advantage for data consistency too )

Requirement

  • Firstly generate boilerplate & connect to database (mongodb via Mongoose ODM)

  • Mongoose version must be greater than 6.x.x

  • For existing project use mongocat-sync to migrate to denormable schema (We are working on it, it's not available yet)

  • Setup providers & consumers carefully

  • Follow linear approach, one collection can consume many denormalized data from many provider

  • A provider can consume many denormalized data from other providers too but never create big bang

  • Big bang creates when you are consuming from a collection at the same time provider denorbmalized data to that consumer too.

Documentation

Provider

import { provider } from 'mongocat';

const CategorySchema = new Schema(
  {
    title: String,
    slug: String,
    icon: String,
    status: String,
  },
  { timestamps: true }
);

CategorySchema.plugin(
  provider({
    toRef: 'Category',
    keyFields: ['title', 'slug', 'icon'],
    ignoredFields: ['status'],
  })
);

export const Category = model('Category', CategorySchema);
import { provider } from 'mongocat';

const UserSchema = new Schema(
  {
    name: String,
    username: String,
    email: String,
    status: String,
  },
  { timestamps: true }
);

UserSchema.plugin(
  provider({
    toRef: 'User',
    keyFields: ['name', 'username', 'email', 'status'],
  })
);

export const User = model('User', UserSchema);

Consumer

import { watchConsumer } from 'mongocat';

const BlogSchema = new Schema({
  title: String,
  slug: String,
  category: new Schema({
    _id: {
      type: Schema.Types.ObjectId,
      ref: 'Category',
    },
    title: String,
    slug: String,
    icon: String,
  }),
  status: Boolean,
});

BlogSchema.plugin(
  watchConsumer({
    toPath: 'category',
    key: '_id',
    strict: true,
    fromRef: 'Category',
    toRef: 'Blog',
    changeStreamEnabled: false, // sync updatesfrom third party source
  })
);

export const Blog = model('Blog', BlogSchema);

Frontend Payloads

  • Blog:

      {
         title: "Mongocat is joss",
         category: {
            _id: "62960300da98cc1aba3e9ee2"
         },
         status: true
      }
  {
     title: "Docker is joss",
     category: {
        _id: "62960300da98cc1aba3e9ee2"
     },
     tags: [
      { _id: "62960300da98cc1aba3e9ee2" },
      { _id: "62960300da98cc1aba3e9ee2" }
     ],
     status: true
  }