4
votes

This should be doable with foreign keys, but I'm scouring through the docs but I can't seem to find anything about foreign keys in it.

It looks like the only kind of relationship supported by Cloud Spanner is the interleaved-table relationship... but honestly NoSQL document stores like MongoDB already provide this much.

How would you implement many-to-many relationships in Cloud Spanner?

EDIT:

In my specific case I want a feature similar to Twitter's followers, and a "Following" is a directed relation from one user to another.

I can see how to model this to get relatively efficient queries, but I don't see how I would safeguard the system from inconsistencies, i.e. having a Following that references an User that has been deleted.

2

2 Answers

4
votes

Cloud Spanner supports a full range of joins (Inner, Cross, Full, Left, Right). It lets you create and query many-to-many relationships just as you would in a standard SQL database.

However, just because you can make those queries, does not mean that they will be efficient. If your queries need to read and write across splits, then your query performance will be slower as it needs to co-ordinate reads and writes to multiple splits. Interleaved tables give you more control over your data layout on disk, to improve the performance of your queries.

If you wanted to create an efficient many-to-many relationship, you could have two tables that interleave with a parent table on a shared common key: e.g.

Parent key = account_id
-- Many 1 key = account_id, user_id
-- Many 2 key = account_id, group_id

This would enable you to make queries that only need to touch a single split, keeping them fast, efficient, and conflict free.

Cloud Spanner also has an array type which depending on your use case may also be helpful.

EDIT: responding to

I can see how to model this to get relatively efficient queries, but I don't see how I would safeguard the system from inconsistencies, i.e. having a Following that references an User that has been deleted.

You could either delete all the follower records within the same account delete mutation as two separate queries in a transaction, or setup a background job to clean it up in the background.

Also, in this situation I can't for instance have a Many2 be cascade-deleted because its reference in Many1 has been deleted, right? The only cascade delete I can do in this case is if I delete a whole Parent.

Yes, that's correct.