npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

mongo-odm

v1.1.10

Published

Mongo ODB client

Readme

Build Status Coverage Status

Mongo ODM

A typescript ODM based on native node.js Mongo library.

Installation

npm install --save mong-odm

// or

yarn add mongo-odm

Model

@Collection()
export class User extends BaseDocument {

  @Property()
  public _id: ObjectID;

  @Property()
  public fullName: string;

  // When you specify `referencedField` then it means you don't own the join property
  @OneToMany({targetDocument: 'Log', referencedField: 'user'})
  public log: Log[];

  @OneToOne({targetDocument: 'Car', referencedField: 'user'})
  public car: Car;

  // If you don't specify `referencedField` it means you own the the reference IDs - you have array of address ids in your collection
  @OneToMany({targetDocument: 'Address'})
  public addresses: Address;

}

You can set different collection name by collectionName property in decorator

@Collection({collectionName: 'a-name'})

Script auto generates lisp-case (kebab-case) for any name automatically

class UserAddress extends ... => collection name 'user-address'

CRUD

First of all you need to create instance of Document Manager

// database.ts
// Default is localhost
const documentManager = DocumentManager.create({
   database: 'mongo-odm',
   documentsDir: './dist/documents' // Documents dir must point dist one
});

// You can also specify own url in options for replica set and another parameters (like http auth.)
{
  url: 'mongodb://node1,node2:27889,node3/?replicaSet=rs0'
}

It is recommended to create all repositories and export them from the database.ts as follows:

export const userRepository = documentManager.getRepository<User>(User);
export const logRepository = documentManager.getRepository<Log>(Log);
export const ... = documentManager.getRepository<...>(...);

You don't need to get instance of repository from document manager again and just import it where it is needed.

Create

const user = await userRepository.create(new User({fullName: "Pepa Voprsalek"));
const user2 = new User();
user2.fullName = "another user";
await userRepository.create(user2);

// You can also send there plain object, after create you will get proper object based by repository
const userInstance = await userRepository.create({fullName: 'another fullname'});
console.log(userInstance._id);

After create you will get assigned _id to you object from query result

Retrieve

All find methods return complete model with all private fields and model methods

const user1 = await userRepository.findOneBy({fullName: 'Foo bar'});
const user2 = await userRepository.findOneById('2312ba029fec9223...');
const users = await userRepository.findBy({'fullName': '....'});

Populate

const user = await userRepository.findOneBy({...}, ['log']);
// If log is @OneToMany you can access as usual -> user.log[0].eventType

Update

// By string id
userRepository.update('52acfac010e110a0..', { fullName: "new fullName"});

// By ObjectId
userRepository.update(ObjectId(...), { fullName: "new fullName"});

// By model
const user = await userRepository.find(...);
userRepository.update(user, { fullName: "new fullName"});

// By model changed directly without object with changes - repository will calculate changes itself
const user = await userRepository.find(...);
user.fullName = 'new fullName';
userRepository.update(user);

Also you can update a document by where:

userRepository.updateOneBy({fullName: 'old fullname'}, { fullName: 'new fullName'});

Delete

// By string id
userRepository.delete('52acfac010e110a0..');

// By ObjectId
const userId = new ObjectID('52acfac010e110a0..'):
userRepository.delete(userId);

// By model
const user = await userRepository.find({...});
userRepository.delete(user);

Also you can delete a document by where:

userRepository.deleteOneBy({fullName: 'some filter value'});

Count

const usersCount = await userRepository.count();

// With where
const youngUserCount = await userRepository.count({age: 29');

Sum

const totalAgeOfAllUsers = await userRepository.sum('age');

// With where
const sum = await userRepository.sum('age', {age: { $gt: 30}}');

Aggregate

const cursor = await aggregationRepository.aggregate([{
  $group: {_id: null, sum: {$sum: '$someNumber'}}
}]);

cursor.next((err: any, row: any) => {
  if (err) {
    throw err;
  }

  // row.sum === 20
});

Custom repository

You can specify your own class for a type

# custom-repository.ts
import { BaseDocument, Repository } from '../../lib';
import { FindOneOptions } from 'mongodb';

export class UserRepository<T extends BaseDocument> extends Repository<T> {

  public async findOneBy(where: any = {}, populate: string[] = [], options: FindOneOptions = {}): Promise<T | null> {
    const user = (await super.findOneBy(where, populate, options) as any);
    if (user) {
      // i.e. LOG WE FOUND THE USER
    }

    return something;
  }

}

# user.ts
@Collection({customRepository: UserRepository})
export class User {
  ...
}

Hooks

We support all pre/post create/update/delete hooks. They need decorator as follows:

  • @PreCreate
  • @PostCreate
  • @PreUpdate
  • @PostUpdate
  • @PreDelete
  • @PostDelete

All hooks are applied on every object found during all operations of find, update, delete excluding native commands.

class User extends BaseDocument {

  @PreCreate()
  preCreate() {
    this.createdAt = new Date();
  }

  @PostCreate()
  postCreate() {
    elasticSearch.put(....);
  }

  @PreUpdate()
  preUpdate() {
    this.updatedAt = new Date();
  }


  @PostUpdate()
  postUpdate() {
     logger.log('Updated ID:' + this._id);
  }

  @PostDelete()
  postDelete() {
    imageRepository.removeFromFileSystem(this)
  }

}

You can have as many hooks as you need as


@PostCreate()
logAfterCreate() {
  // logging stuff
}

@PostCreate()
doAnotherThings() {
  // another amazing stuff
}

Future

  • validations
  • field name translation (custom db fields)
  • possibility to specify where in @OneToOne or @OneToMany
  • lazy loading on @OneToOne and @OneToMany...?