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

Add support for Wildcards #942

Open
ollyde opened this issue May 3, 2022 · 24 comments
Open

Add support for Wildcards #942

ollyde opened this issue May 3, 2022 · 24 comments

Comments

@ollyde
Copy link

ollyde commented May 3, 2022

We need to sync our models from server to client. So also need to convert them from JSON exactly. With GraphQL this is becoming very painful.

Here's what we have to do for the hundreds of models in the project.
Screenshot 2022-05-03 at 16 10 28

Then for each query we need to remember to add these fields otherwise it breaks.
Screenshot 2022-05-03 at 16 11 31

A simple "*" wildcard would solve a lot of issues with GraphQL, the option is already supported on Apollo GraphQL web browser, just one little step to make it feasible.

@rivantsov
Copy link
Contributor

question - when we use * in a query, how deep it is supposed to go, for fields that return objects or lists of objects?

@ollyde
Copy link
Author

ollyde commented May 3, 2022

All objects and properties.

@rivantsov
Copy link
Contributor

but then, there might be circular refs in object types. ParentObj has a list of child objects, and child has a ref to parent. You are in infinite loop

@ollyde
Copy link
Author

ollyde commented May 3, 2022

@rivantsov it's already solved on Apollo with a button :-) There are easy ways to prevent that.

@rivantsov
Copy link
Contributor

can you please explain more? with an example, of query with * , against types with circular refs?

@ollyde
Copy link
Author

ollyde commented May 3, 2022

It's fairly simple what we need, attached a screenshot from a GraphQL explorer. We could write a meta data API but that is just faff. I'm honestly surprised this wasn't supported in GraphQL from day 1, since many folks using it have the same use case as me, specially with TypeScript etc.

Screenshot 2022-05-03 at 18 31 51

@lennyburdette
Copy link

It's really important to note that this new UI in Apollo Studio is a convenience for adding all available fields to the operation body. But the operation sent to the server still explicitly references each field (even if they're added recursively).

One critical property of GraphQL is that the client will never receive fields it doesn't explicitly ask for. If GraphQL had a wildcard field selector, and you added a field to the schema, the client would start receiving data it didn't know about when the operation was authored. If that new field is slow, the whole operation will take an unexpected latency hit.

I can certainly sympathize with wanting your authoring experience to be more convenient, but adding a wildcard field selector violates some of the key constraints of the query language so I'd look at solving this problem elsewhere.

@ollyde
Copy link
Author

ollyde commented May 3, 2022

@lennyburdette thanks for the input!

Most of GraphQL projects I've seen are doing exactly what I'm doing because of type safety. Many of my fellow developers complain about the exact same thing "Why can't we simply parse an object via wildcard?"

We're not asking to wildcard from the root, only for "objects". I think it's so close!

I might have to write some scruffy data field fetching API if the GraphQL team can't get the vision here. The next project we'll be going back to Rest if it's not resolved because of these long quires and bugs they introduce.

Another example.

I have a UserModel that is the same on the server and client, very common use case. It should be possible for user {*} to just fetch the fields here; what is the issue?

@BoD
Copy link
Contributor

BoD commented May 3, 2022

Could Fragments help a bit?

@ollyde
Copy link
Author

ollyde commented May 3, 2022

@BoD no.

@lennyburdette
Copy link

Previous discussion: #127

@ollyde
Copy link
Author

ollyde commented May 3, 2022

@lennyburdette I see it was closed with no answer 🙈 this is such a simple thing that people are requesting.

@michaelstaib
Copy link
Member

GraphQL is specifically designed to be explicit. In general, this is not a good feature to have in the query engine since it makes the execution unpredictable. In tooling wildcards can easily be implemented in the way apollo studio or others do it. Think about the implications for clients that use wildcards and get data they will never do anything with.

@ollyde
Copy link
Author

ollyde commented May 3, 2022

@michaelstaib most of the time it's usually a 1:1 relationship to database object vs. request serialization. So the data is already there in nearly all the cases I have seen.

I'll repeat myself here, we're not asking to change GraphQL we just asking for a continence method with control. It's up to the user where they place it, if they place it inside a large root tree, that's on them!

I'm sure saving a few bytes is most cases does not make a difference. I mean loading the profiles here was like 30 large requests worth of data for example. For the additional queries it should be on the user where they use the wildcard.

