Thoughts and wishes for API v7
Since the first alpha releases for API v7 are out, I want to share some thoughts on it.
- It seems like the new filter operators are coming. Great to hear that! I hope you have #4827 in mind? Would be a really nice feature to have string comparison ignoring case finally :)
- #5819 removes single element relationships. I understand the intention behind that. However, as already discussed in several tickets, e.g. here, the :1 relationship is a BIG and important thing (a
Producthas ONEPriceand is produced by ONECompany). Our API relies heavily on this feature. The release notes on v7 describe how to use the@cypherdirective to achieve the removed behaviour. Since filtering on@cypherfields is possible, this seems to be working. But that's only for READ scenarios. How about WRITE? It is not sufficient to just READ nodes connect in a :1 manner. We also have to CREATE, UPDATE, DELETE them. Is this coming as a new feature as proposed by me in #1962? Or how are you planning to workaround WRITE scenarios?
But overall we are excited and look forward to v7! Is there an approximate timeline as to when we can expect a final release??
- It seems like the new filter operators are coming. Great to hear that! I hope you have Add new filters for String types to enable case-insensitive filtering #4827 in mind? Would be a really nice feature to have string comparison ignoring case finally :)
Definitely, this kind of feature request is one of the many reasons we are making this change to the input types! We may not add it directly in 7.0.0, but it can certainly be expected not far behind.
- Remove single relationships #5819 removes single element relationships. I understand the intention behind that. However, as already discussed in several tickets, e.g. here, the :1 relationship is a BIG and important thing (a
Producthas ONEPriceand is produced by ONECompany). Our API relies heavily on this feature. The release notes on v7 describe how to use the@cypherdirective to achieve the removed behaviour. Since filtering on@cypherfields is possible, this seems to be working. But that's only for READ scenarios. How about WRITE? It is not sufficient to just READ nodes connect in a :1 manner. We also have to CREATE, UPDATE, DELETE them. Is this coming as a new feature as proposed by me in Extend the @cypher directive with statements for create/update/delete mutations to be able to mutate properties which are resolved by a @cypher directive #1962? Or how are you planning to workaround WRITE scenarios?
I think the important thing to note here is that we are removing this functionality because we simply cannot guarantee the adherence to any particular relationship cardinality. The long term answer to this problem is constraints in the database to control this, but this will be a long long way off. In the interim, I'm afraid that the answer may be more around workarounds. For example, having a Cypher field to read the data, which contains the logic of how to decide which node to return. And then mapping a relationship field which is write-only and using this for the modification of data, just without any guarantees of cardinality. We'll look to do a write up of a workaround such as this because I agree that it's perhaps not intuitive.
But overall we are excited and look forward to v7! Is there an approximate timeline as to when we can expect a final release??
We are aiming for around the end of March/beginning of April. 🙂
Hey @darrellwarde, any news on the workaround for CREATE,UPDATE,DELETE mutations to handle the :1 relationships via cypher? Are you still planning to release end of March/beginning of April?
Hey @angrykoala , maybe you can give an answer to my question from above?
Hey @darrellwarde, any news on the workaround for CREATE,UPDATE,DELETE mutations to handle the :1 relationships via cypher? Are you still planning to release end of March/beginning of April?
Hi @andreloeffelmann
Yes, we are still aiming to beginning of April. The 7 alpha is already looking a bit more stable in terms of breaking changes, and now working on fixing some bugs.
Any particular info you want about the 1: cypher workaround?
In general, as Darrell described, it shouldn't be too hard to achieve some basic functionality for 1-1 relationships using the @cypher directive, although there may be some limitations, any in particular that you find? You should be able to try a fairly stable version of 7.0 alpha already if you want to try these
Hi @angrykoala
Great to hear that - looking forward to it :)
I am talking about the workaround @darrellwarde mentioned in https://github.com/neo4j/graphql/issues/5932#issuecomment-2590242956:
I'm afraid that the answer may be more around workarounds. For example, having a Cypher field to read the data, which contains the logic of how to decide which node to return. And then mapping a relationship field which is write-only and using this for the modification of data, just without any guarantees of cardinality. We'll look to do a write up of a workaround such as this because I agree that it's perhaps not intuitive.
I have not found any information on this anywhere until now. As I wrote in my first comment of this ticket:
However, as already discussed in several tickets, e.g. here, the :1 relationship is a BIG and important thing (a
Producthas ONEPriceand is produced by ONECompany). Our API relies heavily on this feature. The release notes on v7 describe how to use the@cypherdirective to achieve the removed behaviour. Since filtering on@cypherfields is possible, this seems to be working. But that's only for READ scenarios. How about WRITE? It is not sufficient to just READ nodes connect in a :1 manner. We also have to CREATE, UPDATE, DELETE them. Is this coming as a new feature as proposed by me in Extend the @cypher directive with statements for create/update/delete mutations to be able to mutate properties which are resolved by a @cypher directive #1962? Or how are you planning to workaround WRITE scenarios?
... it is not only about READing 1: relationships with the cypher directive. The important CREATE,UPDATE,DELETE stuff is still missing and I do not see how to solve that despite having read each release note of the alpha versions of v7.
That said: we are not able to upgrade to v7 without having the possibililty to realize CRUD operations for 1: relationships
Can you explain the workaround for me?
Ah, thanks for the clarification @andreloeffelmann
CRUD operations can be a bit more tricky to emulate, but the gist is:
- Have a normal, many to many relationships, this one will be used for CRUD operations over this relationship (you can use the
@querydirective to make it not-readable. The@relationshipconfiguration may also help in making sure that only the operations you want are accesible. From the point of view of the client, these are many to many CRUD operations - Have a second field that is readonly with
@cypher, this one matches the relationship, but only returns one item. This is the 1: relationship exposed to read operations
So, in essence, having 2 different fields , one for modifying the relationship, other for reading as a 1:
You may notice that this does not really guarantee cardinality, and that is the main reason why we had to remove 1: relationships for now, as the solution existing in 5 LTS does not really guarantee this either
Does this help? We are aware of the limitations of these workarounds and will work on finding better approaches to this, but hopefully will be enough to move towards v7
Hi @angrykoala
thanks for the update! So you are basically saying that this type definition:
type Product @node {
productId: String!
price: Price @relationship (type: "PRODUCT_HAS_PRICE", direction: OUT, queryDirection: DIRECTED)
}
type Price @node {
value: Float
currency: String
}
should be replaced by this:
type Product @node {
productId: String!
price: Price @cypher(
statement: """
MATCH(this)-[:PRODUCT_HAS_PRICE]->(p:Price)
RETURN p
"""
columnName: "p"
)
prices: [Price!]! @relationship (type: "PRODUCT_HAS_PRICE", direction: OUT, queryDirection: DIRECTED) @selectable(onRead: false, onAggregate: false)
}
type Price @node {
value: Float
currency: String
}
Note that I replaced @query with @selectable since prices is a field, not a type.
Is this the idea?
If so, I hope it will be possible to do this:?
type Product @node {
productId: String!
price: Price @cypher(
statement: """
MATCH(this)-[:PRODUCT_HAS_PRICE]->(p:Price)
RETURN p
"""
columnName: "p"
)
price: [Price!]! @relationship (type: "PRODUCT_HAS_PRICE", direction: OUT, queryDirection: DIRECTED) @selectable(onRead: false, onAggregate: false)
}
type Price @node {
value: Float
currency: String
}
Note the difference: the price field is called price in both ways, not prices (plural) for the relationship. Since the one with the @cypher directive is for READ scenarios only and the one with the @relationship and @settable directive is for CUD scenarios, the introspection result should be fine.
What about https://github.com/neo4j/graphql/issues/1962 which I have proposed almost 3 years ago? This would allow a much cleaner solution.
Yeah, that would be the rough idea. I don't think the second snippet will work, as the source is not valid GraphQL.
#1962 (and the related #2265) is something that we still have as a long term goal to improve the Cypher directive. It is a non-trivial feature with many edge cases, so it will not be a short term alternative for v7.
Hi @andreloeffelmann
I'll close this issue now, as the first two items have been addressed already and the third one is covered by #2265
Feel free to comment if I missed anything else to be addressed in this issue