Skip to main content

`result`: Add custom fields and methods to query results

info

Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the clientExtensions Preview feature flag if you are running on a version earlier than 4.16.0.

You can use the result Prisma Client extensions component type to add custom fields and methods to query results.

Add custom fields or methods to query results

Use the $extends client-level method to create an extended client. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions.

Use the result extension component to add custom fields and methods to query results.

To add a custom field or method to query results, use the following structure. In this example, we add the custom field myComputedField to the result of a user model query.

const prisma = new PrismaClient().$extends({
name?: 'name',
result?: {
user: { // in this case, we extend the `user` model
myComputedField: { // the name of the new computed field
needs: { ... },
compute() { ... }
},
},
},
});

The parameters are as follows:

  • name: (optional) specifies a name for the extension that appears in error logs.
  • result: defines new fields and methods to the query results.
  • needs: an object which describes the dependencies of the result field.
  • compute: a method that defines how the virtual field is computed when it is accessed.

Add a custom field to query results

You can use the result extension component to add fields to query results. These fields are computed at runtime and are type-safe.

In the following example, we add a new virtual field called fullName to the user model.

const prisma = new PrismaClient().$extends({
result: {
user: {
fullName: {
// the dependencies
needs: { firstName: true, lastName: true },
compute(user) {
// the computation logic
return `${user.firstName} ${user.lastName}`
},
},
},
},
})

const user = await prisma.user.findFirst()

// return the user's full name, such as "John Doe"
console.log(user.fullName)

In above example, the input user of compute is automatically typed according to the object defined in needs. firstName and lastName are of type string, because they are specified in needs. If they are not specified in needs, then they cannot be accessed.

Re-use a computed field in another computed field

The following example computes a user's title and full name in a type-safe way. titleFullName is a computed field that reuses the fullName computed field.

const prisma = new PrismaClient()
.$extends({
result: {
user: {
fullName: {
needs: { firstName: true, lastName: true },
compute(user) {
return `${user.firstName} ${user.lastName}`
},
},
},
},
})
.$extends({
result: {
user: {
titleFullName: {
needs: { title: true, fullName: true },
compute(user) {
return `${user.title} (${user.fullName})`
},
},
},
},
})

Considerations for fields

  • For performance reasons, Prisma Client computes results on access, not on retrieval.

  • You can only create computed fields that are based on scalar fields.

  • You can only use computed fields with select and you cannot aggregate them. For example:

    const user = await prisma.user.findFirst({
    select: { email: true },
    })
    console.log(user.fullName) // undefined

Add a custom method to the result object

You can use the result component to add methods to query results. The following example adds a new method, save to the result object.

const prisma = new PrismaClient().$extends({
result: {
user: {
save: {
needs: { id: true },
compute(user) {
return () =>
prisma.user.update({ where: { id: user.id }, data: user })
},
},
},
},
})

const user = await prisma.user.findUniqueOrThrow({ where: { id: someId } })
user.email = '[email protected]'
await user.save()