While TypeORM is primarily known as an ORM for SQL databases such as PostgreSQL, MySQL etc, it also provides excellent support for NoSQL database such as MongoDB. The great part is that the TypeORM MongoDB Integration uses similar concepts to SQL support. This makes it easy for developers to switch to MongoDB quite easily.

In this post, we will learn how to connect TypeORM to a MongoDB database. We will also look at how to insert and query records in the MongoDB database.

1 – TypeORM MongoDB Connection using DataSource

The first step is to connect MongoDB database with TypeORM. Assuming that we have a MongoDB instance up and running on localhost and default port 27017, we can configure the TypeORM datasource as below:

import "reflect-metadata"
import { DataSource } from "typeorm"
import { Tweet } from "./entity/Tweet"

export const AppDataSource = new DataSource({
    type: "mongodb",
    database: "test",
    synchronize: true,
    logging: ['query', 'error'],
    entities: [Tweet],
    migrations: [],
    subscribers: [],
})

Basically, the datasource is a configuration object that allows us to define important settings. Apart from type of database and its name, we can also supply credentials.

Note that we have one item in the entities array i.e. Tweet. We will be creating that entity in the next section.

2 – TypeORM MongoDB Entity

With the datasource configuration out of the way, we can create a TypeORM Entity. See below:

import { Entity, ObjectIdColumn, ObjectID, Column } from "typeorm"

@Entity()
export class Tweet {

    @ObjectIdColumn()
    id: ObjectID

    @Column()
    content: string

    @Column()
    userName: string
}

As you can see, we use the @Entity() decorator to tell TypeORM that Tweet is an entity. In MongoDB terms, this is equivalent to a collection. For the fields, we use @Column() decorator. However, MongoDB collections require an ObjectID as the identifier. TypeORM provides a special decorator @ObjectIdColumn() for the same. Also, the id field is of type ObjectID.

We can insert data into this particular entity as follows:

console.log("Inserting a new tweet into the database...")
const tweet = new Tweet()
tweet.content = "This is TypeORM MongoDB integration"
tweet.userName = "nick123";

await AppDataSource.manager.save(tweet)
console.log("Saved a new tweet with id: " + tweet.id)

console.log("Loading tweets from the database...")
const tweets = await AppDataSource.manager.find(Tweet)
console.log("Loaded tweets: ", tweets)

3 – TypeORM MongoDB Subdocument Handling

MongoDB has a concept of documents and subdocuments. While subdocuments form a part of a MongoDB document, we often need to declare separate entities for subdocuments to better manage our application complexity.

For the above example, let’s consider that every Tweet will have one or more replies. Also, a Tweet will have some stats like likes and retweet counters. To store such information, we will create a couple of entities as below:

import { Column } from "typeorm";

export class Reply {

    @Column()
    text: string;

    @Column()
    username: string;
}
import { Column } from "typeorm";

export class Statistics {

    @Column()
    likes: number;

    @Column()
    retweets: number;
}

Notice that we don’t need to decorate these entities with @Entity decorator. We will simply use them in the Tweet entity as separate fields and use the @Column decorator to point to them.

See below example:

import { Entity, ObjectIdColumn, ObjectID, Column } from "typeorm"
import { Reply } from "./Reply"
import { Statistics } from "./Statistics"

@Entity()
export class Tweet {

    @ObjectIdColumn()
    id: ObjectID

    @Column()
    content: string

    @Column()
    userName: string

    @Column((type) => Reply)
    replies: Reply[]

    @Column((type) => Statistics)
    statistics: Statistics;
}

Now, we can simply insert data for the complete Tweet document as below:

console.log("Inserting a new tweet into the database...")
const tweet = new Tweet()
tweet.content = "This is TypeORM MongoDB integration"
tweet.userName = "nick123";

tweet.statistics = new Statistics();
tweet.statistics.likes = 57;
tweet.statistics.retweets = 21;

const reply1 = new Reply();
reply1.text = "Looks good!"
reply1.username = "jack321"

const reply2 = new Reply();
reply2.text = "Wow, I was looking for it!"
reply2.username = "nil453"

tweet.replies = [
    reply1, reply2
]
await AppDataSource.manager.save(tweet)
console.log("Saved a new tweet with id: " + tweet.id)

console.log("Loading tweets from the database...")
const tweets = await AppDataSource.manager.find(Tweet)
console.log("Loaded tweets: ", tweets)

Upon fetching, the output would the Tweet document with the Reply and Statistics subdocument as well.

4 – Querying MongoDB Documents

Inserting documents is one part of the job. We also need to query data from these MongoDB documents. TypeORM again provides appropriate methods to achieve the same.

For example, to fetch tweets by user, we can query as below:

console.log("Loading tweets by user from database...")
const tweetByUser = await AppDataSource.manager.findBy(Tweet, {
    userName: "nick123"
})
console.log("Loaded tweets: ", tweetByUser)

Taking another example, we can also query based on a field in the subdocuments.

console.log("Query subdocuments...")
const tweetList = await AppDataSource.getMongoRepository(Tweet).find({
    where: {
        "statistics.likes": { $eq: 57 }
    }
})
console.log("Loaded tweets: ", tweetList)

Basically, here we are checking that the likes in the statistics subdocument should be equal to 57.

Conclusion

In case you are comfortable with TypeORM and don’t want to switch to Mongoose while working with MongoDB, you can continue using TypeORM. The setup for TypeORM MongoDB is not so different from other databases. Moreover, using the same ORM across your application can help increase team efficiency.

Want to learn more about TypeORM? Check out this post on Entity Relations in TypeORM.

If you have any comments or queries about this post, please feel free to mention them in the comments section below.

Categories: BlogTypeORM

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *