如何使用 TypeORM 种子来为数据库播种
让我们开始编码
概述
除了在应用程序原型设计过程中提供极大的便利之外,它还能在生产环境中为我们带来诸多好处。也就是说,它能够帮助我们从构思过程、应用程序创建到生产环境。
您可能已经从文章标题中注意到了这一点,或者我决定创建一篇简单的文章,其中我们使用最流行的 ORM 之一,并且我们将为我们的数据库播种。
数据库播种可以在不同的环境中完成,从插入随机批次以便我们可以更快地测试我们的应用程序(这有助于我们的开发经验),但我们也可以定义一个对象数组,这些对象可以是数据。管理员帐户或仅仅是需要在生产环境中使用的数据。
在今天的示例中,我将解释如何将随机数据插入数据库,以及如何在它们之间建立关系。最终,我们将拥有一个只有两个端点的 API:一个用于获取所有用户及其文章,另一个用于获取所有文章及其作者。
我还想补充一点,本文不会讲解如何使用 Express、TypeORM 和 TypeScript 创建 API。我只会讲解如何在现有 API 中实现数据库的种子填充。如果您想访问包含本文最终成果的 GitHub 仓库,请点击此处。
让我们开始编码
在我们的项目的根目录中(package.json 所在的位置),我们将安装以下依赖项:
npm install typeorm-seeding faker --save
npm install @types/faker --save-dev
现在我将解释我认为关于我们将要使用的库( typeorm-seeding )的两件基本的事情。
我首先要讲的是工厂。基本上,我们会为应用程序中的每个实体定义一个工厂,它负责生成填充应用程序的数据。这些数据分别对应于我们在实体中定义的属性。
因此,我们假设这些是您的实体:
// @/src/db/entities/user.ts
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToMany,
BaseEntity,
} from "typeorm";
import { Post } from "./post";
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id!: number;
@Column()
name!: string;
@OneToMany(() => Post, (post) => post.user)
posts?: Post[];
}
// @/src/db/entities/post.ts
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
BaseEntity,
} from "typeorm";
import { User } from "./user";
@Entity()
export class Post extends BaseEntity {
@PrimaryGeneratedColumn()
id!: number;
@Column()
title!: string;
@Column()
description!: string;
@Column({ type: "boolean", default: false })
isPublished!: boolean;
@ManyToOne(() => User, (user) => user.posts)
user!: User;
}
对于用户实体,我们只需要生成与该工厂对应的用户名:
// @/src/db/seeding/factories/user.factory.ts
import * as Faker from "faker";
import { define } from "typeorm-seeding";
import { User } from "../../entities";
define(User, (faker: typeof Faker) => {
const user = new User();
const firstName = faker.name.firstName();
const lastName = faker.name.lastName();
user.name = `${firstName} ${lastName}`;
return user;
});
就这篇文章而言,它应该是这样的:
// @/src/db/seeding/factories/post.factory.ts
import * as Faker from "faker";
import { define } from "typeorm-seeding";
import { Post } from "../../entities";
define(Post, (faker: typeof Faker) => {
const post = new Post();
post.title = faker.lorem.words(8);
post.description = faker.lorem.paragraph(6);
post.isPublished = faker.random.boolean();
return post;
});
现在我们的工厂已经定义好了,只要我们定义了想要创建的用户或文章的数量,工厂就会在每个属性中生成随机值。
现在我们可以转到 Seeder,seeder 是一个用于执行数据库播种的类,在这里我希望您小心名称,因为种子的名称对应于类的名称(而不是文件的名称)。
Seeder 的样板如下:
// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";
// ...
export default class InitialDatabaseSeed implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<void> {
// ...
}
}
我们首先需要做的是导入我们要播种的实体。
// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";
import { User, Post } from "../../entities";
export default class InitialDatabaseSeed implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<void> {
// ...
}
}
现在让我们先为用户表播种,并定义我们想在表中总共插入 15 个用户。
// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";
import { User, Post } from "../../entities";
export default class InitialDatabaseSeed implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<void> {
const users = await factory(User)().createMany(15);
// ...
}
}
创建用户后,我们现在要生成文章。不过,这次除了定义要生成的文章数量外,我们还需要传递必须是文章作者的用户。在本例中,我们必须以随机方式分配作者。像这样:
// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";
import { User, Post } from "../../entities";
export default class InitialDatabaseSeed implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<void> {
const users = await factory(User)().createMany(15);
await factory(Post)()
.map(async (post) => {
post.user = users[Math.floor(Math.random() * users.length)];
return post;
})
.createMany(100);
}
}
定义工厂并创建播种机后,下一步就是在 TypeORM 配置中定义工厂和播种机所在的目录。
// @/ormconfig.ts
import { User, Post } from "./src/db/entities";
export default {
name: "default",
type: "sqlite",
database: "src/db/dev.db",
entities: [User, Post],
synchronize: true,
logging: false,
// These two lines have been added:
seeds: ["src/db/seeding/seeds/**/*{.ts,.js}"],
factories: ["src/db/seeding/factories/**/*{.ts,.js}"],
};
最后,只需转到我们的package.json
并创建负责播种数据库的脚本。
// @/package.json
{
// ...
"scripts": {
// ...
"db:seed": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed"
},
// ...
}
不要忘记运行您的 API 进程并运行命令npm run db:seed
来为您的数据库提供种子。
结论
一如既往,希望你觉得这篇文章有趣。如果你发现本文有任何错误,请在评论区指出。🧑🏻💻
祝你度过美好的一天!👋 🌱
文章来源:https://dev.to/franciscomendes10866/how-to-seed-database-using-typeorm-seeding-4kd5