Do any of the graph based/aware databases have good mechanisms for maintaining referential integrity? Do any of the graph-based/graph-aware databases (Neo4j, ArangoDB, OrientDB, or other) have mechanisms for maintaining referential integrity on a par with those offered by relational databases?

I'm exploring various document-based databases to find a suitable engine to use for adding an auxiliary data storage to a certain project.  

I discovered graph-based/multimodel databases and they seemed like a good idea, but I was surprised to find that they don't seem to offer the same level of protection of relations/links/edges that modern relational databases have.

In particular, I'm talking about linking deletions of entities/vertices with deletion of links/edges. In a relational database, I can have a foreign key constraint that links records from one table with records in another table, and will either 


prevent deletion of record in table A if it's referenced by record in table B ("on delete no action"), or 
delete the referencing record(s) in table B if a referenced record in table A is being deleted.


I expected to find a similar mechanics in graph-aware databases. For example, if a "comment" vertex links to a "post" vertex (forming a many-to-1 relation), then there are the following problems/challenges to solve:


Prevent deletion of a post while there are edges from comments to this post. This way, a comment could never have a dangling link/edge to a post. The solution would be: depending on the link/edge properties, either 


prevent deletion of a post until all edges from comments to this post are deleted, or 
delete all comments linking to this post when the post is being deleted.

Prevent deletion of an edge from a comment to a post without deleting the comment itself, to prevent the comment from not having a link/edge to a post at all.
Only allow creation of a comment if an edge is created to link this comment to a post at the same time.


Are mechanisms like this really lacking in graph-based databases, or was I just unable to find them?

I know that OrientDB has the "link" data type that probably solves the second and the third problem (if a link-typed property is declared mandatory and non-null, then it's impossible to create a record without specifying the link destination, and later it's impossible to break the link by un-setting the property).  

However, as far as I remember, it's possible to delete the record which a link-typed property points to, thus producing a dangling link (so the first problem is not solved).

I also know that in certain databases I can use nested documents as an alternative to having multiple linked documents. However, this approach doesn't scale well (for cases when the number of linking records grows can grow indefinitely). Also, it is quite limited (it can't be used as an alternative when several links are needed, say, to a post and to a user; there are other important limitations, too).
Only allow creation of a comment if an edge is created to link this comment to a post at the same time.


This is supported by Dgraph Labs' GraphQL implementation out of the box. In your schema, you would add a exclamation mark ! to denote that an edge is required when added and when retrieved.
type Post {
  id: ID
  comments: [Comment]
}
type Comment {
  id: ID
  text: String!
  onPost: Post! @hasInverse(field: comments)
}

This schema above, would mandate that every Comment have a reference onPost edge and would return errors if you send mutations that did not match this requirement.
This would also error if you were to query a comment and request the onPost edge and it did not exist. How might that happen if the Comments cannot be added without the edge? Because the @hasInverse will do the bookkeeping to keep the Post.comments and Comment.onPost edges consistent. This allows you to delete a post node that could delete Comment.onPost edges.


Prevent deletion of a post while there are edges from comments to this post.
Prevent deletion of an edge from a comment to a post without deleting the comment itself


Right now in Dgraph's GraphQL implementation there is no way to enforce or prevent cascade deletes as there is with SQL-like databases. This would have to be managed from a middleware level. Having that said, Dgraph Labs has implemented a way to currently do this with the @custom directive and are currently developing (promised for 20.11 release) a @lambda directive to enable an almost native javascript middleware functionality. Combining either one of these methods with another currently awaiting release directive @generate. The generate directive will allow you to disable the default generated mutations and then you can create your own custom mutations to handle this business logic as needed with DQL upserts. These custom mutations can then be mapped and served via the GraphQL endpoint.