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

[FR] GraphQL: Query by field value #5208

Open
daltonrooney opened this issue Nov 5, 2019 · 11 comments
Open

[FR] GraphQL: Query by field value #5208

daltonrooney opened this issue Nov 5, 2019 · 11 comments

Comments

@daltonrooney
Copy link

@daltonrooney daltonrooney commented Nov 5, 2019

Maybe I'm missing something, but do we have the ability to query elements by field data in GraphQL? For example, I'm building an events module and need to query for three months of entries by startDate. In Twig, we would do something like this:

{% set events = craft.entries.section('events').startDate('and', '>= 2019-11-01', '< 2020-02-01').orderBy('startDate asc') %}

Is there an equivalent in GraphQL? Or is the search directive the best way to do this currently?

@andris-sevcenko

This comment has been minimized.

Copy link
Member

@andris-sevcenko andris-sevcenko commented Nov 6, 2019

This is not very feasible in GraphQL, which is much more rigid than regular PHP classes. While, with element queries, it's entirely possible to make sure code just rolls with the punches if something unknown is being set (Craft checks if there's a field with the handle and so on), GraphQL requires all the possible arguments for queries to be listed.

This means that if your Craft install had 100 fields, they would all need to be listed as possible arguments for entry queries. While possible, this would still degrade performance and reduce any GraphQL IDE usability in terms of query auto-completion.

I'd say your options (at the time) are:
a) go with the search query argument
b) as you're rolling your own module, anyway, just add a new GraphQL Query with that module that is more specifically tailored to your needs?

There's no developer documentation for extending GraphQL support, yet, but if you feel like code-diving, then this would be a good place to start: https://github.com/craftcms/cms/blob/develop/src/services/Gql.php#L86-L110

@daltonrooney

This comment has been minimized.

Copy link
Author

@daltonrooney daltonrooney commented Nov 29, 2019

I’d be very interested in option B when more documentation becomes available. I’ve been trying to use the native GraphQL implementation on projects but usually end up going back to CraftQL for anything more than a basic app. We are only going to be doing more GraphQL in the future, so I would love to be able to extend it with our more advanced query requirements.

@andris-sevcenko

This comment has been minimized.

Copy link
Member

@andris-sevcenko andris-sevcenko commented Nov 29, 2019

I hope to get the developer documentation in order this year, as it's is sorely needed.

@narration-sd

This comment has been minimized.

Copy link
Contributor

@narration-sd narration-sd commented Nov 29, 2019

Yup, but maybe get a quick and useful start by describing how to add or modify resolvers, as wouldn't that often be a swifter and nicer way to get results, than wholesale creating queries, etc.?

@narration-sd

This comment has been minimized.

Copy link
Contributor

@narration-sd narration-sd commented Nov 29, 2019

For reference, here's some code as example of what I'm mentioning, if doing something we don't need any more as Andris has kindly added the transform: argument internally for Assets.

For a special Element query, you'd just write that in as result per your argument/s for it, if present.

I don't know how much easier this might be than arranging a full new Query for GraphQL -- the active part would be similar, but there are the issues of defining arguments, non-collision with stock query for that element, etc..

I also know he has well-formed ideas of what apropos patterns should be, so this will be important as well.

We'll be able to see with the documentation for that process...


    if (Comparator::greaterThanOrEqualTo(
           Craft::$app->getVersion(),
           '3.4')) { // where Andris adds field definition ability
                    Event::on(TypeManager::class,
                        TypeManager::EVENT_DEFINE_GQL_TYPE_FIELDS,
                        [$this, 'addGraphQLFieldDefs']);
    }

    public function addGraphQLFieldDefs(DefineGqlTypeFieldsEvent $event)
    {
        if ($event->typeName === 'AssetInterface') {

            $freshArgsList = \array_merge(
                $event->fields['url']['args'],
                [
                    'transform' => [
                        'name' => 'transform',
                        'type' => Type::string(),
                        'description' => 'The handle of the named transform to use.'
                    ]
                ]);

            $event->fields['url'] = [
                'name' => 'url',
                'type' => Type::string(),
                'args' => $freshArgsList,
                'resolve' => function($source, array $arguments, $context, ResolveInfo $resolveInfo) {
                    if (\array_key_exists('transform', $arguments)) {
                        return $source->getUrl($arguments['transform']);
                    } else if ($resolve = $resolveInfo->parentType->resolveFieldFn) {
                        return $resolve ($source, $arguments, $context, $resolveInfo);
                    } else {
                        return $source->getUrl(); // in case, or better this throws Exception?
                    }
                }
            ];
        }
    }
@andris-sevcenko

This comment has been minimized.

Copy link
Member

@andris-sevcenko andris-sevcenko commented Nov 29, 2019

Yup, but maybe get a quick and useful start by describing how to add or modify resolvers, as wouldn't that often be a swifter and nicer way to get results, than wholesale creating queries, etc.?

That's available as of Craft 3.4, though, but yeah. It's possible to use that event and modify query arguments, adding your own conditions.

@narration-sd

This comment has been minimized.

Copy link
Contributor

@narration-sd narration-sd commented Nov 29, 2019

...above corrected to my actual code which has the version compare...

@jamesedmonston

This comment has been minimized.

Copy link

@jamesedmonston jamesedmonston commented Dec 9, 2019

@andris-sevcenko do you have an example of how to achieve this with the search query argument? I'm looking to do something similar to the OP: querying past/future events based on a date field.

@andris-sevcenko

This comment has been minimized.

Copy link
Member

@andris-sevcenko andris-sevcenko commented Dec 11, 2019

@jamesedmonston huh. On second thought, it's not really possible using search, sorry.

Maybe it's really just worth adding all the custom fields as possible query arguments.

@daltonrooney

This comment has been minimized.

Copy link
Author

@daltonrooney daltonrooney commented Dec 11, 2019

Maybe it's really just worth adding all the custom fields as possible query arguments.

@andris-sevcenko I've certainly enjoyed that when working with CraftQL but if it there's a potential performance drawback (especially on a large site with hundreds of fields) then I'm more than open to alternatives. One option might be a config file where we specify which fields that we want to enable in GraphQL queries.

But as we move more toward headless sites altogether, some kind of UI in the control panel would be nice. Maybe a list of all available fields when defining your GraphQL schema, which you can select as appropriate?

@andris-sevcenko

This comment has been minimized.

Copy link
Member

@andris-sevcenko andris-sevcenko commented Dec 12, 2019

@daltonrooney well it's not really a performance drawback, since it all gets cached by default, but rather can get overwhelming? We'll talk this over internally.

@andris-sevcenko andris-sevcenko added this to the 3.4 milestone Dec 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.