Skip to content
This repository has been archived by the owner on Sep 3, 2021. It is now read-only.

Add Schema Stitching Example #550

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

roschaefer
Copy link
Contributor

@roschaefer roschaefer commented Dec 6, 2020

This creates an example repository in /examples to showcase how the freshly renovated graphql schema stitching API can be leveraged for neo4j-graphql-js.

When I was working on Oclelot-Social (formerly known as Human Connection) I made first-had experience of the advantages and disadvantages of neo4j-graphql-js.

Our biggest pain point with neo4j-graphql-js was the difficulty to customize the schema and write our own custom code aside of CRUD operations. I wished GraphQL Stitching had existed back then, because it's solving that problem beautifully.

No more custom fallback type resolvers

Use case: You mix your own mutation/query resolvers with those of neo4j-graphql-js. Unfortunately, you bypass neoj4-graphql-js then. If your custom resolver returns a type defined also your neo4j-graphqj-js schema, good luck writing all the code to fetch the associated data. We wrote our own "fallback resolvers" which checked if a parent.field was already set (then it's most likely populated by neo4j-graphql-js) and otherwise make another database call to fetch it.

Solution with grapqhl schema stitching: Write your own custom stuff and then call delegateToSchema with a query operation on the type you want to return. 🎉

No more man-in-the-middle attacks on resolveInfo

Use-case: Your custom resolvers need data which may not be requested by the client. We "hacked" the resolveInfo object to request certain fields (e.g. id, createdAt or disabled) even if they weren't requested by the client. We would pass this manipulated resolveInfo to neo4j-graphql-js. That way we could make neo4j-graphql-js return all properties of the nodes which we needed.

Solution with grapqhl schema stitching: You specify selectionSet in your resolver. 🎉

Implement performant orderBy of aggregated data

We ran into performance issues while ordering by fields that have a @cypher directive. You could even use Schema Stitching as a workaround. First, you write a custom database query which is known to perform well and populates a list of ids. Then you delegateToSchema the ids to neo4j-graphql-js. If the results are not in order, you could still reorder the results based on the order of your pre-populated ids, e.g. just before you return in your custom resolver.

TODO

  • Introduce lerna.js, so we share a common node_modules folder
  • Add the example tests to the build pipeline
  • Make top-level queries and resolvers exposed by neo4j-graphql-js inaccessible to the client (e.g. because of authorization)

Why are these files executable at all?
@XBeg9
Copy link

XBeg9 commented Dec 10, 2020

Hi @roschaefer, thanks for an example using schema stitching, I am curious, how you will compare this with the apollo federation approach? Thanks

@medizinmensch
Copy link

medizinmensch commented Dec 14, 2020

Looks like there are a few files too many in the root directory.

/package-lock.json
/package.json
/yarn.lock

Don't forget to remove them.

@roschaefer
Copy link
Contributor Author

Looks like there are a few files too many in the root directory.

/package-lock.json
/package.json
/yarn.lock

Don't forget to remove them.

Thanks a million!

@roschaefer
Copy link
Contributor Author

roschaefer commented Dec 15, 2020

Hi @roschaefer, thanks for an example using schema stitching, I am curious, how you will compare this with the apollo federation approach? Thanks

The crucial difference is that in GraphQL schema stitching, the subschemas don't know each other. They are autonomous. See this blog post: https://product.voxmedia.com/2020/11/2/21494865/to-federate-or-stitch-a-graphql-gateway-revisited

I must admit, I haven't used Apollo Federation myself in production. My goal in another project was that I used a remote GraphQL schema at https://graphcms.com/. Their schema would do a lot, but I wanted to implement my own authentication/authorization, data validation and custom logic. It didn't seem possible with Apollo Federation because I have no control over the schema at GraphCMS. However, with GraphQL schema stitching, this is possible and works beautifully. My architecture looks like this:

(Client)--[:PUBLIC_ACCESS]-->(CustomBackend)--[:API_KEY_PROTECTED_ACCESS]-->(GraphCMS)

Now, after I accomplished that, the idea came to my mind to use the same technique for neo4j-graphql-js knowing that the output there is an executableSchema. And it works! Since it's running in the same NodeJS process it's not even a performance overhead.

I think the main advantage of this strategy is that it defeats the tight coupling between type-defintions and resolvers. This is by design since neo4j-graphql-js is like Type-Definition-Driven-Development. Nevertheless, according to my own experiences from production, this is not desirable for the use-case of running a publicly accessible fullstack application on top of neo4j-graphql-js and Neo4J.

But doing it this way, I have all the freedom I want regarding my custom type definitions and still get all the convenience which neo4j-graphql-js brings.

Does that make sense @XBeg9 ?

@roschaefer roschaefer force-pushed the schema_stitching branch 2 times, most recently from c1d1255 to ef1b6c9 Compare December 15, 2020 22:22
@medizinmensch
Copy link

Looks like there are still 3 empty files in root which don't belong there. Maybe its a GitHub issue showing these or I am misinterpreting these?
Also a small typo for the folder example/schema-stitching/src/db/entitites/ and its references ("entities" would be correct).

I like the example!

@roschaefer
Copy link
Contributor Author

Looks like there are still 3 empty files in root which don't belong there. Maybe its a GitHub issue showing these or I am misinterpreting these?
Also a small typo for the folder example/schema-stitching/src/db/entitites/ and its references ("entities" would be correct).

I like the example!

Thanks, typo is fixed now. This PR waits for #549 to be merged, that's why you see those three files in the PR. It's just UNIX file permissions, no changes to the content.

@michaeldgraham
Copy link
Collaborator

#608

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants