Skip to content

GraphQL custom attributes container proposal #282

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

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions design-documents/graph-ql/custom-attributes-container.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
## Problem statement

Some Magento installations may have tens of thousands of custom (EAV) product attributes. This is possible when the merchant is selling thousands of different product types with unique attribute sets.

Custom attributes in GraphQL schema are presented in flat structure, which may be a problem for the client application when performing search in catalog. GraphQL requires all needed fields to be explicitly listed in the query, "get all fields" queries are not supported. At the same time Magento is expected to return all EAV attributes applicable to each product.

One workaround for "getting all fields" is based on schema introspection, it allows to get names of all fields in `ProductInterface` including EAV attributes. Even with the described workaround client application will have to explicitly list tens of thousands of attributes in the search query because it does not know in advance products belonging to which attribute sets will be returned in search result.

# Proposed solution

To account for dynamic nature of EAV attributes and the need of "getting all fields" in product search queries, `custom_attributes: [CustomAttribute]!` container will be introduced.

```graphql
type CustomAttribute {
code: String!
value: String!
}
```

Here `value` is JSON-encoded value of the custom attribute.

Flat representation of custom attributes in `ProductInterface` (and other EAV entities like `Category`, `Customer` etc) will remain intact. The client will a have choice to query custom fields explicitly and have validation of the response against GraphQL schema or to "get all" custom attributes using `custom_attributes` container.

It is necessary to keep in mind that with `custom_attributes` it is not possible to query product EAV attributes selectively, which may lead to performance degradation.

### Sample queries

Current implementation allows the following query
```graphql
{
products(search: "test") {
items {
name
sku
color
manufacturer
size
}
}
}
```

Let's assume the response will be

```graphql
{
"data": {
"products": {
"items": [
{
"name": "Test Simple Product",
"sku": "testSimpleProduct",
"color": "Red",
"manufacturer": "Company A"
"size": null
},
{
"name": "Test Configurable Product",
"sku": "testConfigProduct",
"color": null,
"manufacturer": "Company B"
"size": "XXL"
}
]
}
}
}
```

With the proposed changes the above mentioned queries will still be supported. In addition, the following query will become possible

```graphql
{
products(search: "test") {
items {
name
sku
custom_attributes {
code
value
}
}
}
}
```
Note that color and size are not applicable to some products in the search result. In the previous example they were returned as `null`. In the following example they are not returned at all

```graphql
{
"data": {
"products": {
"items": [
{
"name": "Test Simple Product",
"sku": "testSimpleProduct",
"custom_attributes": [
{
"code": "color"
"value": "Red"
},
{
"code": "manufacturer"
"value": "Company A"
}
]
},
{
"name": "Test Configurable Product",
"sku": "testConfigProduct",
"custom_attributes": [
{
"code": "manufacturer"
"value": "Company B"
},
{
"code": "size"
"value": "XXL"
}
]
},
]
}
}
}
```

# Alternatives considered

1. [Persisted queries](https://github.com/magento/graphql-ce/issues/781) can be leveraged to mitigate described issue with the increased size of the request.
1. To improve flexibility and allow support of complex structures, `type` can be added to the definition of `CustomAttribute` in the future, if there are valid use cases.
1. `value` of the `CustomAttribute` can have different format other than JSON, potentially more strict one.
1. It is possible to eliminate rendering of custom attributes in flat structure from `ProductInterface` (and other EAV entities) and completely rely on containers. We believe this will cause developer experience degradation and does not bring any significant benefits for production deployments.