graphql / graphql/graphql-spec

client cursor - select by list of random keys - client side query batching

Open
#665 2 comments 0 reactions 0 assignees View on GitHub
👻 Needs Champion
Dominant language
JavaScript
Stars
14.6k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

in SQL we can use the [SQL IN operator](https://www.w3schools.com/sql/sql_in.asp)
```
SELECT * FROM table
WHERE table.key IN UNNEST (@keylist)
```
where keylist is an array of keys like `[1, 1000, 50, 10000]` [[source](https://cloud.google.com/spanner/docs/sql-best-practices#write_efficient_queries_for_range_key_lookup)]
[ the UNNEST operator converts from array to vertical vector ]

the keys are random, not adjacent, not predictable
similar to a server-side pagination cursor, so we can say "client cursor"

use case in graphQL?
parallel pagination. broad first search / breadth-first search.
and: dealing with "read only" servers = we cannot change the server schema

workaround?
using a list of N keys, we can repeat the same selector [sub-query] for N times
and append the key index to all variable names

code sample in javascript
with the compound key `{ repoOwner, repoName }`
```js
const url = 'https://api.github.com/graphql'

// basic authentication - only for testing
const username = 'your_github_username'
const password = 'your_github_password'

// query object
const qObj = {

variables: {

repoOwner_0: "graphql",
repoName_0: "graphql-spec",

repoOwner_1: "graphql",
repoName_1: "graphql-js",
},

query: `query
(
$repoOwner_0: String!,
$repoName_0: String!,

$repoOwner_1: String!,
$repoName_1: String!,
){

r0: repository
(
owner: $repoOwner_0,
name: $repoName_0,
){
nameWithOwner
pushedAt
createdAt
stargazers { totalCount }
}

r1: repository
(
owner: $repoOwner_1,
name: $repoName_1,
){
nameWithOwner
pushedAt
createdAt
stargazers { totalCount }
}

}`
}

// send query
const headers = new Headers({
'Authorization': 'Basic '+btoa(username+":"+password),
'Content-Type': 'application/json',
'Accept': 'application/json',
})
fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(qObj),
})
.then(r => r.json())
.then(response => {
// print response
console.log('response = '+JSON.stringify(response, null, ' '))
})
```
result:
```txt
response = {
"data": {
"r0": {
"nameWithOwner": "graphql/graphql-spec",
"pushedAt": "2019-12-19T01:02:54Z",
"createdAt": "2015-07-01T01:26:56Z",
"stargazers": {
"totalCount": 12274
}
},
"r1": {
"nameWithOwner": "graphql/graphql-js",
"pushedAt": "2019-12-26T02:31:06Z",
"createdAt": "2015-06-30T12:16:50Z",
"stargazers": {
"totalCount": 15304
}
}
}
}
```
this selector
```
repository
(
owner: [$repoOwner_0, $repoOwner_1],
name: [$repoName_0, $repoName_1],
)
```
is not supported by the server:
> List dimension mismatch on variable $var_name and argument name ([String!]! / String!)

the fields [repository, repositry] must be renamed to [r0, r1], otherwise i get
> Field 'field_name' has an argument conflict

[on stackoverflow.com](https://stackoverflow.com/questions/59482349/graphql-client-side-query-batching-repeat-one-query-for-a-list-of-keys) i posted some more code, to generate such "concat queries"
inspired by [Batching queries with GraphQL & Python, by Julien Danjou](https://medium.com/mergify/batching-queries-with-graphql-94983b648c3c)

questions:

1. am i re-inventing the wheel here? and just too blind to see a better solution?
2. are there plans to implement such a feature? i could not even find a similar request

implementation sketch:
add a `@repeat` directive / pseudo-object / block / container

```js
const qObj = {

variables: {

repoOwner: ["graphql", "graphql" ],
repoName: ["graphql-spec", "graphql-js"],

constVar: 1234,
},

query: `query
(
$repoOwner: String!,
$repoName: String!,
$constVar: Int!,
){

# repeat this block for all keys
# = for the longest array, fill shorter arrays

@repeat {
repository
(
owner: $repoOwner,
name: $repoName,
)
{
pushedAt
stargazers { totalCount }

sampleobject(arg: $constVar)
}
}

}`
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.