# Add Columns to a Link Table

In this chapter, you'll learn how to add custom columns to a link definition's table and manage them.

## Link Table's Default Columns

When you define a link between two data models, Medusa creates a link table in the database to store the IDs of the linked records. You can learn more about the created table in the [Module Links chapter](https://docs.medusajs.com/learn/fundamentals/module-links).

In various cases, you might need to store additional data in the link table. For example, if you define a link between a `product` and a `post`, you might want to store the publish date of the product's post in the link table.

In those cases, you can add a custom column to a link's table in the link definition. You can later set that column whenever you create or update a link between the linked records.

***

## How to Add Custom Columns to a Link's Table?

The `defineLink` function used to define a link accepts a third parameter, which is an object of options.

To add custom columns to a link's table, pass in the third parameter of `defineLink` a `database` property:

```ts highlights={linkHighlights}
import BlogModule from "../modules/blog"
import ProductModule from "@medusajs/medusa/product"
import { defineLink } from "@medusajs/framework/utils"

export default defineLink(
  ProductModule.linkable.product,
  BlogModule.linkable.blog,
  {
    database: {
      extraColumns: {
        metadata: {
          type: "json",
        },
      },
    },
  }
)
```

This adds to the table created for the link between `product` and `blog` a `metadata` column of type `json`.

### Database Options

The `database` property defines configuration for the table created in the database.

Its `extraColumns` property defines custom columns to create in the link's table.

`extraColumns`'s value is an object whose keys are the names of the columns, and values are the column's configurations as an object.

### Column Configurations

The column's configurations object accepts the following properties:

- `type`: The column's type. Possible values are:
  - `string`
  - `text`
  - `integer`
  - `boolean`
  - `date`
  - `time`
  - `datetime`
  - `enum`
  - `json`
  - `array`
  - `enumArray`
  - `float`
  - `double`
  - `decimal`
  - `bigint`
  - `mediumint`
  - `smallint`
  - `tinyint`
  - `blob`
  - `uuid`
  - `uint8array`
- `defaultValue`: The column's default value.
- `nullable`: Whether the column can have `null` values.

***

## Set Custom Column when Creating Link

The object you pass to Link's `create` method accepts a `data` property. Its value is an object whose keys are custom column names, and values are the value of the custom column for this link.

For example:

Refer to the [Link](https://docs.medusajs.com/learn/fundamentals/module-links/link) chapter to learn how to import and use the `link` instance.

### Link

```ts
await link.create({
  [Modules.PRODUCT]: {
    product_id: "123",
  },
  [BLOG_MODULE]: {
    post_id: "321",
  },
  data: {
    metadata: {
      test: true,
    },
  },
})
```

### createRemoteLinksStep

```ts
import { Modules } from "@medusajs/framework/utils"
import { BLOG_MODULE } from "../modules/blog"
import { createRemoteLinksStep } from "@medusajs/medusa/core-flows"
import { 
  createWorkflow,
  transform,
} from "@medusajs/framework/workflows-sdk"

export const myWorkflow = createWorkflow(
  "my-workflow",
  () => {
    // ...
    const linkData = transform({
      // TODO pass input data
    }, () => {
      return [
        {
          [Modules.PRODUCT]: {
            product_id: "123",
          },
          [BLOG_MODULE]: {
            post_id: "321",
          },
          data: {
            metadata: {
              test: true,
            },
          },
        },
      ]
    })
    createRemoteLinksStep(linkData)
    // ...
  }
)
```

***

## Retrieve Custom Column with Link

To retrieve linked records with their custom columns, use [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query). This section explores two methods to retrieve a link's custom columns.

### Method 1: Using Special Link Field

A data model will have a special field for all its link tables. The field's name is in the `{camel_case_data_model_name}_link` format, where `{camel_case_data_model_name}` is the name of the linked data model in camel case.

For example:

```ts highlights={method1Highlights}
const { data } = await query.graph({
  entity: "product",
  fields: ["id", "title", "post_link.metadata", "post.*"],
  filters: {
    id: "prod_123",
  },
})
```

In this example, you retrieve a product and the `metadata` custom column in the link table between `product` and `post` using the `post_link.metadata` field.

You can also retrieve all custom columns in the link table using the `post_link.*` field.

### Method 2: Using Entry Point

A module link's definition, exported by a file under `src/links`, has a special `entryPoint` property. Use this property when specifying the `entity` property in Query's `graph` method.

For example:

```ts highlights={retrieveHighlights}
import productPostLink from "../links/product-post"

// ...

const { data } = await query.graph({
  entity: productPostLink.entryPoint,
  fields: ["metadata", "product.*", "post.*"],
  filters: {
    product_id: "prod_123",
  },
})
```

This retrieves the product of id `prod_123` and its linked `post` records.

In the `fields` array you pass `metadata`, which is the custom column to retrieve of the link.

***

## Update Custom Column's Value

Link's `create` method updates a link's data if the link between the specified records already exists.

So, to update the value of a custom column in a created link, use the `create` method again passing it a new value for the custom column.

For example:

### Link

```ts
await link.create({
  [Modules.PRODUCT]: {
    product_id: "123",
  },
  [BLOG_MODULE]: {
    post_id: "321",
  },
  data: {
    metadata: {
      test: false,
    },
  },
})
```

### updateRemoteLinksStep

```ts
import { Modules } from "@medusajs/framework/utils"
import { BLOG_MODULE } from "../modules/blog"
import { updateRemoteLinksStep } from "@medusajs/medusa/core-flows"
import { 
  createWorkflow,
  transform,
} from "@medusajs/framework/workflows-sdk"

export const myWorkflow = createWorkflow(
  "my-workflow",
  () => {
    // ...
    const linkData = transform({
      // TODO pass input data
    }, () => {
      return [
        {
          [Modules.PRODUCT]: {
            product_id: "123",
          },
          [BLOG_MODULE]: {
            post_id: "321",
          },
          data: {
            metadata: {
              test: false,
            },
          },
        },
      ]
    })
    updateRemoteLinksStep(linkData)
    // ...
  }
)
```


---

The best way to deploy Medusa is through Medusa Cloud where you get autoscaling production infrastructure fine tuned for Medusa. Create an account by signing up at cloud.medusajs.com/signup.
