From 0bcdcccbe23ed4e32f8ab4c7c25ffd52e56f4a1f Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Mon, 16 Sep 2024 15:46:26 +0300 Subject: [PATCH] docs: update query usage across docs (#9120) WIP --- .../modules/query/page.mdx | 74 +++++++++---------- .../product/guides/price-with-taxes/page.mdx | 22 +++--- .../product/guides/price/page.mdx | 38 +++++----- .../examples/standard/page.mdx | 36 ++++----- .../examples/restaurant-delivery/page.mdx | 45 ++++++----- .../marketplace/examples/vendors/page.mdx | 24 +++--- .../subscriptions/examples/standard/page.mdx | 28 +++---- 7 files changed, 123 insertions(+), 144 deletions(-) diff --git a/www/apps/book/app/advanced-development/modules/query/page.mdx b/www/apps/book/app/advanced-development/modules/query/page.mdx index 291f798342..0b81c2e04d 100644 --- a/www/apps/book/app/advanced-development/modules/query/page.mdx +++ b/www/apps/book/app/advanced-development/modules/query/page.mdx @@ -8,9 +8,9 @@ export const metadata = { In this chapter, you’ll learn about the Query utility and how to use it to fetch data from modules. - + -Remote Query is now deprecated in favor of Query. Follow this documentation to see the difference in the usage. +Query is in development and is subject to change in future releases. @@ -29,7 +29,7 @@ For example, create the route `src/api/store/query/route.ts` with the following export const exampleHighlights = [ ["13", "", "Resolve Query from the Medusa container."], ["15", "graph", "Run a query to retrieve data."], - ["16", "entryPoint", "The name of the data model you're querying."], + ["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."], ] @@ -49,7 +49,7 @@ export const GET = async ( const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const { data: myCustoms } = await query.graph({ - entryPoint: "my_custom", + entity: "my_custom", fields: ["id", "name"], }) @@ -61,7 +61,7 @@ In the above example, you resolve Query from the Medusa container using the `Con Then, you run a query using its `graph` method. This method accepts as a parameter an object with the following required properties: -- `entryPoint`: The data model's name, as specified in the first parameter of the `model.define` method used for the data model's definition. +- `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: @@ -79,6 +79,14 @@ The method returns an object that has a `data` property, which holds an array of --- +## 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 `.*`. @@ -87,7 +95,7 @@ For example: ```ts highlights={[["6"]]} const { data: myCustoms } = await query.graph({ - entryPoint: "my_custom", + entity: "my_custom", fields: [ "id", "name", @@ -110,7 +118,7 @@ For example: ```ts highlights={[["6"]]} const { data: myCustoms } = await query.graph({ - entryPoint: "my_custom", + entity: "my_custom", fields: [ "id", "name", @@ -125,54 +133,36 @@ const { data: myCustoms } = await query.graph({ ```ts highlights={[["6"], ["7"], ["8"], ["9"]]} const { data: myCustoms } = await query.graph({ - entryPoint: "my_custom", + entity: "my_custom", fields: ["id", "name"], - variables: { - filters: { - id: [ - "mc_01HWSVWR4D2XVPQ06DQ8X9K7AX", - "mc_01HWSVWK3KYHKQEE6QGS2JC3FX", - ], - }, + 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. + Filters don't apply on fields of linked data models from other modules. -The `query.graph` function accepts a `variables` property. You can use this property to filter retrieved records. - - - --- ## Sort Records ```ts highlights={[["5"], ["6"], ["7"]]} const { data: myCustoms } = await query.graph({ - entryPoint: "my_custom", + entity: "my_custom", fields: ["id", "name"], - variables: { + pagination: { order: { name: "DESC", }, @@ -186,7 +176,9 @@ Sorting doesn't work on fields of linked data models from other modules. -To sort returned records, pass an `order` property to `variables`. +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: @@ -202,16 +194,16 @@ const { data: myCustoms, metadata: { count, take, skip }, } = await query.graph({ - entryPoint: "my_custom", + entity: "my_custom", fields: ["id", "name"], - variables: { + pagination: { skip: 0, take: 10, }, }) ``` -To paginate the returned records, pass the following properties to `variables`: +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. diff --git a/www/apps/resources/app/commerce-modules/product/guides/price-with-taxes/page.mdx b/www/apps/resources/app/commerce-modules/product/guides/price-with-taxes/page.mdx index f9e4ca444f..f475800f75 100644 --- a/www/apps/resources/app/commerce-modules/product/guides/price-with-taxes/page.mdx +++ b/www/apps/resources/app/commerce-modules/product/guides/price-with-taxes/page.mdx @@ -38,23 +38,27 @@ const taxModuleService = container.resolve( After resolving the resources, use Query to retrieve the products with the variants' prices for a context: ```ts +import { QueryContext } from "@medusajs/utils" + +// ... + const { data: products } = await query.graph({ - entryPoint: "product", + entity: "product", fields: [ "*", "variants.*", "variants.calculated_price.*", ], - variables: { - filters: { - id: "prod_123", - }, - "variants.calculated_price": { - context: { + filters: { + id: "prod_123", + }, + context: { + variants: { + calculated_price: QueryContext({ region_id: "region_123", currency_code: "usd", - }, - }, + }), + } }, }) ``` diff --git a/www/apps/resources/app/commerce-modules/product/guides/price/page.mdx b/www/apps/resources/app/commerce-modules/product/guides/price/page.mdx index 40ae204e1f..e5b5988627 100644 --- a/www/apps/resources/app/commerce-modules/product/guides/price/page.mdx +++ b/www/apps/resources/app/commerce-modules/product/guides/price/page.mdx @@ -26,18 +26,16 @@ For example: ```ts highlights={[["6"]]} const { data: products } = await query.graph({ - entryPoint: "product", + entity: "product", fields: [ "*", "variants.*", "variants.prices.*", ], - variables: { - filters: { - id: [ - "prod_123", - ], - }, + filters: { + id: [ + "prod_123", + ], }, }) ``` @@ -59,32 +57,38 @@ Learn more about prices calculation in [this Pricing Module documentation](../.. To retrieve calculated prices of variants based on a context, retrieve the products using Query and: - Pass `variants.calculated_price.*` in the `fields` property. -- Pass in the `variables` property a `variants.calculated_price` property whose value is the [calculation context object](../../../pricing/price-calculation/page.mdx#calculation-context). +- Pass a `context` property in the object parameter. Its value is an object of objects to sets the context for the retrieved fields. For example: ```ts highlights={[["6"], ["12"], ["13"], ["14"], ["15"], ["16"], ["17"]]} +import { QueryContext } from "@medusajs/utils" + +// ... + const { data: products } = await query.graph({ - entryPoint: "product", + entity: "product", fields: [ "*", "variants.*", "variants.calculated_price.*", ], - variables: { - filters: { - id: "prod_123", - }, - "variants.calculated_price": { - context: { + filters: { + id: "prod_123", + }, + context: { + variants: { + calculated_price: QueryContext({ region_id: "reg_01J3MRPDNXXXDSCC76Y6YCZARS", currency_code: "eur", - }, + }), }, }, }) ``` -The `variants.calculated_price` property of `variables` is an object that has a `context` property. `context`'s value is an object whose keys are price rules, such as `region_id`, and value is the rule's value in this context, such as the customer's region's ID. +For the context of the product variant's calculated price, you pass an object to `context` with the property `variants`, whose value is another object with the property `calculated_price`. + +`calculated_price`'s value is created using the `QueryContext` utility function, passing it a [calculation context object](../../../pricing/price-calculation/page.mdx#calculation-context). Each variant in the retrieved products has a `calculated_price` object. Learn more about its properties in [this Pricing Module guide](../../../pricing/price-calculation/page.mdx#returned-price-object). diff --git a/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx b/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx index b4c4b49ded..59c739796c 100644 --- a/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx +++ b/www/apps/resources/app/recipes/digital-products/examples/standard/page.mdx @@ -305,14 +305,14 @@ export const GET = async ( data: digitalProducts, metadata: { count, take, skip }, } = await query.graph({ - entryPoint: "digital_product", + entity: "digital_product", fields: [ "*", "medias.*", "product_variant.*", ...(fields || []), ], - variables: { + pagination: { skip: offset, take: limit, }, @@ -1858,17 +1858,15 @@ async function digitalProductOrderCreatedHandler({ ) const { data: [digitalProductOrder] } = await query.graph({ - entryPoint: "digital_product_order", + entity: "digital_product_order", fields: [ "*", "products.*", "products.medias.*", "order.*", ], - variables: { - filters: { - id: data.id, - }, + filters: { + id: data.id, }, }) @@ -2046,15 +2044,13 @@ export const GET = async ( const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const { data: [customer] } = await query.graph({ - entryPoint: "customer", + entity: "customer", fields: [ "orders.digital_product_order.products.*", "orders.digital_product_order.products.medias.*", ], - variables: { - filters: { - id: req.auth_context.actor_id, - }, + filters: { + id: req.auth_context.actor_id, }, }) @@ -2109,14 +2105,12 @@ export const POST = async ( const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const { data: [customer] } = await query.graph({ - entryPoint: "customer", + entity: "customer", fields: [ "orders.digital_product_order.*", ], - variables: { - filters: { - id: req.auth_context.actor_id, - }, + filters: { + id: req.auth_context.actor_id, }, }) @@ -2125,14 +2119,12 @@ export const POST = async ( .map((order) => order.digital_product_order.id) const { data: dpoResult } = await query.graph({ - entryPoint: "digital_product_order", + entity: "digital_product_order", fields: [ "products.medias.*", ], - variables: { - filters: { - id: customerDigitalOrderIds, - }, + filters: { + id: customerDigitalOrderIds, }, }) diff --git a/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx b/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx index ef7ec70c76..e0398f00ad 100644 --- a/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx +++ b/www/apps/resources/app/recipes/marketplace/examples/restaurant-delivery/page.mdx @@ -627,7 +627,10 @@ In the file `src/api/restaurants/route.ts` add the following API route: ```ts title="src/api/restaurants/route.ts" // other imports... import { MedusaRequest, MedusaResponse } from "@medusajs/medusa" -import { ContainerRegistrationKeys } from "@medusajs/utils" +import { + ContainerRegistrationKeys, + QueryContext +} from "@medusajs/utils" // ... @@ -637,7 +640,7 @@ export async function GET(req: MedusaRequest, res: MedusaResponse) { const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const { data: restaurants } = await query.graph({ - entryPoint: "restaurants", + entity: "restaurants", fields: [ "id", "handle", @@ -652,11 +655,13 @@ export async function GET(req: MedusaRequest, res: MedusaResponse) { "products.variants.*", "products.variants.calculated_price.*", ], - variables: { - filters: queryFilters, - "products.variants.calculated_price": { - context: { - currency_code, + filters: queryFilters, + context: { + products: { + variants: { + calculated_price: QueryContext({ + currency_code, + }) }, }, }, @@ -1690,11 +1695,9 @@ export const notifyRestaurantStep = createStep( const query = container.resolve(ContainerRegistrationKeys.QUERY) const { data: [delivery] } = await query.graph({ - entryPoint: "deliveries", - variables: { - filters: { - id: deliveryId, - }, + entity: "deliveries", + filters: { + id: deliveryId, }, fields: ["id", "restaurant.id"], }) @@ -1772,12 +1775,7 @@ export const createOrderStep = createStep( const query = container.resolve(ContainerRegistrationKeys.QUERY) const { data: [delivery] } = await query.graph({ - entryPoint: "deliveries", - variables: { - filters: { - id: deliveryId, - }, - }, + entity: "deliveries", fields: [ "id", "cart.*", @@ -1786,6 +1784,9 @@ export const createOrderStep = createStep( "cart.items.*", "cart.shipping_methods.*", ], + filters: { + id: deliveryId, + }, }) // TODO create order @@ -2601,14 +2602,12 @@ export const isDeliveryRestaurant = async ( ) const { data: [delivery] } = await query.graph({ - entryPoint: "delivery", + entity: "delivery", fields: [ "restaurant.*", ], - variables: { - filters: { - id: req.params.id, - }, + filters: { + id: req.params.id, }, }) diff --git a/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx b/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx index b4e2501dec..70c480f8e1 100644 --- a/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx +++ b/www/apps/resources/app/recipes/marketplace/examples/vendors/page.mdx @@ -590,12 +590,10 @@ export const GET = async ( ) const { data: [vendor] } = await query.graph({ - entryPoint: "vendor", + entity: "vendor", fields: ["products.*"], - variables: { - filters: { - id: [vendorAdmin.vendor.id], - }, + filters: { + id: [vendorAdmin.vendor.id], }, }) @@ -830,12 +828,10 @@ const groupVendorItemsStep = createStep( await Promise.all(cart.items?.map(async (item) => { const { data: [product] } = await query.graph({ - entryPoint: "product", + entity: "product", fields: ["vendor.*"], - variables: { - filters: { - id: [item.product_id], - }, + filters: { + id: [item.product_id], }, }) @@ -1274,12 +1270,10 @@ export const GET = async ( ) const { data: [vendor] } = await query.graph({ - entryPoint: "vendor", + entity: "vendor", fields: ["orders.*"], - variables: { - filters: { - id: [vendorAdmin.vendor.id], - }, + filters: { + id: [vendorAdmin.vendor.id], }, }) diff --git a/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx b/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx index 0d9814a853..402099383b 100644 --- a/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx +++ b/www/apps/resources/app/recipes/subscriptions/examples/standard/page.mdx @@ -677,14 +677,12 @@ export const POST = async ( const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const { data: [cart] } = await query.graph({ - entryPoint: "cart", + entity: "cart", fields: [ "metadata", ], - variables: { - filters: { - id: [req.params.id], - }, + filters: { + id: [req.params.id], }, }) @@ -998,14 +996,14 @@ export const GET = async ( data: subscriptions, metadata: { count, take, skip }, } = await query.graph({ - entryPoint: "subscription", + entity: "subscription", fields: [ "*", "orders.*", "customer.*", ...(req.validatedQuery?.fields.split(",") || []), ], - variables: { + pagination: { skip: offset, take: limit, order: { @@ -1051,17 +1049,15 @@ export const GET = async ( const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const { data: [subscription] } = await query.graph({ - entryPoint: "subscription", + entity: "subscription", fields: [ "*", "orders.*", "customer.*", ...(req.validatedQuery?.fields.split(",") || []), ], - variables: { - filters: { - id: [req.params.id], - }, + filters: { + id: [req.params.id], }, }) @@ -2134,14 +2130,12 @@ export const GET = async ( const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const { data: [customer] } = await query.graph({ - entryPoint: "customer", + entity: "customer", fields: [ "subscriptions.*", ], - variables: { - filters: { - id: [req.auth_context.actor_id], - }, + filters: { + id: [req.auth_context.actor_id], }, })