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

Is there a way to get "subfields" when using the __fields__() method? #104

Open
Justin-Wise opened this issue May 11, 2020 · 9 comments
Open
Assignees
Labels
question Further information is requested

Comments

@Justin-Wise
Copy link

Justin-Wise commented May 11, 2020

Is there a way to use the fields method to query items in the current level, as well as those in a sublevel?

If something looked like this:
query { repository(id: "repo1") { issues { number title body reporter { login name }
could you do something like
issues.__field__('number','{reporter:login}')?

@barbieri
Copy link
Member

just a sub-selection, you can't. You need to do in 2 statements:

issues.__fields__() # the the basic fields
issues.reporter.__fields__()

However, if you want the whole subtree -- be careful of loops/cycles -- you can use __to_graphql__(auto_select_depth=3) you can see some examples at https://sgqlc.readthedocs.io/en/latest/sgqlc.operation.html

@barbieri barbieri self-assigned this May 12, 2020
@barbieri barbieri added the question Further information is requested label May 12, 2020
@n-wach
Copy link
Contributor

n-wach commented Dec 24, 2020

How hard would it be to add support for this?

I was somewhat disappointed this wasn't a built-in feature, and ended up creating some utilities to be able to add subfields from a string path.

@barbieri
Copy link
Member

@n-wach well, as I said you shouldn't be querying for all fields, just the fields that you use, that's the idea behind GraphQL, the lack of "versions" and one of the way to avoid breaks.

However, during dev/debug it may be helpful, so I added the __to_graphql__(auto_select_depth=3)

But be careful, loops may cause some issues (that's why the depth is low by default).

What kind of app/client are you writing?

@n-wach
Copy link
Contributor

n-wach commented Jan 2, 2021

We are writing a python library that wraps a GraphQL API, built on top of SGQLC.

We have a bit of a unique situation--our GraphQL schema is complicated and can be updated frequently, so we're using autogenerated SGQLC. We've added wrapper classes that wrap the SGQLC types, and provide methods for populating additional fields, performing operations, etc.

We frequently want to allow the library user to decide what fields they want (rather than selecting all fields). Since there are a few layers of error handing/abstraction between the public functions and underlying SGQLC operation/query, we had to find an easier way to specify fields.

We have a class that stores a list of strings for fields we want on an operation. Class can be created and modified before the Operation is created, and handles adding Selections prior to the Operation being sent. The major new feature being that we allow specifying subpaths. So you could include "issues.reporter.name" when an operation would return Repository. We've got some other features (default selected fields rather than selecting all, support for arguments, excluding from default fields) that help make the API easier to use.

Although we love SGQLC, we've effectively hidden it from our library's users

@barbieri
Copy link
Member

barbieri commented Jan 7, 2021

@n-wach wow, my company is a heavy user of GraphQL on both server and client side, we have web applications, react-native applications, federated servers and so on, we never had to reach that. Are you using it as a client on the server side or front-ends?

I ask because on front-ends, at least in JavaScript world, the trend is to specify some fragments or some operations and let the rest be generated, so you just write the DSL and let the infra do stuff for you. At the end this becomes very, very easy to use, you test on some interactive playground, then copy that to your application and it's basically done.

To bring SGQLC closer to that, more recently I've added operations support to sgqlc-codegen, you can type your fragments, your operations and have it to generate the Operation for you in a simple and efficient way. I'm even mulling on some optimizations, such as cache/save the output code (which is basically a "compressed" form of the input, so we remove whitespaces and all), instead of generating it every time as currently done by SGQLC.

Also, I'm planing to add the https://docs.python.org/3/library/typing.html support to that generation (not the whole SGQLC as it uses some metatypes and it makes static typing difficult), so you could get the resulting data shape once you + the operation with the data.

Maybe going that path would bring you more flexibility while making it easier for your users? You can provide a fragment library and people could use that + the sgqlc-codegen operation to generate stuff, instead of using yet-another-layer.

@n-wach
Copy link
Contributor

n-wach commented Jan 8, 2021

Yeah, our JS front-end applications use fragments, and so do tools on the server-side.

The goal of our library is to open up our API to Python scripting for other parts of the company. We wanted it to be approachable and simple to use straight out of the box (by including a default subset of fields on queries, etc.), but also allow developers low level access to optimize/extend if they have to.

Most users will be clients writing scripts to automate tasks, we don't use this library on the server side.

@barbieri
Copy link
Member

barbieri commented Jan 8, 2021

ok, anyway, the code that __fields__ and __to_graphql__() uses are based on primitives like dir() and iterations, then you can probably implement that behavior yourself, correct?

Do you have any issues to get it done? If so, let me know.

@n-wach
Copy link
Contributor

n-wach commented Jan 8, 2021

Yeah we've got it working.

I was just wondering if letting __fields__ natively accept subfields (like "issues.reporter.name") would be a useful feature for other folks.

@barbieri
Copy link
Member

I think it could be, but I fear people abusing it, with a __fields__ and a huuuuge list of stuff, moving from python to its own "dsl".

Remember that GraphQL allows arguments, so if you add a.b.c you likely will have people asking for a(x=1).b.c and you reinvent SGQLC using strings rather than python code 😅

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

No branches or pull requests

3 participants