ardatan / ardatan/graphql-mesh

Unable to merge field selection in one resolver with selectionSet in another resolver

Open
#591 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
3.5k
Forks
363
Avg merge
6h 10m
Merged PRs (30d)
19

Description

Thanks to #584, now we can set field selection in apiContext call. This is great because it solves #579.

But there might be some drawback.. I found an issue when applying newest GraphQL Mesh to [my project](https://github.com/onelittlenightmusic/kubernetes-graphql/).
I created a simple example [here](https://github.com/onelittlenightmusic/graphql-mesh/pull/2/files).

The first resolver returns a type `PageviewTops`. I used field selection in api call.

[1st resolver]

```graphql
extend type Query {
viewsOver500K(project: String!): PageviewTops
}
```

```js
async viewsOver500K(obj, _, { Wiki }, info) {
const pageviewTops = await Wiki.api.getMetricsPageviewsTopProjectAccessYearMonthDay(
{
project: "en.wikipedia.org",
access: "all-access",
day: "31",
month: "05",
year: "2020"
},{
fields: {
items: {
articles: {
views: true
}
}
}
});
return pageviewTops;
},
```

The second resolver is a query resolver `topViewArticleName` in `PageviewTops` type. This has `selectionSet`. I imagine the field selection in first resolver and the selectionSet in second resolver request different fields each other (first => `view`, second => `article`)

[2nd resolver]
```graphql
extend type PageviewTops {
topViewArticleName: String
}
```

```js
PageviewTops: {
topViewArticleName: {
resolve: async (obj, _, { Wiki }, info) => {
return obj.items[0].articles[0].article;
},
selectionSet: `
{
items {
articles {
article
}
}
}
`
}
```

My use case is that I call the first resolver at root level. And I call the second resolver under the returned type of first resolver.

```graphql
viewsOver500K(project: "en.wikipedia.com") { # First
topViewArticleName # Second
items {
articles {
views
# not including the field `article` required in second resolver
}
}
}
```

Then I have this result in which second resolver returns `null`. This is because selectionSet is not reflected.

```js
{
"data": {
"viewsOver500K": {
"topViewArticleName": null,
"items": [
{
"articles": [
{
"views": 5440104
},
..
```

To test effect of field selection, I removed field selection in first resolver like this.

[Arranged 1st resolver(removed field selection)]

```js
async viewsTop(obj, _, { Wiki }, info) {
const pageviewTops = await Wiki.api.getMetricsPageviewsTopProjectAccessYearMonthDay(
{
project: "en.wikipedia.org",
access: "all-access",
day: "31",
month: "05",
year: "2020"
});
return pageviewTops;
}
```

Then I got this result, which includes right value of second resolver. This shows selectionSet is reflected without field selection of first resolver.

```js
{
"data": {
"viewsTop": {
"topViewArticleName": "Main_Page",
"items": [
{
"articles": [
{
"views": 5440104
},
```

The main issue is that, once we use field selection, other resolvers cannot set selectionSet to the same objects. The same pattern is in my project [here](https://github.com/onelittlenightmusic/kubernetes-graphql/blob/99b5efd89e3b2125a6fb5e9dcef8a24ed4b753ed/k8s/meshrc-cm.yaml#L224).

I try to summarize. Maybe these three field selections are related. Some intelligent merge mechanism will be required in this case.

```
query {
first(): type A {
second()
otherfield1
otherfield2
}
}
```

[Field selections related to type A]
1. Field selection in `first()` resolver (this was solved in #584)
1. User field selection (`otherfield1`, `otherfield2`)
1. selectionSet from `second()` to prepare resolver parameter `obj` (this issue's topic) --> there might be multiple resolvers with selectionSet..

@ardatan You suggested you were thinking some easier method to merge field selection... I wish your possible solution meets this issue as well. I did simple remediation at #579 in order to merge 1. and 2. but I found that was not sufficient...because 3. was not covered. Do you have any suggestion? Thank you.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the linked graphql-mesh reproduction and compare the field selection in the first resolver with the selectionSet in PageviewTops.topViewArticleName. Reproduce the query showing topViewArticleName as null, then inspect the related configuration in k8s/meshrc-cm.yaml. Done means selections from the API call, user query, and nested resolver are merged so the nested resolver receives article and the expected value is returned.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, typescript
Domain
api, backend-api-design
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.