maoosi / prisma-appsync

⚡ Turns your ◭ Prisma Schema into a fully-featured GraphQL API, tailored for AWS AppSync.

Home Page:https://prisma-appsync.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Add support for `is`, `isNot` relation filters

Tenrys opened this issue · comments

commented

They seem to be missing in the currently generated GraphQL types, I'm not certain when they are and aren't available, but I think it would be nice to have the option to use them, maybe.

https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#is

I'm not sure if it would be as easy as modifying the schema generator template. For now I'll settle with some, I may take a look myself later

Both is and isNot filters were removed from 1.0.0-rc.2 (see full changelog) in favour of the newest Fluent API syntax.

This (removed):

query {
 listPosts(
  where: {
   author: { is: { username: "xxx" } }
  }
 ) {
  title
  author { username }
 }
}

Is equivalent to this (supported):

query {
 listPosts(
  where: {
   author: { username: { equals: "xxx" } }
  }
 ) {
  title
  author { username }
 }
}

Supporting both syntaxes simultaneously could be possible using the below Schema:

input UserScalarsWhereInput {
  # ...
  author: String
}

input PostWhereInput {
  # ...
  author: UserWhereInput
  is: UserScalarsWhereInput
  isNot: UserScalarsWhereInput
}

However, I'm thinking it would add (unnecessary?) complexity to detect and prevent using both syntaxes simultaneously within a single query.

Unless there is a use case in which the Fluent API syntax wouldn't allow doing the same as with is and isNot?

commented

I was mostly thinking about how to check whether or not a one-to-one relationship exists. I know the equivalent would be some: {} for one-to-many.

Would you have an example query to share (if you were to do it with the Prisma Client directly)?

commented
model Valuation {  
  ...
  estate      Estate?
  ...
}

model Estate {
  ...
  valuationUuid String     @unique
  valuation     Valuation  @relation(fields: [valuationUuid], references: [uuid])
  ...
}
const valuations = await client.valuation.findMany({
	where: {
		estate: {
			is: null,
		},
	},
});

Maybe there is a better way that I don't know of.

Another way to achieve the same would be:

query {
  listValuations(
    where: {
      estateUuid: { equals: null }
    }
  ) {
    id
  }
}

In theory this should work, though I've just tested it on my local machine - and it seems the event parser is transforming null values into undefined.

arguments: {
  where: {
    estateUuid: {
      equals: undefined # this should be null
    }
  }
}

Can you please try and let me know if you see the same issue on your end?

commented

Well, I have the foreign key on the side of the estate which refers to the valuation, so I can't check the exact same way.

I've tried a few different ways, but it doesn't seem to do much, e.g:

image

commented

I think it wouldn't hurt to bring back <Model>RelationFilter as it is in Prisma, with the same definition as <Model>WhereInput, except with those two deleted lines brought back:

12865a1#diff-0f3118d4d839ee46a643c4a03ad907f78569918a6a3cc248ab072e0e45bcba0aR52-R64

While making sure they do not get overriden, like how Prisma does it:

export type ValuationWhereInput = {
  AND?: Enumerable<ValuationWhereInput>
  OR?: Enumerable<ValuationWhereInput>
  NOT?: Enumerable<ValuationWhereInput>
  ...
  estate?: XOR<EstateRelationFilter, EstateWhereInput> | null
}

export type EstateRelationFilter = {
  is?: EstateWhereInput | null
  isNot?: EstateWhereInput | null
}

And just replacing the <Model>WhereInput here:

https://github.com/maoosi/prisma-appsync/blob/main/packages/generator/templates/schema.gql.njk#L84-L88

By the <Model>RelationFilter.

There is no proper way to express OR or XOR in GraphQL, so I don't think it will be possible to emulate XOR<EstateRelationFilter, EstateWhereInput> | null.

This is also why null filters are causing issues, as you can't write uuid: StringFilter | null or is: EstateWhereInput | null either with GraphQL. If your model is expecting uuid: StringFilter and you give it null, it is interpreted as undefined and then doesn't work properly when passed to Prisma Client.

That said, not being able to use null filters is problematic - so I will open a new issue and look into ways we can possibly fix it.

commented

Do you think fixing that issue would then take care of my initial problem and let me filter on one-to-one relationship existence, where the foreign key is not available on the model that is being filtered?

Yes, that's what I'm hopping for.

See #94

@Tenrys you can install prisma-appsync@1.0.0-preview.6.4 and try this:

query {
  listValuations (
    where: {
      estate: { is: NULL } # or `isNot: NULL`
    }
  ) {
    uuid
    estate {
      uuid
    }
  }
}

Let me know if that solves your issue?

commented

Works perfect for relationships, however I tried is and isNot on Int, String, Boolean and came up with Prisma validation errors because is and isNot aren't handled on their filters. I imagine it's the same with Float and other AWS scalars too.

Could make them use equals and notEquals on the Prisma side of things maybe?

Should work better now if you install prisma-appsync@1.0.0-preview.6.5 !

  • Filtering by null on Relations can be done via is: NULL and isNot: null
  • Filtering by null on regular fields (String, Boolean, etc) can be done via isNull: true and isNull: false
  • Filtering by null on required fields is not possible (e.g. if title is required/mandatory it means it can't be null)
commented

A bug I found: if you try to use is and isNot from <Model>WhereInput inside of a some or every, Prisma throws a validation error.

Thanks @Tenrys! I've created a separate issue: #102