Query Context

In this chapter, you'll learn how to pass contexts when retrieving data with Query.

What is Query Context?#

Query context is a way to pass additional information when retrieving data with Query. This data can be useful when applying custom transformations to the retrieved data based on the current context.

For example, consider you have a Blog Module with posts and authors. You can accept the user's language as a context and return the posts in the user's language. Another example is how Medusa uses Query Context to retrieve product variants' prices based on the customer's currency.


How to Use Query Context#

The query.graph method accepts an optional context parameter that can be used to pass additional context either to the data model you're retrieving (for example, post), or its related and linked models (for example, author).

You initialize a context using QueryContext from the Modules SDK. It accepts an object of contexts as an argument.

For example, to retrieve posts using Query while passing the user's language as a context:

Code
1const { data } = await query.graph({2  entity: "post",3  fields: ["*"],4  context: QueryContext({5    lang: "es",6  })7})

In this example, you pass in the context a lang property whose value is es.

Then, to handle the context while retrieving records of the data model, in the associated module's service you override the generated list method of the data model.

For example, continuing the example above, you can override the listPosts method of the Blog Module's service to handle the context:

Code
1import { MedusaContext, MedusaService } from "@medusajs/framework/utils"2import { Context, FindConfig } from "@medusajs/framework/types"3import Post from "./models/post"4import Author from "./models/author"5
6class BlogModuleService extends MedusaService({7  Post,8  Author9}){10  // @ts-ignore11  async listPosts(12    filters?: any, 13    config?: FindConfig<any> | undefined, 14    @MedusaContext() sharedContext?: Context | undefined15  ) {16    const context = filters.context ?? {}17    delete filters.context18
19    let posts = await super.listPosts(filters, config, sharedContext)20
21    if (context.lang === "es") {22      posts = posts.map((post) => {23        return {24          ...post,25          title: post.title + " en español",26        }27      })28    }29
30    return posts31  }32}33
34export default BlogModuleService

In the above example, you override the generated listPosts method. This method receives as a first parameter the filters passed to the query, but it also includes a context property that holds the context passed to the query.

You extract the context from filters, then retrieve the posts using the parent's listPosts method. After that, if the language is set in the context, you transform the titles of the posts.

All posts returned will now have their titles appended with "en español".

TipLearn more about the generated list method in this reference.

If you're retrieving a data model and you want to pass context to its associated model in the same module, you can pass them as part of QueryContext's parameter, then handle them in the same list method.

NoteFor linked data models, check out the next section.

For example, to pass a context for the post's authors:

Code
1const { data } = await query.graph({2  entity: "post",3  fields: ["*"],4  context: QueryContext({5    lang: "es",6    author: QueryContext({7      lang: "es",8    })9  })10})

Then, in the listPosts method, you can handle the context for the post's authors:

Code
1import { MedusaContext, MedusaService } from "@medusajs/framework/utils"2import { Context, FindConfig } from "@medusajs/framework/types"3import Post from "./models/post"4import Author from "./models/author"5
6class BlogModuleService extends MedusaService({7  Post,8  Author9}){10  // @ts-ignore11  async listPosts(12    filters?: any, 13    config?: FindConfig<any> | undefined, 14    @MedusaContext() sharedContext?: Context | undefined15  ) {16    const context = filters.context ?? {}17    delete filters.context18
19    let posts = await super.listPosts(filters, config, sharedContext)20
21    const isPostLangEs = context.lang === "es"22    const isAuthorLangEs = context.author?.lang === "es"23
24    if (isPostLangEs || isAuthorLangEs) {25      posts = posts.map((post) => {26        return {27          ...post,28          title: isPostLangEs ? post.title + " en español" : post.title,29          author: {30            ...post.author,31            name: isAuthorLangEs ? post.author.name + " en español" : post.author.name,32          }33        }34      })35    }36
37    return posts38  }39}40
41export default BlogModuleService

The context in filters will also have the context for author, which you can use to make transformations to the post's authors.


Passing Query Context to Linked Data Models#

If you're retrieving a data model and you want to pass context to a linked model in a different module, pass to the context property an object instead, where its keys are the linked model's name and the values are the context for that linked model.

For example, consider the Product Module's Product data model is linked to the Blog Module's Post data model. You can pass context to the Post data model while retrieving products like so:

Code
1const { data } = await query.graph({2  entity: "product",3  fields: ["*", "post.*"],4  context: {5    post: QueryContext({6      lang: "es",7    })8  }9})

In this example, you retrieve products and their associated posts. You also pass a context for post, indicating the customer's language.

To handle the context, you override the generated listPosts method of the Blog Module as explained previously.

Was this chapter helpful?
Edit this page
Ask Anything
FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break