Skip to content

Commit

Permalink
Start path/collect/shortest for recursive queries
Browse files Browse the repository at this point in the history
  • Loading branch information
Dhghomon committed Jan 3, 2025
1 parent 4ce0b98 commit b06c4ed
Showing 1 changed file with 175 additions and 0 deletions.
175 changes: 175 additions & 0 deletions src/content/doc-surrealql/datamodel/idioms.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,181 @@ Possible output of the final query:
}
```

#### Collecting paths, collecting unique nodes, finding shortest path

<Since v="v2.2.0" />

* `{..+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.

* `{..+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.

```surql
CREATE
person:you,
person:friend1, person:friend2,
person:acquaintance1, person:acquaintance2, person:acquaintance3,
person:star;
-- You have two friends
RELATE person:you->knows->[person:friend1, person:friend2];
-- The first friend 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
RELATE person:friend2->knows->[person:acquaintance1, person:acquaintance2, person:acquaintance3];
-- One of those people is friends with a movie star
RELATE person:acquaintance3->knows->person:star;
```

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.

```surql
person:you.{..+path}->knows->person;
```

```surql title="Output"
[
[
person:friend2,
person:acquaintance2
],
[
person:friend2,
person:acquaintance1
],
[
person:friend1,
person:friend2,
person:acquaintance2
],
[
person:friend1,
person:friend2,
person:acquaintance1
],
[
person:friend2,
person:acquaintance3,
person:star
],
[
person:friend1,
person:friend2,
person:acquaintance3,
person:star
]
]
```

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

```surql
person:you.{..+shortest=person:star}->knows->person;
```

```surql title="Output"
[
person:friend2,
person:acquaintance3,
person:star
]
```

Using `+collect` will collect all of the unique collected records. As this collection is created by moving recursively one level at a time, the output will show the closest connections first and least close connections at the end.

```surql
person:you.{..+collect}->knows->person;
```

```surql title="Output"
[
person:friend1,
person:friend2,
person:acquaintance2,
person:acquaintance1,
person:acquaintance3,
person:star
]
```

Adding `+inclusive` will show the same output, except that the original `person:one` record will also be present.

```surql
person:you.{..+shortest=person:star+inclusive}->knows->person;
person:you.{..+collect+inclusive}->knows->person;
```

```surql title="Output"
-------- Query --------
[
person:you,
person:friend2,
person:acquaintance3,
person:star
]
-------- Query --------
[
person:you,
person:friend1,
person:friend2,
person:acquaintance2,
person:acquaintance1,
person:acquaintance3,
person:star
]
```

The unbounded syntax `..` can be replaced with a bounded range to ensure that the recursive query only goes down to a certain deth. For example, using `..2` with `+collect` will show all first- and second-degree relations starting from `person:you`:

```surql
person:you.{..2+collect}->knows->person;
```

```surql title="All first- and second-degree relations"
[
person:friend1,
person:friend2,
person:acquaintance2,
person:acquaintance1,
person:acquaintance3
]
```

Doing the same with `+shortest=person:star` will return an empty array, because there is no path from `person:you` to `person:star` that only requires two hops.

```surql
person:you.{..2+shortest=person:star}->knows->person;
```

```surql title="Output"
[]
```

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
person:1.{..+path}.{
id,
next: ->knows->person.@
};
```

```surql
'Can not construct a recursion plan when an instruction is provided'
```

## Combining Idiom Parts

Idioms can combine multiple parts to navigate complex data structures seamlessly.
Expand Down

0 comments on commit b06c4ed

Please sign in to comment.