Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cost improvement: annotate unique fields #8060

Closed
bbarry opened this issue Feb 21, 2025 · 1 comment
Closed

cost improvement: annotate unique fields #8060

bbarry opened this issue Feb 21, 2025 · 1 comment

Comments

@bbarry
Copy link

bbarry commented Feb 21, 2025

Product

Hot Chocolate

Is your feature request related to a problem?

This is mostly a user training issue, but there is an aspect of intuition being violated here. Basically when users make requests for entries that they know are unique, they are getting hit with high costs on their operation because they neglected to include a paging parameter.

It would be nice to be able to annotate fields as being unique and thus an equality filter using them would mean the same thing as setting the page size to 1 for the purposes of cost calculation.

The solution you'd like

I am imagining something roughly like:

public record Book([Unique]int BookId, string? Name);

would result in a state such that the cost of these two field resolvers are equal:

query GetBooksTwice($bookId: Int!) {
    a: books(where: { bookId: { eq: $bookId } }) { bookId name }
    b: books(where: { bookId: { eq: $bookId } } first: 1) { bookId name }
}

Perhaps this involves a schema adjustment like:

input BooksFilterInput {
  bookId: UniqueIntOperationFilterInput
  # ...
}
input UniqueIntOperationFilterInput {
  eq: Int
  # ... (everything in the base int filter)
}

Or maybe an annotation on the query field:

type Query
  books( # ...
  )
    @implicitSlicing(
        slicingCoordinate: ["where", "bookId", "eq"],
        maxPageSize: 1)
@michaelstaib
Copy link
Member

In general this would be a bad schema design. As a general rule have explicit fields to fetch books by their identifier.

type Query {
  bookById(id: ID!): Book
}

This has many reasons:

  1. Discoverability - The API is more clear to the consumer.
  2. Performance - Its very difficult to optimize a books with filters call whereas the bookById call can be easily optimized and use a DataLoader.
  3. Compatibility - Lookups in GraphQL also help in the frontend as they can double as node field.

If you have batching needs its best practice to have a batching version in addition.

type Query {
  bookById(id: ID!): Book
  booksById(id: [ID!]!): [Book]
}

DO not use filters to avoid creating specific lookups.
DO use filtering only if you have a client use case where you for instance have a grid and you need client-controlled filters.
DO use strict FilterInputTypes to only allow what is really needed by the client use-case.

In general in GraphQL you want to apply the YAGNI principal... You aint gonna need it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants