mongo-odm
TypeScript icon, indicating that this package has built-in type declarations

1.1.10 • Public • Published

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...?

Readme

Keywords

none

Package Sidebar

Install

npm i mongo-odm

Weekly Downloads

0

Version

1.1.10

License

MIT

Unpacked Size

206 kB

Total Files

57

Last publish

Collaborators

  • doublemcz