Basic Graph Traversal
Starting Traversals
To start a graph traversal, one needs an entry point
- listing all nodes of a specific type (similar to a full table scan)
- from a tag (both nodes and relations can be tagged)
- we already have a concrete reference (ZefRef or EZefRef) to a node or relation on the graph and can traverse from there
1. Listing All Instances of a Type
gs = g | now # get the latest graph slice
gs | all # lists all instances that exist in this graph slice
gs | all[ET] # list all entities that exist in this graph slice (RT/AET also valid)
gs | all[ET.Person] # returns a LazyValue[List[ZefRef]]
gs | all[AET.Float] # all atomic entities of type Float
gs | all[RT.FirstName] # relations have types too. A ZefRef can also refer to a relation
gs | all[(ET.Person, RT.FirstName, AET.String)] # more specific: source/target type can also be included
All the examples return lists of instances in lazy form which exist in the graph slice gs
.
Analogous operations can be done on the eternal graph: This will answer the question "show all instances that ever existed at any time".
g | all
g | all[ET]
g | all[ET.Person]
...
2. Entering via a Tag
z_dog = gs['my favorite dog'] # any string can be used as a tag within the context of a graph slice
Traversing
first_names = all_persons | Out[RT.FirstName] | value # this is still lazy
(gs
| all[ET.Person]
| filter[lambda z: z | Out[RT.FirstName] == 'Yolandi']
| single # there can only one (otherwise single will fail)
| collect # trigger evaluation
)
```python
```python
```python
```python
```python
```python
```python
## structure
---
Normal traversal
```python
z1 | outs
z1 | ins
z1 | Outs[RT.FriendOf]
z1 | out_rels[RT.FriendOf]
z_rel = z1 | out_rel[RT.FriendOf]
z_rel | target
z_rel | source
...
Time travel
z1 | to_frame[g | now]
z1 | time_travel[-2] # moves the reference frame: go back two slices
z1 | time_travel[+5]
z_tx | time_travel[-2] # if z_tx is a ZefRef, it also only moves the reference frame, even if z_tx points to a TX
z1 | time_travel[Time('2021 December 4 15:31:00 (+0100)')]
# z1 | exists[my_graph_slice]
z_zr | contained_in[my_graph_slice]
z_ezr | contained_in[g]
Given a RAE, look at all events in its past:
z_ae | instantiated # when was the AET instantiated
z_ae | value_assigned # a List[ZefRef[TX]] when values were assigned
z_ae | terminated
Given a TX, explore what happened there
my_tx | instantiated # show all instantiated RAEs
my_tx | terminated
my_tx | value_assigned
my_tx | merged
my_tx | affected
given a ZefRef / EZefRef pointing to a TX, get the graph slice / state following this TX
z_tx_zr | to_graph_slice # ZefRef -> GraphSlice, discards reference frame, returns a GraphSlice
z_tx_ezr | to_graph_slice # EZefRef -> GraphSlice returns a GraphSlice
Conversely, given a graph slice, get the TX that precedes it.
my_graph_slice | to_tx # => ZefRef[TX]
The reference frame is also that of the GraphSlice.
Temporal Traversals
Relative traversals: there are
z_zr | time_travel[-2] # move the reference frame back 2 time slices, keep pointing at the same object
z_zr | time_travel[-3*units.hours] # go back 2 time slices
my_graph_slice | time_travel[+3] # it can also be used on graph slices directly
Absolute traversals: the 'now' operator is the bridge between modeled time and execution time. It takes one to the point in time of execution, i.e. it cannot be used inside any pure function.
now() # -> Time. returns current time (of type Time)
g | now # Graph -> GraphSlice
gs | now # GraphSlice -> GraphSlice
z_zr_my_entity | now # ZefRef -> ZefRef: fast forward to very latest reference frame at time of execution
z_ezr_my_entity | now # EZefRef -> ZefRef: fast forward to very latest reference frame at time of execution