gentics / mesh-incubator

Project which is home for planned enhancements for Gentics Mesh
3 stars 0 forks source link

GraphQL: Dynamic loading of fields of node #23

Open philippguertler opened 5 years ago

philippguertler commented 5 years ago

Description

Currently, fields of a node can only be loaded by writing the fieldName in the GraphQL query like this:

{
  nodes {
    elements {
      uuid
      fields {
        ... on folder {
          slug
          name
        }
      }
    }
  }
}

There are a few problems with this:

Proposal

Allow the user to query all fields at once. One possibility would be to have a field for each type. The above query could be simplified to this:

{
  nodes {
    elements {
      uuid
      stringFields
    }
  }
}

You could also use aliases to have the same output as the first query:

{
  nodes {
    elements {
      uuid
      fields: stringFields
    }
  }
}

It should also be possible to add parameters to these fields:

{
  nodes {
    elements {
      uuid
      fields: stringFields(linkType: SHORT)
    }
  }
}

We could also add a filter to allow only certain fields:

{
  nodes {
    elements {
      uuid
      fields: stringFields(linkType: SHORT, filter: {name: {regex: "^cr_"}})
    }
  }
}

Of course it is possible to query other fields like usual:

{
  nodes {
    elements {
      uuid
      stringFields(linkType: SHORT, filter: {name: {regex: "^cr_"}})
      fields {
        ... on vehicleImage {
          image {
            width
            height
          }
        }
      }
    }
  }
}

Caveats

To make this work, we would need to introduce an untyped scalar value which can hold anything. This goes somewhat against the philosophy of GraphQL, because it is not immediately clear what how the response looks like by looking at the query.

mephinet commented 5 years ago

I have a feeling that this request is only coming from users of the Gentics Portals, but not from other Mesh users, or from the GraphQL community out there. Do you agree? Because if that were true, it might be ahint that for fetching a CMS page's tags (and for this task only), a REST request would be more suitable than a GraphQL request... This would basically mean that the Portals continues to use GraphQL for everything, except for PortalPhp::loadByPath and ContentPathHandler.loadByPath. While causing an additional round-trip (because a GraphQL query would probably still need to be done for breadcrumbs, navigation, languages, schema, etc - just the fragment content on %contentSchema% would be replaced by the REST call), it would allow portal developers the choice between

  1. use the fast GraphQL-only path, if a fragment content on %contentSchema% is provided
  2. use the slower GraphQL+REST path, thereby freeing the developer from the necessity of modifying the GraphQL query when the CMS template or tag map changes
philippguertler commented 4 years ago

Because if that were true, it might be ahint that for fetching a CMS page's tags (and for this task only), a REST request would be more suitable than a GraphQL request...

I'm not sure about that. If you want to follow a node reference (e.g. related Pages) you might want to have additional information. With REST you would only get the uuid. With GraphQL you could load additional fields for the related Pages.

philippguertler commented 4 years ago

Another possibility would be to fetch each field individually. Example:

{
  nodes {
    elements {
      uuid
      fields: dynamicFields {
        title: string(name: "title")
        subtitle: string(name: "subtitle")
        content: string(name: "content", linkType: SHORT)
        relatedEvents: nodeList(name: "relatedEvents") {
          uuid
          path
          fields: dynamicFields {
            startDate: date(name: "startDate")
          }
        }
      }
    }
  }
}

If a field cannot be found or the type does not match, null will be returned for that field.