import { TypeList, Tabs, TabsList, TabsTriggerVertical, TabsContent, TabsContentWrapper } from "docs-ui"

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

# {metadata.title}

In this chapter, you’ll learn about the Query utility and how to use it to fetch data from modules.

<Note type="soon" title="In Development">

Query is in development and is subject to change in future releases.

</Note>

## What is Query?

Query fetches data across modules. It’s a set of methods registered in the Medusa container under the `query` key.

In your resources, such as API routes or workflows, you can resolve Query to fetch data across custom modules and Medusa’s commerce modules.

---

## Query Example

For example, create the route `src/api/query/route.ts` with the following content:

export const exampleHighlights = [
  ["13", "", "Resolve Query from the Medusa container."],
  ["15", "graph", "Run a query to retrieve data."],
  ["16", "entity", "The name of the data model you're querying."],
  ["17", "fields", "An array of the data model’s properties to retrieve in the result."],
]

```ts title="src/api/query/route.ts" highlights={exampleHighlights} collapsibleLines="1-8" expandButtonLabel="Show Imports"
import {
  MedusaRequest,
  MedusaResponse,
} from "@medusajs/medusa"
import {
  ContainerRegistrationKeys,
} from "@medusajs/utils"

export const GET = async (
  req: MedusaRequest,
  res: MedusaResponse
) => {
  const query = req.scope.resolve(ContainerRegistrationKeys.QUERY)

  const { data: myCustoms } = await query.graph({
    entity: "my_custom",
    fields: ["id", "name"],
  })

  res.json({ my_customs: myCustoms })
}
```

In the above example, you resolve Query from the Medusa container using the `ContainerRegistrationKeys.QUERY` (`query`) key.

Then, you run a query using its `graph` method. This method accepts as a parameter an object with the following required properties:

- `entity`: The data model's name, as specified in the first parameter of the `model.define` method used for the data model's definition.
- `fields`: An array of the data model’s properties to retrieve in the result.

The method returns an object that has a `data` property, which holds an array of the retrieved data. For example:

```json title="Returned Data"
{
  "data": [
    {
      "id": "123",
      "name": "test"
    }
  ]
}
```

---

## Querying the Graph

When you use the `query.graph` method, you're running a query through an internal graph that the Medusa application creates.

This graph collects data models of all modules in your application, including commerce and custom modules, and identifies relations and links between them.

---

## Retrieve Linked Records

Retrieve the records of a linked data model by passing in `fields` the data model's name suffixed with `.*`.

For example:

```ts highlights={[["6"]]}
const { data: myCustoms } = await query.graph({
  entity: "my_custom",
  fields: [
    "id", 
    "name",
    "product.*",
  ],
})
```

<Note title="Tip">

`.*` means that all of data model's properties should be retrieved. To retrieve a specific property, replace the `*` with the property's name. For example, `product.title`.

</Note>

### Retrieve List Link Records

If the linked data model has `isList` enabled in the link definition, pass in `fields` the data model's plural name suffixed with `.*`.

For example:

```ts highlights={[["6"]]}
const { data: myCustoms } = await query.graph({
  entity: "my_custom",
  fields: [
    "id", 
    "name",
    "products.*",
  ],
})
```

---

## Apply Filters

```ts highlights={[["6"], ["7"], ["8"], ["9"]]}
const { data: myCustoms } = await query.graph({
  entity: "my_custom",
  fields: ["id", "name"],
  filters: {
    id: [
      "mc_01HWSVWR4D2XVPQ06DQ8X9K7AX",
      "mc_01HWSVWK3KYHKQEE6QGS2JC3FX",
    ],
  },
})
```

The `query.graph` function accepts a `filters` property. You can use this property to filter retrieved records.

In the example above, you filter the `my_custom` records by multiple IDs.

<Note>

Filters don't apply on fields of linked data models from other modules.

</Note>

---

## Sort Records

```ts highlights={[["5"], ["6"], ["7"]]}
const { data: myCustoms } = await query.graph({
  entity: "my_custom",
  fields: ["id", "name"],
  pagination: {
    order: {
      name: "DESC",
    },
  },
})
```

<Note>

Sorting doesn't work on fields of linked data models from other modules.

</Note>

The `graph` method's object parameter accepts a `pagination` property to configure the pagination of retrieved records.

To sort returned records, pass an `order` property to `pagination`.

The `order` property is an object whose keys are property names, and values are either:

- `ASC` to sort records by that property in ascending order.
- `DESC` to sort records by that property in descending order.

---

## Apply Pagination

```ts highlights={[["8", "skip", "The number of records to skip before fetching the results."], ["9", "take", "The number of records to fetch."]]}
const { 
  data: myCustoms,
  metadata: { count, take, skip },
} = await query.graph({
  entity: "my_custom",
  fields: ["id", "name"],
  pagination: {
    skip: 0,
    take: 10,
  },
})
```

To paginate the returned records, pass the following properties to `pagination`:

- `skip`: (required to apply pagination) The number of records to skip before fetching the results.
- `take`: The number of records to fetch.

When you provide the pagination fields, the `query.graph` method's returned object has a `metadata` property. Its value is an object having the following properties:

<TypeList types={[
  {
    name: "skip",
    type: "`number`",
    description: "The number of records skipped."
  },
  {
    name: "take",
    type: "`number`",
    description: "The number of records requested to fetch."
  },
  {
    name: "count",
    type: "`number`",
    description: "The total number of records."
  }
]} sectionTitle="Apply Pagination" />
