Skip to main content
Version: Next

What is a relationship?

A relationship is a named associate between exactly two entities, a source and a destination.

From the above graph, a Group entity can be linked to a User entity via a HasMember relationship. Note that the name of the relationship reflects the direction, i.e. pointing from Group to User. This is due to the fact that the actual metadata aspect holding this information is associated with Group, rather than User. Had the direction been reversed, the relationship would have been named IsMemberOf instead. See Direction of Relationships for more discussions on relationship directionality. A specific instance of a relationship, e.g. urn:li:corpGroup:group1 has a member urn:li:corpuser:user1, corresponds to an edge in the metadata graph.

Relationships are meant to be "entity-neutral". In other words, one would expect to use the same OwnedBy relationship to link a Dataset to a User and to link a Dashboard to a User. As Pegasus doesn’t allow typing a field using multiple URNs (because they’re all essentially strings), we resort to using generic URN type for the source and destination. We also introduce a @Relationship annotation to limit the allowed source and destination URN types.

While it’s possible to model relationships in rest.li as association resources, which often get stored as mapping tables, it is far more common to model them as "foreign keys" field in a metadata aspect. For instance, the Ownership aspect is likely to contain an array of owner’s corpUser URNs.

Below is an example of how a relationship is modeled in PDL. Note that:

  1. This aspect, nativeGroupMembership would be associated with a corpUser
  2. The corpUser's aspect points to one or more parent entities of type corpGroup
namespace com.linkedin.identity

import com.linkedin.common.Urn

/**
* Carries information about the native CorpGroups a user is in.
*/
@Aspect = {
"name": "nativeGroupMembership"
}
record NativeGroupMembership {
@Relationship = {
"/*": {
"name": "IsMemberOfNativeGroup",
"entityTypes": [ "corpGroup" ]
}
}
nativeGroups: array[Urn]
}

Direction of Relationships

As relationships are modeled as directed edges between nodes, it’s natural to ask which way should it be pointing, or should there be edges going both ways? The answer is, "doesn’t really matter." It’s rather an aesthetic choice than technical one.

For one, the actual direction doesn’t really impact the execution of graph queries. Most graph DBs are fully capable of traversing edges in reverse direction efficiently.

That being said, generally there’s a more "natural way" to specify the direction of a relationship, which closely relate to how the metadata is stored. For example, the membership information for an LDAP group is generally stored as a list in group’s metadata. As a result, it’s more natural to model a HasMember relationship that points from a group to a member, instead of a IsMemberOf relationship pointing from member to group.

High Cardinality Relationships

See this doc for suggestions on how to best model relationships with high cardinality.