Files
medusa-store/www/apps/book/app/basics/data-models/page.mdx
Shahed Nasser 4fe28f5a95 chore: reorganize docs apps (#7228)
* reorganize docs apps

* add README

* fix directory

* add condition for old docs
2024-05-03 17:36:38 +03:00

229 lines
7.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export const metadata = {
title: `${pageNumber} Data Models`,
}
# {metadata.title}
In this chapter, youll learn what data models are and how to create a data model.
## What is a Data Model?
A data model is a class that represents a table in the database. A data model is created in a module. You can then create a service that manages that data model.
Data models are based on [MikroORM](https://mikro-orm.io/docs/quick-start). So, you can use its decorators, types, and utilities when creating a model.
---
## How to Create a Data Model
<Note title="Steps Summary">
1. Create data model class in a module.
2. Generate migration for the data model.
3. Add migration scripts to the module's definition.
4. Run migration to add table for data model in the database.
</Note>
A data model is a class created in a TypeScript or JavaScript file created in a module under its `models` directory.
For example, create the file `src/modules/hello/models/my-custom.ts` with the following content:
```ts title="src/modules/hello/models/my-custom.ts"
import { generateEntityId } from "@medusajs/utils"
import {
BeforeCreate,
Entity,
OnInit,
PrimaryKey,
Property,
} from "@mikro-orm/core"
@Entity()
export class MyCustom {
@PrimaryKey({ columnType: "text" })
id!: string
@Property({ columnType: "text" })
name: string
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "mc")
}
@OnInit()
OnInit() {
this.id = generateEntityId(this.id, "mc")
}
}
```
This defines a new data model `MyCustom` with the fields `id` and `name`.
The `onCreate` method generates an ID for the data model's record when it's created. The `onInit` method sets the ID when the record is loaded.
<Note title="Tip">
The `generateEntityId` utility method prefixes the `id` of a record with the string provided in the second parameter. This follows Medusa's conventions of creating IDs.
</Note>
### Create a Migration
After creating the data model, you must create a migration that creates a table in your database for this data model.
A migration is a class that implements an `up` and `down` method, where the `up` method reflects changes on the database, and the `down` method reverts the changes from the database.
<Details summaryContent="Generate with MikroORM">
MikroORM provides a CLI tool that helps you generate migrations. To use it:
1. Create the file `src/modules/hello/mikro-orm.config.dev.ts` with the following content:
```ts
import "dotenv/config"
import path from "path"
import { TSMigrationGenerator } from "@medusajs/utils"
import { MyCustom } from "./models/my-custom"
module.exports = {
entities: [MyCustom],
schema: "public",
clientUrl: "postgres://postgres@localhost/medusa-hello",
type: "postgresql",
migrations: {
path: path.join(__dirname, "migrations"),
generator: TSMigrationGenerator,
},
}
```
2. Run the following command in the root directory of your Medusa application:
```bash
npx cross-env MIKRO_ORM_CLI=./src/modules/hello/mikro-orm.config.dev.ts mikro-orm migration:create
```
<Note title="Tip">
You can add this command as a script in `package.json` for easy usage in the future. Use this command whenever you want to generate a new migration in your module.
</Note>
After running the command, a new file is created under the `src/modules/hello/migrations` directory. This file holds `up` and `down` methods that define the actions to execute when running and reverting the migration respectively.
</Details>
For example:
```ts
import { Migration } from "@mikro-orm/migrations"
export class Migration20240429090012 extends Migration {
async up(): Promise<void> {
this.addSql("create table if not exists \"my_custom\" (\"id\" varchar(255) not null, \"name\" text not null, constraint \"my_custom_pkey\" primary key (\"id\"));")
}
async down(): Promise<void> {
this.addSql("drop table if exists \"my_custom\" cascade;")
}
}
```
In the `up` method, you create the table `my_custom` and define its columns. In the `down` method, you drop the table.
<Note title="Tip">
The queries performed in each of the methods use PostgreSQL syntax.
</Note>
### Add Migration to Module Definition
After creating the migration, you must add it to your module's definition. Otherwise, the Medusa application won't run it.
To add a module's migrations to its definitions, use the `ModulesSdkUtils` utility functions imported from `@medusajs/utils`. It has functions to create and define the migration scripts in your module definition.
Change the content of `src/modules/hello.index.ts` that you created in a [previous chapter](../modules-and-services/page.mdx) to the following:
```ts title="src/modules/hello.index.ts" highlights={[["2"], ["6"], ["10"], ["12"], ["14"], ["18"], ["22"], ["28"], ["36"]]}
import HelloModuleService from "./service"
// add necessary imports
import { ModulesSdkUtils } from "@medusajs/utils"
import { MyCustom } from "./models/my-custom"
// define useful constants
const moduleName = "hello"
const pathToMigrations = __dirname + "/migrations"
// assemble object to pass to utility functions
const migrationScriptOptions = {
// the module's name
moduleName,
// the data models of the modules
models: {
MyCustom,
},
// the path to the migrations directory
pathToMigrations,
}
// create and export the script that runs migrations
export const runMigrations = ModulesSdkUtils
.buildMigrationScript(
migrationScriptOptions
)
// create and export the script that reverts migrations
export const revertMigration = ModulesSdkUtils
.buildRevertMigrationScript(
migrationScriptOptions
)
export default {
service: HelloModuleService,
// add the run and revert migration scripts to the module's definition
runMigrations,
revertMigration,
}
```
After importing `ModulesSdkUtils`, you use its `buildMigrationScript` function to create the script that runs the migration, and its `buildRevertMigrationScript` function to create the script that reverts the migration.
Both the `buildMigrationScript` and `buildRevertMigrationScript` accept the same object type as a parameter, which has the following properties:
- `moduleName`: The name of the module that the migrations belong to.
- `models`: An object of the module's data models.
- `pathToMigrations`: The path to the `migrations` directory.
Both created scripts must be exported in the file and within the module's definition object.
### Run Migration
To reflect the changes in the migration, transpile your source files using the `build` command, then run the `migration` command:
```bash npm2yarn
npm run build
npx medusa migrations run
```
If ran successfully, the `my_custom` table will be created in the database.
---
## When to Use
<Note title="Use data models when" type="success">
- You want to store data related to your customization in the database.
</Note>
<Note title="Don't use data models if" type="error">
- You want to store simple key-value pairs related to an existing data model. Instead, use the `metadata` field that most existing models have, which is an object of custom key-value pairs.
</Note>