graphql / graphql/graphql-spec
[RFC] Collections / CollectionTypeDefinition
- Dominant language
- JavaScript
- Stars
- 14.6k
- Forks
- 1.2k
- PR merge metrics
- No merged PRs in 30d
Description
# TL;DR:
This RFC introduces a new variant of Lists/Arrays that has named entries key-value pairs. Which can be queried exactly like arrays, but a result is an object.
## Problem Statement
If a type object has multiple fields of the same type and it makes sense that they are grouped together and be addressed as a collective instead of being addressed individually, with GraphQL you have three ways you can achieve that. Creating a scalar, creating another type, or using an array and somewhere in the documentation mention which position of an array refers to which named entry.
### Example
Consider the following requirements:
1. a `Build` object consists of 4 `Item`-slots.
2. Slot position matters and it should be readable which slots are equipped.
3. Preferably slots should be grouped together under a common ancestor without any unrelated siblings.
4. Item slots should not be queried/selected individually, the query either includes all slots or non.
5. It's possible to specify which `Item` fields are included.
Initially, the schema may look like this:
```graphql
type Item {
id: String!
name: String!
icon(size: String): String!
}
type Build {
id: String!
slot0Item: Item
slot1Item: Item
slot2Item: Item
slot3Item: Item
}
```
... but that doesn't satisfy the **3rd** and **4th** requirements.
Introducing a new type `ItemSlots` still won't satisfy the **4th** requirement:
```graphql
type Item {
id: String!
name: String!
icon(size: String): String!
}
type ItemSlots {
slot0Item: Item
slot1Item: Item
slot2Item: Item
slot3Item: Item
}
type Build {
id: String!
items: ItemSlots!
}
```
and using a Scalar it's not possible to meet the **5th** requirement.
## 🧑💻 Proposed Solution
A new collection type.
## 🎬 Behavior
Collections can be queried exactly as if they were an array/list, but instead of returning an array of `0` to `∞` entries, it returns finite named entries as specified in the schema.
## ✏️ Proposed syntax - `!`
Collections can be defined similarly to how an object type is defined, except fields don't have a type (because all fields are supposed to be of the same type).
```graphql
collection ItemSlots {
slot0
slot1
slot2
slot3
}
type Item {
id: String!
name: String!
icon(size: String): String!
}
type Build {
id: String!
items: ItemSlots! # or `ItemSlots!` if fields are not nullable.
}
```
## ✨ Use cases
* Allows grouping of fields that share the same type and are supposed to be addressed atomically.
* Gets rid of unnecessary/repetitive lines in queries to select the same nested fields across multiple fields.
The `items` field in the above schema can be queried like:
```graphql
query GetBuild($id: String!, $iconSize: String!) {
build(id: $id) {
id
items {
name
icon(iconSize: $iconSize)
}
}
}
```
and the result should look something like this:
```json
{
"data": {
"build": {
"id": "...",
"items": {
"slot0": {
"name": "...",
"icon": "..."
},
"slot1": "...",
"slot2": "...",
"slot3": "..."
}
}
}
}
```
_I should probably note that the template structure of this issue was copied from an RFC of \@\twof. I just found the template very clean and the structure fits my proposal as well. :))_
Contributor guide
Assessment
This issue has not been assessed yet.