neo4j-graphql-js icon indicating copy to clipboard operation
neo4j-graphql-js copied to clipboard

Add Schema Stitching Example

Open roschaefer opened this issue 4 years ago • 7 comments

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. :tada:

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. :tada:

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)

roschaefer avatar Dec 06 '20 01:12 roschaefer

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

XBeg9 avatar Dec 10 '20 11:12 XBeg9

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.

medizinmensch avatar Dec 14 '20 19:12 medizinmensch

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 avatar Dec 15 '20 16:12 roschaefer

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 avatar Dec 15 '20 16:12 roschaefer

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!

medizinmensch avatar Dec 16 '20 11:12 medizinmensch

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.

roschaefer avatar Dec 24 '20 14:12 roschaefer

https://github.com/neo4j-graphql/neo4j-graphql-js/issues/608

michaeldgraham avatar May 02 '21 04:05 michaeldgraham