docs/versioned_docs/version-7.0/usage-with-mongo.md
To use MikroORM with mongo database, do not forget to install @mikro-orm/mongodb dependency. Then call MikroORM.init() as part of bootstrapping your app:
To access driver specific methods like
em.aggregate()you need to specify the driver type when callingMikroORM.init<D>(). Alternatively you can cast theorm.emtoEntityManagerexported from the driver package:tsimport { EntityManager } from '@mikro-orm/mongodb'; const em = orm.em as EntityManager; const qb = em.aggregate(...);
You need to use
clientUrlto set up hosts, usinghostorportis not supported.
import { MikroORM } from '@mikro-orm/mongodb'; // or any other driver package
const orm = await MikroORM.init({
entities: [Author, Book, ...],
dbName: 'my-db-name',
clientUrl: '...',
});
console.log(orm.em); // access EntityManager via `em` property
When defining entity, do not forget to define primary key like this:
@PrimaryKey()
_id: ObjectId;
@SerializedPrimaryKey()
id!: string; // won't be saved in the database
Only
_id: ObjectIdwill be saved in the database.id: stringis virtual and is also optional.
Every entity has both ObjectId and string id available, also all methods of EntityManager and EntityRepository supports querying by both of them.
const author = 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);
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) });
As opposed to SQL drivers that use pivot tables, in mongo we can leverage available array type to store array of collection items (identifiers). This approach has two main benefits:
MongoDB driver supports transactions. To use transactions, there are several things you need to respect:
implicitTransactions: true to enable them globallyem.transactional()orm.schema.create() method to do so# first create replica set
$ run-rs -v 4.2.3
// make sure to import from the MongoDriver package
import { MikroORM } from '@mikro-orm/mongodb';
const orm = await MikroORM.init({
entities: [Author, Book, ...],
clientUrl: 'mongodb://localhost:27017,localhost:27018,localhost:27019/my-db-name?replicaSet=rs0',
implicitTransactions: true, // defaults to false
});
await orm.schema.create();
MongoDB driver supports indexes and unique constraints. You can use @Index() and @Unique() as described in Defining Entities section. To automatically create new indexes when initializing the ORM, you need to enable ensureIndexes option.
const orm = await MikroORM.init({
entities: [Author, Book, ...],
dbName: 'my-db-name',
ensureIndexes: true, // defaults to false
});
Alternatively you can call ensureIndexes() method on the SchemaGenerator:
SchemaGenerator is also supported for MongoDB.
await orm.schema.ensureIndexes();
You can pass additional index/unique options via options parameter:
@Unique({ options: { partialFilterExpression: { name: { $exists: true } } }})
You can also create text indexes by passing type parameter:
@Index({ properties: ['name', 'caption'], type: 'text' })
If you provide only options in the index definition, it will be used as is, this allows to define any kind of index:
@Index({ options: { point: '2dsphere', title: -1 } })
To set index weights, you can pass a tuple to the options parameter:
@Index({ options: [
{ title: 'text', perex: 'text', key: 1 },
{ weights: { title: 10, perex: 5 } },
] })
Sometimes you need to perform some bulk operation, or you just want to populate your database with initial fixtures. Using ORM for such operations can bring unnecessary boilerplate code. In this case, you can use one of insert/nativeUpdate/nativeDelete methods:
em.insert<T extends AnyEntity>(entityName: string, data: any): Promise<IPrimaryKey>;
em.nativeUpdate<T extends AnyEntity>(entityName: string, where: FilterQuery<T>, data: any): Promise<number>;
em.nativeDelete<T extends AnyEntity>(entityName: string, where: FilterQuery<T> | any): Promise<number>;
Those methods execute native driver methods like Mongo's insertOne/updateMany/deleteMany collection methods respectively. This is common interface for all drivers, so for MySQL driver, it will fire native SQL queries. Keep in mind that they do not hydrate results to entities, and they do not trigger lifecycle hooks.
They are also available as EntityRepository shortcuts:
EntityRepository.insert(data: any): Promise<IPrimaryKey>;
EntityRepository.nativeUpdate(where: FilterQuery<T>, data: any): Promise<number>;
EntityRepository.nativeDelete(where: FilterQuery<T> | any): Promise<number>;
There is also shortcut for calling aggregate method:
em.aggregate(entityName: string, pipeline: any[]): Promise<any[]>;
EntityRepository.aggregate(pipeline: any[]): Promise<any[]>;
You can pass MongoDB-specific query options to em.find() and em.count():
Controls string comparison rules for both filtering and sorting. Pass a CollationOptions object — in MongoDB, collation applies to the entire query operation, affecting both WHERE conditions and ORDER BY:
// Case-insensitive find and sort
const users = await em.find(User, { name: 'john' }, {
collation: { locale: 'en', strength: 2 },
orderBy: { name: QueryOrder.ASC },
});
Pass a string (index name) or object (index spec) to the native hint option:
const users = await em.find(User, {}, {
indexHint: 'name_1',
});
// or with index spec
const users = await em.find(User, {}, {
indexHint: { name: 1 },
});
maxTimeMS and allowDiskUseconst users = await em.find(User, {}, {
maxTimeMS: 5000, // query timeout in milliseconds
allowDiskUse: true, // allow disk use for large sorts
});
The
collation,indexHint, andmaxTimeMSoptions also work withem.count(). TheallowDiskUseoption is only available forem.find().