prisma icon indicating copy to clipboard operation
prisma copied to clipboard

Change response field names

Open sehmaschine opened this issue 3 years ago • 37 comments

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.

sehmaschine avatar Dec 01 '20 09:12 sehmaschine

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

devalnor avatar Dec 22 '20 10:12 devalnor

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?

sabi-wabi avatar May 25 '21 20:05 sabi-wabi

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 avatar Jan 11 '22 05:01 jbdemonte

@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
}));

franciscop avatar Mar 03 '22 16:03 franciscop

    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 avatar Mar 15 '22 09:03 Foxhound401

@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.

franciscop avatar May 03 '22 15:05 franciscop

+1

fkaanoz avatar May 29 '22 10:05 fkaanoz

+1

remib18 avatar Sep 02 '22 20:09 remib18

+1

ImVispo avatar Sep 05 '22 02:09 ImVispo

+1

ipavlyk-startupsoft avatar Oct 16 '22 23:10 ipavlyk-startupsoft

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 avatar Oct 20 '22 07:10 notAunty

@notAunty that's not a "solution", it's a proposal for new syntax that is very neat!

franciscop avatar Oct 20 '22 10:10 franciscop

+1 for renaming with 'as'

SC0d3r avatar Oct 24 '22 00:10 SC0d3r

+1, would be a great addition

aaimio avatar Oct 24 '22 07:10 aaimio

+1

ACronje avatar Oct 26 '22 12:10 ACronje

+1

but1head avatar Oct 26 '22 20:10 but1head

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.

Igetin avatar Oct 26 '22 21:10 Igetin

+1

uncletaurin avatar Oct 27 '22 10:10 uncletaurin

+1

bruhju avatar Nov 25 '22 13:11 bruhju

+1

camargosproj avatar Dec 06 '22 12:12 camargosproj

  • 1

smantzouMAS avatar Jan 17 '23 12:01 smantzouMAS

  • 1

kevin1193 avatar Feb 01 '23 10:02 kevin1193

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.

eliliam avatar Mar 27 '23 22:03 eliliam

+1 for this alias feature

matheus-rubio avatar Jun 02 '23 13:06 matheus-rubio

+2 for this alias feature

rodymuniz avatar Jun 06 '23 15:06 rodymuniz

+1039 please

murphman300 avatar Jun 06 '23 20:06 murphman300

+1 for this alias feature

luiys avatar Jun 30 '23 13:06 luiys

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 avatar Jul 04 '23 10:07 yeongjet

@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'))

ershisan99 avatar Jul 11 '23 18:07 ershisan99

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?

oalexdoda avatar Oct 13 '23 13:10 oalexdoda