Links can contain properties. These are distinct from links themselves (which we refer to as simply “links”) and are used to store metadata about a link. Due to how they’re persisted under the hood, link properties have a few additional constraints: they’re always single and optional.
In practice, link properties are best used with many-to-many relationships
(multi
links without any exclusive constraints). For one-to-one,
one-to-many, and many-to-one relationships the same data should be stored in
object properties instead.
Let’s a create a Person.friends
link with a strength
property
corresponding to the strength of the friendship.
type Person {
required property name -> str { constraint exclusive };
multi link friends -> Person {
property strength -> float64;
}
}
type Person {
required property name -> str { constraint exclusive };
multi link friends -> Person {
property strength -> float64;
constraint expression on (
__subject__@strength >= 0
);
}
}
To index on a link property, you must declare an abstract link and extend it.
abstract link friendship {
property strength -> float64;
index on (__subject__@strength);
}
type Person {
required property name -> str { constraint exclusive };
multi link friends extending friendship -> Person;
}
The @strength
property is specified in the shape of the select
subquery. This is only valid in a subquery inside an insert
statement.
insert Person {
name := "Bob",
friends := (
select detached Person {
@strength := 3.14
}
filter .name = "Alice"
)
}
We are using the detached
operator to unbind the
Person
reference from the scope of the insert
query.
When doing a nested insert, link properties can be directly included in the
inner insert
subquery.
insert Person {
name := "Bob",
friends := (
insert Person {
name := "Jane",
@strength := 3.14
}
)
}
update Person
filter .name = "Bob"
set {
friends += (
select .friends {
@strength := 3.7
}
filter .name = "Alice"
)
};
The example updates the @strength
property of Bob’s friends link to
Alice to 3.7.
In the context of multi links the += operator works like an an insert/update operator.
To update one or more links in a multi link, you can select from the current
linked objects, as the example does. Use a detached
selection if you
want to insert/update a wider selection of linked objects instead.
edgedb> ....... ....... ....... ....... .......
select Person {
friends: {
name,
@strength
}
};
{ default::Person {name: 'Alice', friends: {}}, default::Person { name: 'Bob', friends: { default::Person {name: 'Alice', @strength: 3.7} } }, }
Specifying link properties of a computed backlink in your shape is supported as of EdgeDB 3.0.
If you have this schema:
type Person {
required name: str;
multi follows: Person {
followed: datetime {
default := datetime_of_statement();
};
};
multi link followers := .<follows[is Person];
}
this query will work as of EdgeDB 3.0:
select Person {
name,
followers: {
name,
@followed
}
};
even though @followed
is a link property of follows
and we are
accessing is through the computed backlink followers
instead.
If you need link properties on backlinks in earlier versions of EdgeDB, you can use this workaround:
select Person {
name,
followers := .<follows[is Person] {
name,
followed := @followed
}
};