This example shows how to handle a schema that makes use of a backlink. We’ll use a linked-list structure to represent a sequence of events.
We’ll start with this schema:
type Event {
required name: str;
prev: Event;
# ... more properties and links
}
We specify a prev
link because that will make adding a new
Event
at the end of the chain easier, since we’ll be able to
specify the payload and the chain the Event
should be appended to
in a single insert
. Once we’ve updated the schema
file we proceed with our first migration:
$
edgedb migration create
did you create object type 'default::Event'? [y,n,l,c,b,s,q,?] > y Created ./dbschema/migrations/00001.edgeql, id: m1v3ahcx5f43y6mlsdmlz2agnf6msbc7rt3zstiqmezaqx4ev2qovq
$
edgedb migrate
Applied m1v3ahcx5f43y6mlsdmlz2agnf6msbc7rt3zstiqmezaqx4ev2qovq (00001.edgeql)
We now have a way of chaining events together. We might create a few events like these:
db> ... ... ...
select Event {
name,
prev: { name },
};
{ default::Event {name: 'setup', prev: {}}, default::Event {name: 'work', prev: default::Event {name: 'setup'}}, default::Event {name: 'cleanup', prev: default::Event {name: 'work'}}, }
It seems like having a next
link would be useful, too. So we can
define it as a computed link by using backlink notation:
type Event {
required name: str;
prev: Event;
link next := .<prev[is Event];
}
The migration is straightforward enough:
$
edgedb migration create
did you create link 'next' of object type 'default::Event'? [y,n,l,c,b,s,q,?] > y Created ./dbschema/migrations/00002.edgeql, id: m1qpukyvw2m4lmomoseni7vdmevk4wzgsbviojacyrqgiyqjp5sdsa
$
edgedb migrate
Applied m1qpukyvw2m4lmomoseni7vdmevk4wzgsbviojacyrqgiyqjp5sdsa (00002.edgeql)
Trying out the new link on our existing data gives us:
db> ... ... ... ...
select Event {
name,
prev_name := .prev.name,
next_name := .next.name,
};
{ default::Event { name: 'setup', prev_name: {}, next_name: {'work'}, }, default::Event { name: 'work', prev_name: 'setup', next_name: {'cleanup'}, }, default::Event { name: 'cleanup', prev_name: 'work', next_name: {}, }, }
That’s not quite right. The value of next_name
appears to be a set
rather than a singleton. This is because the link prev
is
many-to-one and so next
is one-to-many, making it a multi link.
Let’s fix that by making the link prev
a one-to-one, after all
we’re interested in building event chains, not trees.
type Event {
required name: str;
prev: Event {
constraint exclusive;
};
link next := .<prev[is Event];
}
Since the next
link is computed, the migration should not need any
additional user input even though we’re reducing the link’s
cardinality:
$
edgedb migration create
did you create constraint 'std::exclusive' of link 'prev'? [y,n,l,c,b,s,q,?] > y Created ./dbschema/migrations/00003.edgeql, id: m17or2bfywuckdqeornjmjh7c2voxgatspcewyefcd4p2vbdepimoa
$
edgedb migrate
Applied m17or2bfywuckdqeornjmjh7c2voxgatspcewyefcd4p2vbdepimoa (00003.edgeql)
The new next
computed link is now inferred as a single
link
and so the query results for next_name
and prev_name
are
symmetrical:
db> ... ... ... ...
select Event {
name,
prev_name := .prev.name,
next_name := .next.name,
};
{ default::Event {name: 'setup', prev_name: {}, next_name: 'work'}, default::Event {name: 'work', prev_name: 'setup', next_name: 'cleanup'}, default::Event {name: 'cleanup', prev_name: 'work', next_name: {}}, }