paleobot / pbot-api

MIT License
2 stars 0 forks source link

Investigate Neo4j GraphQL Library as a replacement for neo4j-graphql-js #15

Closed NoisyFlowers closed 2 years ago

NoisyFlowers commented 2 years ago

We use neo4j-graphql-js for our interface between graphql and neo4j. This product had ceased development at the time we chose it, as Neo4j had decided to put their efforts into another library, neo4j-graphql.js. That library did not meet our needs at the time. I can't remember why. It was either missing either support for union types or interfaces, I think. That library was part of Grandstack at the time, and this is why we do not use Grandstack. I had always assumed we'd take another look at it as it matured.

Well, it turns out that Neo4j bailed on that library as well. They are now using a library called Neo4j GraphQL Library. This new library has replaced neo4j-graphql.js in Grandstack.

We should investigate the capabilities of this library and the difficultly of migration from neo4j-graphql-js.

One possible incentive for this is that it appears to handle nested mutations (essentially transactions), which would facilitate the more complex data entry flow we want to support.

https://neo4j.com/product/graphql-library/graphql-faq/

NoisyFlowers commented 2 years ago

We are pretty heavily invested in neo4j-graphql-js. Our entire approach to Groups relies on a hacked fork that injects a MATCH into every query. Because of a number of needs in our business logic, all of our mutation resolvers are custom, generating the Cypher code needed to interact with the Neo4j database.

Specifically, here is a list of migration concerns I've identified. There may be others.

1) Groups MATCH injection
2) soft delete (esp. recording of old data in ENTERED_BY relationship)
3) DELETE cascading
4) DELETE blocking relationships
5) relationship properties
6) cascading of Group to State/Character/CharacterInstance
7) authorization handling
8) ENTERED_BY on everything
9) making sure State and Character or related in CharacterInstance
10) verifying a node with Public Group has only that Group
11) prevent privatization of public nodes
12 a Collection must have at least one Reference
13) a Collection requires Specimens
14) Check for duplicate email in Person nodes

The good news Authentication/authorization in the new library appears well thought out and my go further than just replacing ours. It may also provide a mechanism for implementing the Groups MATCH injection (1) via its "allow" or "where" options.

Relationship properties (5) are handled. The approach is different than in neo4j-graphql-js. I can't tell if it is better, but it exists.

Nested mutations look good in the documentation. These could be huge, if robust in practice.

There is an OGM package that goes with it (https://neo4j.com/docs/graphql-manual/current/ogm/). Not sure how useful this would be, but it exists.

The not-so-good news DELETE blocking relationships (4) might not be robustly handled (https://github.com/neo4j/graphql/issues/1163, https://neo4j.com/docs/graphql-manual/current/troubleshooting/faqs/#_relationship_nullability_isnt_being_enforced_in_my_graph). If not, this would necessitate custom mutation resolvers.

Soft delete (2), DELETE cascading (3), Group cascading (6), ENTERED_BY on everything (8), verification of State-Character on CharacterInstance (9), public Group rules (10 and 11), Collection rules (12 and 13), and existing User check (14) all require varying degrees of special handling in mutation resolvers. I don't see any comprehensive way to add such special handling to the mutation resolvers generated by the library. If we can't use the generated mutation resolvers then we lose the very functionality that brought us here in the first place: nested mutations. Pashang.

There are a lot of open Issues for the project on Github. And there appears to be a propensity to label them Feature Requests and move on. That said, there does appear to be active development.

So, what do we do? neo4j-graphql-js is a dead project. But it works well. I will never understand why Neo4j chose to abandon it (https://github.com/neo4j-graphql/neo4j-graphql-js/issues/608) rather than build off it. We've hacked it directly and we use custom mutation resolvers to get what we need from it. It does not handle nested mutations. We would have to build this functionality into our custom resolvers.

Neo4j Graphql Library is the officially supported way of doing graphql with Neo4j (for now at least, ahem) and is under active development. It handles nested mutations. But our needs will likely force us to create custom mutation resolvers, meaning we won't be able to use the nested mutation functionality.

With either library, it appears we will be on our own for nested mutations.

I'm reasonably sure we could make the new library work for us, and it's probably wise to get on board with the official way of doing things (for now, ahem). But migration effort would be significant. I'd like to see a bit more mileage on Neo4j Graphql Library before commiting to that effort. I vote we hold off. But the opinion is weakly held.

aazaff commented 2 years ago

It sounds to me that migration is not appropriate at this time. If we need to customize the new one as much as the current one, then we don't really gain anything in terms of "standardizing" to the official way.