Closed danReynolds closed 3 years ago
This looks really creative/promising, @danReynolds !
It is currently difficult to perform queries for entities of a particular type from the Apollo cache, such as all Employee entities in the cache with age == 42. Since the cache does not group entities by type, you would need to create a pseudo collection field by writing a field to the root query and always keeping it up to date when new entities of that type are added/removed. If you then wanted to perform the filter by age, you would need to write another type policy called employeesAboveAge that filters the pseudo collection down further.
Just to make sure I'm correctly oriented within the problem space, is it fair to say that the current proposal solves the same problem as the root query / field policy pattern, but with less boilerplate code required of the developer?
If so, it may be instructive to provide a reference example showing how the motivating example of querying Employee
s of a certain age would be accomplished under the existing paradigm.
As an aside: this would be a great topic for a future GraphQL WG meeting. π
This looks really creative/promising, @danReynolds !
It is currently difficult to perform queries for entities of a particular type from the Apollo cache, such as all Employee entities in the cache with age == 42. Since the cache does not group entities by type, you would need to create a pseudo collection field by writing a field to the root query and always keeping it up to date when new entities of that type are added/removed. If you then wanted to perform the filter by age, you would need to write another type policy called employeesAboveAge that filters the pseudo collection down further.
Just to make sure I'm correctly oriented within the problem space, is it fair to say that the current proposal solves the same problem as the root query / field policy pattern, but with less boilerplate code required of the developer?
If so, it may be instructive to provide a reference example showing how the motivating example of querying
Employee
s of a certain age would be accomplished under the existing paradigm.As an aside: this would be a great topic for a future GraphQL WG meeting. π
Yea! we discussed it at a working group meeting a couple weeks back, I think you were out. I'm planning to write up a post demonstrating the use cases it solves, it was getting to be too much background for a PR description.
Experimental support for accessing and filtering entity collections by typename from the Apollo cache using the new
useFragment
anduseFragmentWhere
hooks.This change introduces the concept of data entity collections, grouped by type. It is currently difficult to perform queries for entities of a particular type from the Apollo cache, such as all
Employee
entities in the cache withage == 42
. Since the cache does not group entities by type, you would need to create a pseudo collection field by writing a field to the root query and always keeping it up to date when new entities of that type are added/removed.If you then wanted to perform the filter by age, you would need to write another type policy called
employeesAboveAge
that filters the pseudo collection down further.This ends up being a lot of overhead and developer maintenance to do manually and could be made easier. This feature supports automatic collection grouping of entities in the cache, which can then be queried using the new
useFragment
anduseFragmentWhere
as well as thewatchFragment
andwatchFragmentWhere
APIs.an example of using the hooks might look like this:
This is still an experimental implementation requiring some further cleanup/testing but the PR is up early for feedback from folks.
Proposed implementation
Whenever a normalized entity like an
Employee:1
object is written to the cache, a reference is also added to aCacheExtensionsCollectionEntity
entity for that type, with IDCacheExtensionsCollectionEntity:TypeName
that is shaped like this:With the list of entities by type now maintained in the cache, we can then add support watching for updates to the full or filtered collection. While there is a matching
readFragment
API available as a counterpart toreadQuery
, there is no built-inuseFragment
orwatchFragment
API foruseQuery
orwatchQuery
. This is likely because entities themselves are not watchable in the Apollo cache, only queries support the observable API necessary for subscribing to changes.To overcome this limitation and introduce the
useFragment
,watchFragment
and newuseFragmentWhere
APIs, we automatically generate a type policy for these calls and access the data from the collection entities. This way, whenever any fields requested in the fragment change in the cache, the type policy will update and deliver new data, just like a manually defined type policy would.Open API questions
Right now it creates the automatically generated type policies by fragment name. Fragment and query names should be unique across apps since conflicting ones would break tools like TS type generation. The alternative to relying on fragment names here would be to have the new APIs like
useFragmentWhere
support aname
oralias
field to cache it under, which can be done but adds a bit more developer overhead.I will probably list a few more things here as people point them out/I think through why this is all a bad idea π