question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Prisma Client: `@map` on the query level

See original GitHub issue

Problem

Hey! Would love it if the query builder API introduces a way to @map on the query level. Per example change an id field on the response object to be databaseId but only on a single query. It’s possible via a raw query using as but it would be nicer to do so on the query level. I think this would hugely increase performance on some cases when you have to loop on a findMany response to change the name of certain fields.

Suggested solution

Take a select query:

const users = prisma.user.findMany({ take: 10 })

which is the equivalent to

SELECT `main`.`User`.`id`, `main`.`User`.`createdAt`, `main`.`User`.`updatedAt`,
`main`.`User`.`email`, `main`.`User`.`name` FROM `main`.`User` LIMIT 10

To map only for this specific query you’d have to

const newUsers = users.map(x => ({...x, databaseId: x.id, id: undefined }))

which can be done with sql via the as operator like so (which is much much faster and scales very well):

SELECT `main`.`User`.`id` as databaseId, `main`.`User`.`createdAt`, `main`.`User`.`updatedAt`,
`main`.`User`.`email`, `main`.`User`.`name` FROM `main`.`User` LIMIT 10

Suggested API:

const users = prisma.user.findMany({ take: 10, map: { id: "databaseId" } })

Alternatives

Maybe not the keyword map but something else to not confuse people? Also with the suggested API I didn’t really give it much thought on how would it be properly typed but I am pretty sure it’s possible, either way that would be I guess one of the challenges.

Additional context

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:13
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

9reactions
AlaaZorkanecommented, Apr 23, 2021

Okay so here is what I was able to come up with (with a help from a friend of mine and a kind stranger in typescript’s discord)

// This is a wrapper around the methods that will be using map,
// required to be able to read the args (and the value of `map`) in the form of `as const`
declare function find<A>(x: Narrow<A>): A;

type Cast<A, B> = A extends B ? A : B;

type Narrowable =
    | string
    | number
    | bigint
    | boolean;

type Narrow<A> = Cast<A,
    | []
    | (A extends Narrowable ? A : never)
    | ({ [K in keyof A]: Narrow<A[K]> })
>;

// Our prisma model - works with complex types say per example relations etc
type User = {
    id: string;
    name: string;
    isVerified: boolean;
}

const args = find({ map: { id: "databaseId" } });

type y = typeof args["map"];

type Mapping<T> = { [K in keyof T]?: string };

type Replace<T, U extends Mapping<T>> = {
  [K in keyof T as K extends keyof U ? string & U[K] : K]: T[K]
};

type ControlledUserOutput = Replace<User, y>

const dbOutput: ControlledUserOutput = {
    databaseId: "something",
    name: "primsic",
    isVerified: true,
}

Playground Link

Also this issue was helpful: https://github.com/microsoft/TypeScript/issues/30680

Limitations

  • Changing the symbol on the map args (databaseId in our example) won’t change the dbOutput property name, for some reason typescript couldn’t pick that up ;/ changeSymbol
  • Doesn’t work with nested objects, say if you have a relation and you want to rename a field inside that relation (you can rename the relation root property itself)
4reactions
AlaaZorkanecommented, Apr 22, 2021

@map will make all the queries return databaseId instead of id, and will also change the property name for other methods (input and output), on the other hand, what I am proposing works basically for a specific single query and only for the returned data (not the input data).

Motivation would be to give people more control on the shape of the returned data, in my case I want this so I can make the id a databaseId on certain parts of my app but not on all parts of the app

Read more comments on GitHub >

github_iconTop Results From Across the Web

Prisma Client API (Reference)
API reference documentation for Prisma Client. ... Array of log levels, [ "info", "query" ] ... 3 query: string // Query sent to...
Read more >
Data model (Reference) - Prisma
Represent the entities of your application domain; Map to the tables ... The following query uses the Prisma Client generated from this data...
Read more >
Prisma Client extensions: query component (Preview)
The query object can contain functions that map to the names of the Prisma Client operations, such as findUnique , findFirst , findMany...
Read more >
Raw database access (Reference) - Prisma
Prisma Client supports the option of sending raw queries to your database. ... Prisma maps any database values returned by $queryRaw and $queryRawUnsafe...
Read more >
Using custom model and field names (Concepts) - Prisma
You can "rename" fields and models that are used in the Prisma Client by mapping them to the "original" names in the database...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found