export const metadata = {
  title: `${pageNumber} Data Models`,
}

# {metadata.title}

In this chapter, you’ll 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. It's created in a module.

---

## How to Create a Data Model?

<Note title="Steps Summary">

1. Create a data model in a module.
2. Create migration for the data model.
4. Run migration to add the data model's table in the database.

</Note>

A data model is created in a TypeScript or JavaScript file under a module's `models` directory. It's defined using the `model` utility imported from `@medusajs/utils`.

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 { model } from "@medusajs/utils"

const MyCustom = model.define("my_custom", {
  id: model.id().primaryKey(),
  name: model.text(),
})

export default MyCustom
```

You define a data model using the `model`'s `define` method. It accepts two parameters:

1. The first one is the name of the data model's table in the database.
2. The second is an object, which is the data model's schema. The schema's properties are defined using the `model`'s methods.

The example above defines the data model `MyCustom` with the properties `id` and `name`. 

### Create a Migration

A migration defines changes to be made in the database, such as create or update tables.

A migration is a class created in a TypeScript or JavaScript file under a module's `migrations` directory. It has two methods:

- The `up` method reflects changes on the database.
- The `down` method reverts the changes made in the `up` method.

<Details summaryContent="Generate Migration">
  To generate migrations:

  1. Create the file `src/modules/hello/migrations-config.ts` with the following content:

  ```ts highlights={[["7", '"medusa-hello"', "Use any database name relevant for your module."]]}
  import { defineMikroOrmCliConfig } from "@medusajs/utils"
  import path from "path"
  import MyCustom from "./models/my-custom"

  export default defineMikroOrmCliConfig("hello", {
    entities: [MyCustom] as any[],
    migrations: {
      path: path.join(__dirname, "migrations"),
    },
  })
  ```

  2. Run the following command in the root directory of your Medusa application:

  ```bash
  npx cross-env MIKRO_ORM_CLI=./src/modules/hello/migrations-config.ts mikro-orm migration:create
  ```

  <Note title="Tip">

  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 migration file is generated under the `src/modules/hello/migrations` directory.
  
</Details>

For example:

```ts title="src/modules/migrations/Migration20240429090012.ts"
import { Migration } from "@mikro-orm/migrations"

export class Migration20240702105919 extends Migration {

  async up(): Promise<void> {
    this.addSql("create table if not exists \"my_custom\" (\"id\" text not null, \"name\" text not null, \"created_at\" timestamptz not null default now(), \"updated_at\" timestamptz not null default now(), \"deleted_at\" timestamptz 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>

### Run Migration

To reflect the changes in the migration, run the `migration` command:

```bash
npx medusa migrations run
```

If ran successfully, the `my_custom` table will be created in the database.

---

## When to Use Data Models

<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>
