Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mikro-orm

Package Overview
Dependencies
Maintainers
1
Versions
3403
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mikro-orm - npm Package Compare versions

Comparing version 0.7.0 to 0.7.1

2

package.json
{
"name": "mikro-orm",
"version": "0.7.0",
"version": "0.7.1",
"description": "Simple typescript mongo ORM for node.js based on data-mapper, unit-of-work and identity-map patterns",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -13,12 +13,42 @@ # mikro-orm

## Installation & Usage
## Defining entity
Fist install the module via `yarn` or `npm`:
`$ yarn add mikro-orm`
or
`$ npm i -s mikro-orm`
Then call `MikroORM.init` as part of bootstrapping your app:
```typescript
import { BaseEntity, Entity, ManyToOne, Property } from 'mikro-orm';
import { Publisher } from './Publisher';
import { Author } from './Author';
import { BookRepository } from './BookRepository';
const orm = await MikroORM.init({
entitiesDirs: ['entities'], // relative to `baseDir`
dbName: 'my-db-name',
clientUrl: '...', // defaults to 'mongodb://localhost:27017'
baseDir: __dirname, // defaults to `process.cwd()`
});
console.log(orm.em); // EntityManager
```
@Entity({ collection: 'books-table', customRepository: BookRepository })
And do not forget to clear entity manager before each request if you do not want
to store all loaded entities in memory:
```typescript
const app = express();
app.use((req, res, next) => {
orm.em.clear();
next();
});
```
Now you can define your entities (in one of the `entitiesDirs` folders):
### Defining entity
```typescript
@Entity({ collection: 'books-table' })
export class Book extends BaseEntity {

@@ -35,11 +65,2 @@

@Property()
metaObject: object;
@Property()
metaArray: any[];
@Property()
metaArrayOfStrings: string[];
constructor(title: string, author: Author) {

@@ -49,5 +70,2 @@ super();

this.author = author;
this.metaObject = {};
this.metaArray = [{test: 123, lol: true}];
this.metaArrayOfStrings = ['test'];
}

@@ -58,25 +76,5 @@

## Installation
With your entities set up, you can start using entity manager and repositories as described
in following section. For more examples, take a look at `tests/EntityManager.test.ts`.
`$ yarn add mikro-orm`
or
`$ npm install mikro-orm`
## Usage
For more examples, take a look at `tests/EntityManager.test.ts`.
```typescript
import { MikroORM, Collection } from 'mikro-orm';
const orm = await MikroORM.init({
entitiesDirs: ['entities'], // relative to `baseDir`
dbName: 'my-db-name',
baseDir: __dirname,
});
console.log(orm.em); // EntityManager
```
## Persisting and cascading

@@ -114,5 +112,25 @@

To fetch entities from database you can use `find()` and `findOne()` of `EntityManager`.
To fetch entities from database you can use `find()` and `findOne()` of `EntityManager`:
API:
```typescript
EntityManager.getCollection(entityName: string): Collection; // returns mongodb Collection for given entity
EntityManager.getRepository<T extends BaseEntity>(entityName: string): EntityRepository<T>;
EntityManager.find<T extends BaseEntity>(entityName: string, where?: FilterQuery<T>, populate?: string[], orderBy?: { [k: string]: 1 | -1; }, limit?: number, offset?: number): Promise<T[]>;
EntityManager.findOne<T extends BaseEntity>(entityName: string, where: FilterQuery<T> | string, populate?: string[]): Promise<T>;
EntityManager.merge<T extends BaseEntity>(entityName: string, data: any): T;
EntityManager.getReference<T extends BaseEntity>(entityName: string, id: string): T;
EntityManager.remove(entityName: string, where: BaseEntity | any): Promise<number>;
EntityManager.removeEntity(entity: BaseEntity): Promise<number>;
EntityManager.count(entityName: string, where: any): Promise<number>;
EntityManager.persist(entity: BaseEntity | BaseEntity[], flush?: boolean): Promise<void>;
EntityManager.flush(): Promise<void>;
EntityManager.clear(): void;
EntityManager.canPopulate(entityName: string, property: string): boolean;
```
Example:
```typescript
const author = orm.em.findOne(Author.name, '...id...');

@@ -140,5 +158,21 @@ const books = orm.em.find(Book.name, {});

More convenient way of fetching entities from database is by using `EntityRepository`:
More convenient way of fetching entities from database is by using `EntityRepository`, that
carries the entity name so you do not have to pass it to every `find` and `findOne` calls:
API:
```typescript
EntityRepository.persist(entity: BaseEntity, flush?: boolean): Promise<void>;
EntityRepository.findOne(where: FilterQuery<BaseEntity> | string, populate?: string[]): Promise<BaseEntity>;
EntityRepository.find(where: FilterQuery<BaseEntity>, populate?: string[], orderBy?: { [k: string]: 1 | -1; }, limit?: number, offset?: number): Promise<BaseEntity[]>;
EntityRepository.findAll(populate?: string[], orderBy?: { [k: string]: 1 | -1; }, limit?: number, offset?: number): Promise<BaseEntity[]>;
EntityRepository.remove(where: BaseEntity | any): Promise<number>;
EntityRepository.flush(): Promise<void>;
EntityRepository.canPopulate(property: string): boolean;
EntityRepository.count(where?: any): Promise<number>;
```
Example:
```typescript
const booksRepository = orm.em.getRepository<Book>(Book.name);

@@ -153,6 +187,30 @@

TODO
To use custom repository, just extend `EntityRepository<T>` class:
## Identity Map
```typescript
export class CustomAuthorRepository extends EntityRepository<Author> {
// your custom methods...
public findAndUpdate(...) {
// ...
}
}
```
And register your repository as `@Entity` decorator:
```typescript
@Entity({ customRepository: CustomAuthorRepository })
export class Publisher extends BaseEntity {
// ...
}
```
Then your custom repository can be accessed via `EntityManager.getRepository()` method.
## Core features
### Identity Map
`MikroORM` uses identity map in background so you will always get the same instance of

@@ -170,4 +228,10 @@ one entity.

## Using references
If you want to clear this identity map cache, you can do so via `EntityManager.clear()` method:
```typescript
orm.em.clear();
```
### Entity references
Every single entity relation is mapped to an entity reference. Reference is an entity that has

@@ -191,4 +255,58 @@ only its identifier. This reference is stored in identity map so you will get the same object

## Collections
### Using entity constructors
Internally, `MikroORM` never calls entity constructor, so you are free to use it as you wish.
The constructor will be called only when you instantiate the class yourself via `new` operator,
so it is a handy place to require your data when creating new entity.
For example following `Book` entity definition will always require to set `title` and `author`,
but `publisher` will be optional:
```typescript
@Entity()
export class Book extends BaseEntity {
@Property()
title: string;
@ManyToOne({ entity: () => Author.name })
author: Author;
@ManyToOne({ entity: () => Publisher.name })
publisher: Publisher;
@ManyToMany({ entity: () => BookTag.name, inversedBy: 'books' })
tags: Collection<BookTag>;
constructor(title: string, author: Author) {
super();
this.title = title;
this.author = author;
}
}
```
### `ObjectID` and `string` duality
Every entity has both `ObjectID` and `string` id available, also all methods of `EntityManager`
and `EntityRepository` supports querying by both of them.
```typescript
const author = await orm.em.getReference('...id...');
console.log(author.id); // returns '...id...'
console.log(author._id); // returns ObjectID('...id...')
// all of those will return the same results
const article = '...article id...'; // string id
const book = '...book id...'; // string id
const repo = orm.em.getRepository<Author>(Author.name);
const foo1 = await repo.find({ id: { $in: [article] }, favouriteBook: book });
const bar1 = await repo.find({ id: { $in: [new ObjectID(article)] }, favouriteBook: new ObjectID(book) });
const foo2 = await repo.find({ _id: { $in: [article] }, favouriteBook: book });
const bar2 = await repo.find({ _id: { $in: [new ObjectID(article)] }, favouriteBook: new ObjectID(book) });
```
### Collections
`OneToMany` and `ManyToMany` collections are stored in a `Collection` wrapper. It implements

@@ -198,8 +316,7 @@ iterator so you can use `for of` loop to iterate through it.

```typescript
const author = orm.em.findOne(Author.name, '...');
const author = orm.em.findOne(Author.name, '...', ['books']); // populating books collection
console.log(author.name); // Jon Snow
// or we could lazy load books collection later via `init()` method
await author.books.init();
await author.books.init(); // init all books
for (const book of author.books) {

@@ -229,10 +346,82 @@ console.log(book.title); // initialized

console.log(author.books.getIdentifiers('id')); // array of string
```
### `OneToMany` collections
`OneToMany` collections are inverse side of `ManyToOne` references, to which they need to point via `fk` attribute:
```typescript
@Entity()
export class Book extends BaseEntity {
@ManyToOne({ entity: () => Author.name })
author: Author;
}
@Entity()
export class BookTag extends BaseEntity {
@OneToMany({ entity: () => Book.name, fk: 'author' })
books: Collection<Book>;
}
```
## Using entity constructors
### `ManyToMany` collections
Internally, `MikroORM` never calls entity constructor, so you are free to use it as you wish.
The constructor will be called only when you instantiate the class yourself via `new` operator.
As opposed to SQL databases, with MongoDB we do not need to have join tables for `ManyToMany` relations.
All references are stored as an array of `ObjectID`s on owning entity.
#### Unidirectional
Unidirectional `ManyToMany` relations are defined only on one side, and marked explicitly as `owner`:
```typescript
@ManyToMany({ entity: () => Book.name, owner: true })
books: Collection<Book>;
```
#### Bidirectional
Bidirectional `ManyToMany` relations are defined on both sides, while one is owning side (where references are store),
marked by `inversedBy` attribute pointing to the inverse side:
```typescript
@ManyToMany({ entity: () => BookTag.name, inversedBy: 'books' })
tags: Collection<BookTag>;
```
And on the inversed side we define it with `mappedBy` attribute poining back to the owner:
```typescript
@ManyToMany({ entity: () => Book.name, mappedBy: 'tags' })
books: Collection<Book>;
```
### Updating entity values with `BaseEntity.assign()`
When you want to update entity based on user input, you will usually have just plain
string ids of entity relations as user input. Normally you would need to use
`EntityManager.getReference()` to create references from each id first, and then
use those references to update entity relations:
```typescript
const jon = new Author('Jon Snow', 'snow@wall.st');
const book = new Book('Book', jon);
book.author = orm.em.getReference<Author>(Author.name, '...id...');
```
Same result can be easily achiever with `BaseEntity.assign()`:
```typescript
book.assign({
title: 'Better Book 1',
author: '...id...',
});
console.log(book.title); // 'Better Book 1'
console.log(book.author); // instnace of Author with id: '...id...'
console.log(book.author.id); // '...id...'
```
## TODO

@@ -248,5 +437,2 @@

- 1:M / M:1 collections
- many to many collections
- custom repository
- lifecycle hooks
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc