Use an ORM
TypeORM is an ORM that can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms, and can be used with TypeScript and JavaScript (ES2021). Unlike other current JavaScript ORMs, it supports both Active Record and Data Mapper patterns, which means you can write high-quality, loosely coupled, scalable, maintainable applications in the most productive way.
Because YugabyteDB is PostgreSQL-compatible, TypeORM supports the YugabyteDB YSQL API.
Use this guide to get started using TypeORM for connecting to YugabyteDB.
CRUD operations
The following steps demonstrate how to perform common tasks required for Node.js application development using TypeORM.
Step 1: Create a Node.js project and install TypeORM package
Before proceeding, you need to install Node.js on your machine. Refer to Downloading and installing Node.js and npm in the npm documentation.
To create a basic Node.js project and install the typeorm
package, do the following:
-
Create a new directory and initialize a Node.js project. This creates a
package.json
file.mkdir nodejs-typeorm-example && cd nodejs-typeorm-example npm init -y
-
Configure typescript by first creating a
tsconfig.json
file.npx tsc --init
-
Update the
tsconfig.json
file.{ "compilerOptions": { "target": "ES2021", "module": "CommonJS", "outDir": "./dist", "rootDir": "./src", "strict": true, "experimentalDecorators": true, "emitDecoratorMetadata": true } }
-
Install the
typeorm
package and its related dependency packages, along with typescript and the pg driver.npm install typeorm pg reflect-metadata npm install --save-dev typescript ts-node @types/node
Optional: Use YugabyteDB smart driver with TypeORM
For better features like load balancing, topology awareness, and multinode cluster support, you can use the YugabyteDB smart driver as a replacement for the PostgreSQL driver (TypeORM uses the
pg
driver under the hood):npm install typeorm reflect-metadata "pg@npm:@yugabytedb/pg" npm install --save-dev typescript ts-node @types/node
Refer to YugabyteDB Node.js smart driver documentation for more information on smart driver with Node.js.
When using the smart driver, your
package.json
dependencies section will look like the following:{ "dependencies": { "typeorm": "^0.3.17", "pg": "npm:@yugabytedb/pg", "reflect-metadata": "^0.1.13" }, "devDependencies": { "typescript": "^5.0.0", "ts-node": "^10.9.0", "@types/node": "^20.0.0" } }
Step 2: Implement ORM mapping for YugabyteDB
-
To start with TypeORM, in your project directory, create a directory
src
with the following structure:mkdir src touch src/data-source.ts touch src/index.ts mkdir src/entity touch src/entity/User.ts
-
data-source.ts
contains the credentials to connect to your database. Copy the following sample code to thedata-source.ts
file.Basic configuration:
import "reflect-metadata" import { DataSource } from "typeorm" import { User } from "./entity/User" export const AppDataSource = new DataSource({ type: "postgres", host: "localhost", port: 5433, username: "yugabyte", password: "yugabyte", database: "yugabyte", synchronize: true, logging: false, entities: [User], migrations: [], subscribers: [], })
For multi-node clusters with load balancing (YugabyteDB Smart Driver):
If you're using a multi-node YugabyteDB cluster and want to take advantage of load balancing and topology awareness, use the following configuration with the smart driver:
import "reflect-metadata" import { DataSource } from "typeorm" import { User } from "./entity/User" export const AppDataSource = new DataSource({ type: "postgres", host: "localhost", port: 5433, username: "yugabyte", password: "yugabyte", database: "yugabyte", synchronize: true, logging: false, entities: [User], migrations: [], subscribers: [], extra: { loadBalance: "true" } })
The
extra.loadBalance: "true"
option enables load balancing across multiple nodes in your YugabyteDB cluster. This configuration is only beneficial when using the YugabyteDB smart driver with a multi-node cluster setup. For single-node deployments or when not using the smart driver, you can omit this configuration and use the above one. -
Create a new entity, User, by adding the following to the
entity/User.ts
file.import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"; @Entity() export class User { @PrimaryGeneratedColumn() id!: number; @Column() firstname!: string; @Column() lastname!: string; @Column() age!: number; }
-
After the setup is done, you can connect to the database and perform the CRUD operation. In the
index.ts
file, add the following:import { AppDataSource } from "./data-source" import { User } from "./entity/User" AppDataSource.initialize().then(async () => { console.log("Inserting a new user into the database...") const user = new User() user.firstname = "Timber" user.lastname = "Saw" user.age = 25 await AppDataSource.manager.save(user) console.log("Saved a new user with id: " + user.id) console.log("Loading users from the database...") const users = await AppDataSource.manager.find(User) console.log("Loaded users: ", users) console.log("Here you can setup and run express / fastify / any other framework.") }).catch(error => console.log(error))
Run the index.ts
file:
npx ts-node src/index.ts
The following output is expected:
Inserting a new user into the database...
Saved a new user with id: 1
Loading users from the database...
Loaded users: [ User { id: 1, firstname: 'Timber', lastname: 'Saw', age: 25 } ]