Right now GraphQL is awful to manage on large projects that have type safety, especially with schema additions or changes. On the +14 projects I'm managing, most of our bugs come from developers missing variables from serialized objects that make GQL requests.

@rivantsov
Copy link
Contributor

rivantsov commented May 3, 2022

I would side with @OllyDixon
His case is legit - I guess the client app loads ALL stuff, and turns it into object graph, and then operates it, shows in UI pages. The data is preloaded, it is I guess more efficient to load all and show parts in different areas, rather than run multiple queries on the fly to ask for slightly different things.
The queries I guess are stored in separate files and part of codebase, so you have to modify them whenever you change the object model. We should not say 'it's a bad practice to query all' - it depends.
Just like with SQL, there's * wildcard. Yes, it is considered a bad practice to use it in production queries, but there are cases when this is the least of 2 or more evils. And by the way, it is very helpful in manual querying, even when tools like SMS can generate the list for you, but it is not always usable (with multiple tables and joins).
Basically, if somebody willingly (!) wants to do something potentially (!) inefficient, we (GraphQL folks) should not be like 'oh this is stupid, we forbid it'. Programmers are not idiots, not all of them, they know what they are doing most of the time, we should trust them.
Edit: the question still remains about object/list fields; I guess they should NOT be included. I guess if you add a child list of objects, it is a big model change, so it's worth fixing queries manuall

@PascalSenn
Copy link
Contributor

@OllyDixon I dont understand the argument with typesafety.

Do you define the models in the client manually? I mean, the actual code models?

Usually the client defines the graphql queries, and based on these queries the code representation is generated. These queries are then also used for other export e.g. persisted queries.

There is also generator for dart https://pub.dev/documentation/graphql_codegen/latest/
(and there are a bunch of open source integrations for https://www.graphql-code-generator.com like https://github.com/vinaybedre/graphql-flutter-codegen

What you essentially do here is what fragments are used for:
image

fragment Room on Room {
  number
}

fragment Company on Company {
   name
}

fragment RoomResult on RoomResult {
  room {
    ...Room
  }
  company {
    ...Company
  }
}

@ollyde
Copy link
Author

ollyde commented May 3, 2022

@PascalSenn thanks for the input, but it doesn't solve the issue we have.

@rivantsov
Copy link
Contributor

on the second thought, what would happen with Union-type field? of list of union objects? - we might get varying list of fields, even in one array of objects...

@PascalSenn
Copy link
Contributor

@rivantsov you also run into type collision with these fields, as in e.g. graphql/graphql-js#53

@rivantsov
Copy link
Contributor

@PascalSenn - well, it means fields with params (methods) are excluded, anyway. So this * applies only to fields of primitive types, scalars, enums, or arrays of these. Still, seems to me wildcard might be useful. For pure data objects, without methods

@PascalSenn
Copy link
Contributor

@rivantsov sorry wrong issue. i was searching for an issue of the problem on the spec repo but didnt read it right. This issue describes it well: dotansimha/graphql-code-generator#2781

@ollyde
Copy link
Author

ollyde commented May 4, 2022

I think it would be nice to get this as an option; how people use it is on them :-)

We can already write some boilerplate that makes a request for the field-name metas and finds the name for each of the base objects, in-fact there are some libraries that exist to for-fill this purpose.

But I really think we shouldn't have to keep making wacky solutions when the base spec could offer an elegant solution.

@cliqer
Copy link

cliqer commented Jan 8, 2023

Thrown here while looking for an answer to this simple question and It is so sad that 127 got closed like that.

In the same way, we should remove * on SELECT from all SQL languages and keep typing each table separately because, what will happen if you delete a table, right?

Directus has a nice solution for deep nesting with multiple wildcards (..*) where you can go as deep as you want.

so, Back to REST...

@ollyde
Copy link
Author

ollyde commented Jan 8, 2023

@cliqer we migrated to tRPC. 3 systems so far. Has playground and automatic docs with 30% the code. GraphQL is overly verbose and I don’t see any use cases for it.

For typed languages (most systems) GraphQLs extremely annoying. We were getting bugs cause we had to hold a reference to object properties..

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

No branches or pull requests

7 participants