3

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

  1. prevent deletion of record in table A if it's referenced by record in table B ("on delete no action"), or

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

  1. 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

    1. prevent deletion of a post until all edges from comments to this post are deleted, or

    2. delete all comments linking to this post when the post is being deleted.

  2. 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.

  3. 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).

4
  • 1
    This is an excellent first question (+1) and should NOT be downvoted or VtC as a simple "shopping list" question - it is a strong technical question and should stand! – Vérace Apr 10 '20 at 14:17
  • @Vérace It's a matter of English language, not authority, and my knowledge of English is limited. :) (I deleted my earlier comments to avoid noise.) – pvgoran Apr 10 '20 at 17:11
  • 1
    I was wrong - "Does any" works - "Does any of the following hold?" (singular - he does) is good English, but "does any of the graph..." doesn't work for me! "Do any" (they do - plural)! Your knowledge of English is certainly not limited - and is a lot better than many here - I just hope my edits helped with your question! I'll delete my prior comments also! Leaving first one though! – Vérace Apr 10 '20 at 17:21
  • I know nothing (well, v. little - have read some of the blurb), but have you considered the AgensGraph project - might be worth a look? – Vérace Apr 11 '20 at 12:24
0
  1. 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.

  1. Prevent deletion of a post while there are edges from comments to this post.
  2. 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.