diff --git a/src/content/doc-surrealql/datamodel/references.mdx b/src/content/doc-surrealql/datamodel/references.mdx index c58a66e91..03a0d46f3 100644 --- a/src/content/doc-surrealql/datamodel/references.mdx +++ b/src/content/doc-surrealql/datamodel/references.mdx @@ -81,11 +81,6 @@ Because the `owners` field on `comic_book` looks for any and all references, it This can be fixed by changing the single field of type `references` to two fields, one of which is a `references`, and the other a `references`. ```surql -REMOVE TABLE person; -REMOVE TABLE comic_book; -REMOVE TABLE publisher; -REMOVE TABLE book; - DEFINE FIELD comics ON person TYPE option>> REFERENCE; DEFINE FIELD products ON publisher TYPE option>> REFERENCE; DEFINE FIELD owners ON comic_book TYPE references; @@ -146,6 +141,48 @@ SELECT * FROM comic_book; ] ``` +## Using the `.refs()` method + +The `.refs()` method can be called on a record to find references to it in the same way that a field can be defined as a `references`. Similar to defining a field of type `references`, this function can also narrow down the references to a record by only returning references from a certain table, or a certain table and field name. + +```surql +DEFINE FIELD comics ON person TYPE option>> REFERENCE; +DEFINE FIELD borrowed_comics ON person TYPE option>> REFERENCE; + +CREATE person:one SET comics = [comic_book:one]; +CREATE person:two SET borrowed_comics = [comic_book:one]; +CREATE comic_book:one SET title = "Loki, God of Stories"; + +-- All references +comic_book:one.refs(); +-- All references from 'person' records +comic_book:one.refs('person'); +-- All references from 'person' records via a field 'comics' +comic_book:one.refs('person', 'comics'); +``` + +```surql title="Output" +-------- Query -------- + +[ + person:two, + person:one +] + +-------- Query -------- + +[ + person:two, + person:one +] + +-------- Query -------- + +[ + person:one +] +``` + ## Specifying deletion behaviour When keeping track of references, it is very likely that you will want some behaviour to happen when a reference is deleted. Take the following example of a `person` who owns a `comic_book`, which is later deleted. However, a follow-up `SELECT * FROM person` still shows the comic book. @@ -188,6 +225,169 @@ A query using `INFO FOR TABLE person` shows that the actual statement created us This `ON DELETE` clause can be modified to have some other behaviour besides ignoring when a reference is deleted. +### ON DELETE IGNORE + +As shown in the previous section, this is the default behaviour for references. + +```surql +-- Default, behaviour, so identical to: +-- DEFINE FIELD friends ON person TYPE option>> REFERENCE; +DEFINE FIELD friends ON person TYPE option>> REFERENCE ON DELETE IGNORE; +DEFINE FIELD friended_by ON person TYPE references; + +CREATE person:one SET friends = [person:two]; +CREATE person:two; +DELETE person:one; +person:two.*; +``` + +As the deletion of `person:one` is ignored when calculating the `friended_by` field, it will still show `person:one` even though the record itself has been deleted. + +```surql +{ + friended_by: [ + person:one + ], + id: person:two +} +``` + +### ON DELETE UNSET + +`ON DELETE UNSET` will unset (remove) any linked records that are deleted. This can be thought of as the opposite of `ON DELETE IGNORE`. + +```surql +DEFINE FIELD comments ON person TYPE option>> REFERENCE ON DELETE UNSET; +DEFINE FIELD author ON comment TYPE references; + +CREATE person:one; +UPDATE person:one SET comments += (CREATE ONLY comment SET text = "Estonia is bigger than I expected!").id; +-- Give this one a parameter name so it can be deleted later +LET $comment = CREATE ONLY comment SET text = "I don't get the joke here?"; +UPDATE person:one SET comments += $comment.id; +-- Now delete it +DELETE $comment; +-- Only one comment shows up for person:one now +person:one.comments.*.*; +``` + +```surql title="Output of person:one queries" +-------- Query -------- + +[ + { + author: [ + person:one + ], + id: comment:idxhzumaggzb7g3ym6bl, + text: 'Estonia is bigger than I expected!' + }, + { + author: [ + person:one + ], + id: comment:58uasmx4s0vdjjehfyjz, + text: "I don't get the joke here?" + } +] + +-------- Query -------- + +[ + { + author: [ + person:one + ], + id: comment:uma97u2j2q4tlamzc9yv, + text: 'Estonia is bigger than I expected!' + } +] +``` + +### ON DELETE CASCADE + +The `ON DELETE CASCADE` will cause a record to be deleted if any record it references is deleted. This is useful for records that should not exist if a record that links to them no longer exists. + +```surql +REMOVE DATABASE db; + +DEFINE FIELD author ON comment TYPE record REFERENCE ON DELETE CASCADE; +DEFINE FIELD comments ON person TYPE references; + +CREATE person:one; +CREATE comment SET author = person:one, text = "5/10 for this blog post. The problems I have with it are..."; +CREATE comment SET author = person:one, text = "WOW! I never knew you could cut a rope with an arrow."; + +-- Show all the details of comments for 'person:one' +person:one.comments.*.*; +DELETE person:one; +-- Comments no longer exist +SELECT * FROM comment; +``` + +```surql title="Output" +-------- Query -------- + +[ + { + author: person:one, + id: comment:8msvp0egg8cdlyu4vvn9, + text: 'WOW! I never knew you could cut a rope with an arrow.' + }, + { + author: person:one, + id: comment:i72qfjy59vbn81hk6lrm, + text: '5/10 for this blog post. The problems I have with it are...' + } +] + +-------- Query -------- + +[] + +-------- Query -------- + +[] +``` + ### ON DELETE REJECT -`ON DELETE REJECT` will outright make it impossible to delete a record that is referenced from somewhere else. \ No newline at end of file +`ON DELETE REJECT` will outright make it impossible to delete a record that is referenced from somewhere else. For example, consider the case in which a house should not be demolished (deleted) until it has been disconnected from utilities such as gas, water, electricity, and so on. This can be simulated in a schema by adding a `REFERENCE ON DELETE REJECT` to the `utility` table, making it impossible for any `house` to be deleted if they link to it. + +```surql +DEFINE FIELD connected_to ON utility TYPE option>> REFERENCE ON DELETE REJECT; +DEFINE FIELD using ON house TYPE references; + +CREATE house:one; +CREATE utility:gas, utility:water SET connected_to = [house:one]; +``` + +At this point, the `using` field on `house:one` automatically picks up the two references, + +```surql +house:one.*; +DELETE house:one; +``` + +```surql title="Output" +-------- Query -------- + +{ + id: house:one, + using: [ + utility:gas, + utility:water + ] +} + +-------- Query -------- + +'Cannot delete `house:one` as it is referenced by `utility:gas` with an ON DELETE REJECT clause' +``` + +UPDATE utility:gas SET connected_to -= house:one; +UPDATE utility:water SET connected_to -= house:one; + +DELETE house:one; +``` +