Skip to content

Commit

Permalink
Add content, placeholder ASCII graph
Browse files Browse the repository at this point in the history
  • Loading branch information
Dhghomon committed Jan 3, 2025
1 parent b06c4ed commit 8a6e9b8
Showing 1 changed file with 57 additions and 8 deletions.
65 changes: 57 additions & 8 deletions src/content/doc-surrealql/datamodel/idioms.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1170,38 +1170,63 @@ Possible output of the final query:

<Since v="v2.2.0" />

SurrealDB has a number of built-in algorithms that allow recursive queries to collect all paths, all unique nodes, and to find the shortest path to a record. The syntax is as follows:

* `{..+path}`: used to collect all walked paths.
* `{..+collect}`: used to collect all unique nodes walked.
* `{..+shortest=record:id}`: used to find the shortest path to a specified record id, such as `person:tobie` or `person:one`.

The first record in any of these paths can be included by adding `+inclusive` to the end.
The originating (first) record is excluded from these paths. To include the first record, `+inclusive` can be added to the syntax above.

* `{..+path+inclusive}`
* `{..+collect+inclusive}`
* `{..+shortest=record:id+inclusive}`

To learn these three paths, take the following example showing a small network of friends. The network begins with `person:you`, follows up with two friends, then three acquaintances known by these friends, and finally a movie star (`person:star`) who is known by one of the acquaintances.
To demonstrate the output of these three algorithms, take the following example showing a small network of friends. The network begins with `person:you`, followed by two friends (`person:friend1`, `person:friend2`), then three acquaintances known by these friends (`person:acquaintance1`, `person:acquaintance2`, `person:acquaintance3`), and finally a movie star (`person:star`) who is known by one of the acquaintances.

```surql
CREATE
person:you,
person:friend1, person:friend2,
person:acquaintance1, person:acquaintance2, person:acquaintance3,
person:star;
person:star
-- Give each of them a name like 'you', 'friend1', etc.
SET name = id.id();
-- You have two friends
RELATE person:you->knows->[person:friend1, person:friend2];
-- The first friend only knows one other person
-- The first friend is shy and only knows one other person
RELATE person:friend1->knows->person:friend2;
-- The second is very social and is friends with many people you barely know
-- The second friend is very social and knows many people you barely know
RELATE person:friend2->knows->[person:acquaintance1, person:acquaintance2, person:acquaintance3];
-- One of those people is friends with a movie star
-- One of those people knows the movie star
RELATE person:acquaintance3->knows->person:star;
```

This representation of this small network of friends allows us to visualize the issues that these three algorithms solve. Using `+path` will output all of the possible paths from `person:you`, `+collect` will collect all of the records in this network, and `+shortest=person:star` will find the shortest path.

```
┌───►person:acquaintance1
┌───────► person:friend1 │
│ │ │
│ │ │
│ │ ┼───►person:acquaintance2 person:star
person:you │ │ ▲
│ │ │ │
│ ▼ │ │
└────────► person:friend2──────┤ │
│ │
│ │
│ │
└───►person:acquaintance3───────────────┘
```

To use these algorithms, follow them with the path that should be followed, in this case `->knows->person`.

Adding `+path` will output all of the possible paths starting from `person:you`. Note that there are two ways to get from `person:one` to the movie star at `person:star`, one of which is shorter than the other.
Adding `+path` will output all of the possible paths starting from `person:you`. As the output is fairly short, we can see that there are two ways to get from `person:one` to the movie star at `person:star`, one of which is one step shorter than the other.

```surql
person:you.{..+path}->knows->person;
Expand Down Expand Up @@ -1241,7 +1266,7 @@ person:you.{..+path}->knows->person;
]
```

To get this shortest path on its own, change the algorithm to `+shortest=person:star`.
To get the database to find the shortest path instead, change the algorithm to `+shortest=person:star`.

```surql
person:you.{..+shortest=person:star}->knows->person;
Expand Down Expand Up @@ -1328,6 +1353,30 @@ person:you.{..2+shortest=person:star}->knows->person;
[]
```

As shown in the previous section, parentheses can be used to show which path should be repeated during the recursion. Once this is over, the destructuring operator, methods and so on can be used to modify the output. The query can also be written over multiple lines if desired.

```surql
-- Start with you
person:you
-- Get the shortest path
.{..+shortest=person:star+inclusive}
-- by following ->knows->person
(->knows->person)
-- then grab the names
.name
-- and capitalize each one
.map(|$n| $n.uppercase());
```

```surql title="Output"
[
'YOU',
'FRIEND2',
'ACQUAINTANCE3',
'STAR'
]
```

As these three use their own algorithms to follow a path, any attempt to construct your own path using `.@` will result in an error.

```surql
Expand Down

0 comments on commit 8a6e9b8

Please sign in to comment.