prisma
prisma copied to clipboard
Change response field names
Problem
I'm trying to rename some fields when using select
.
Suggested solution
This is my current query:
const data = await prisma.data_riskscores.findMany({
select: {
id: true,
sections: true,
configuration_country: {
select: {
id: true,
name: true
}
}
}
})
Now I'd like to rename sections
and configuration_country
, because the data should not necessarily reflect the naming scheme of the database (IMO these are very different usecases):
const data = await prisma.data_riskscores.findMany({
select: {
id: true,
results: sections,
configuration_country: {
as: country,
select: {
id: true,
name: true
}
}
}
})
Alternatives
Using @map
resp. rename the relation field. It's a reasonable alternative, but I think the schema is not the right place to make this change. IMO, the schema should (more or less) reflect the database. Whereas the select
statement should allow to change the response data (because that might differ depending on the context of my request). For now, I'd probably go with a raw query instead.
Another alternative inspired from JS destructuring renaming
const data = await prisma.profile.findMany({
select: {
id: true,
name: true,
configuration_country: 'country' // work like an 'as'
}
})
But it won't resolve the typed approach of Prisma
Hi, is there any update on this?
I am looking for a way to rename the output of an aggregation's field name, e.g _sum
to something like total_X
.
Is there an optimal interim solution to this?
totally agreed,
Too sad to have to map:
const invoices = await this.prisma.invoice.findMany({
where: { AND: where },
include: { client: true, _count: { select: { notes: true } } },
orderBy,
});
return invoices.map(({ _count, ...invoice }) => ({
...invoice,
count: _count,
}));
Instead of simply have:
return this.prisma.invoice.findMany({
where: { AND: where },
include: { client: true, _count: { select: { notes: true }, as: 'count' } },
orderBy,
});
@jbdemonte that's exactly my usecase and my solution! I'm also using _count
and would love to have a native way of renaming it as count
, but meanwhile .map
-ing it with JS. Would love to see support for this kind of field, I'd also suggest as
as the keyname here.
Edit: wait, don't you have to do this to have the count: number
? For me the result is also being nested inside an object:
return invoices.map(({ _count, ...invoice }) => ({
...invoice,
count: _count.notes, // <= I had to also access it
}));
const categories = await this.prisma.category.findMany({
take: limit,
skip: offset,
where: {
is_deleted: false,
},
select: {
id: true,
type: true,
name: true,
},
});
return categories.map(({ id: _id, ...cat }) => ({ _id, ...cat }));
In my case, our frontend expected id
to be _id
, the field name in the underlying database is already _id
, is there any way that I can do to make it happen instead of do the map for every requests ? The map definitely defeated the elegance that prisma provided above.
@Foxhound401 if you want to change them everywhere you can do that with @map
:
https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/use-custom-model-and-field-names
Here we are discussing on a per-query change, not a global alias like you seem to want.
+1
+1
+1
+1
I couldn't use
const data = await prisma.profile.findMany({
select: {
id: true,
name: true,
configuration_country: 'country' // work like an 'as'
}
})
with include
though :cry:
@notAunty that's not a "solution", it's a proposal for new syntax that is very neat!
+1 for renaming with 'as'
+1, would be a great addition
+1
+1
If you just want to express your interest in the feature or your agreement to a comment, please just leave a 👍 reaction. There are people who have subscribed to these threads, and will receive an email from every single "+1" comment, which is not desirable.
+1
+1
+1
- 1
- 1
I'd also like to voice my support, and have done so with the 👍 reaction, however seeing as we have not seen any updates in this thread I thought it more fitting to post a comment instead.
+1 for this alias feature
+2 for this alias feature
+1039 please
+1 for this alias feature
This is an indispensable feature. My solution currently:
export const setCountKey = <T extends Record<string, any>, K extends string>(obj: T, key: K) => {
obj[`${key}Count`] = obj['_count'][key]
delete obj._count
return obj as Omit<T, '_count'> & { [P in `${K}Count`]: number }
}
const [totalCount, list] = await prisma.room.$transaction([
prisma.room.count({ where: { organizationId } }),
prisma.room.findMany({
where: { organizationId },
skip: offset,
take: limit,
select: {
_count: {
select: {
tenants: true
}
},
id: true
}
})
])
const newList = list.map(n => setCountKey(n, 'tenants'))
// newList[0] => { id: number, tenantsCount: number }
Any better idea?
@yeongjet that's neat, thank you! If someone wants to use it as a higher order function here's what I did:
export const setCountKey = <K extends string>(key: K) => {
return <T extends Record<string, any>>(obj: T) => {
obj[`${key}Count`] = obj['_count'][key]
delete obj._count
return obj as Omit<T, '_count'> & { [P in `${K}Count`]: number }
}
}
const newList = list.map(setCountKey('tenants'))
I need this feature too so I can do multiple aggregation relation-filtered queries on a given model.
For example:
prisma.training_sitemaps.findMany({
where: {
agent_id
},
select: {
id: true,
hostname: true,
href: true,
_count: {
select: {
links: { where: { training: 'pending' } }
}
}
}
})
This only allows me to do one filtered count for the links relationship array.
If I want to do 4 of them (i.e. where training is pending, a separate one when training is complete, a separate one when training is failed, another when training is queued, etc.) I can't because links
has to be unique. Any clues for a workaround here?