Discussion Forum

Retrieving Roles in relations

I have some unexpected behaviour regarding roles.
In the query I also want to retrieve the role that an entity has in a relation. But I besides the expected result I also get an additional answer that looks like an abstract role and relation.

I have an example where a person alpha is a friend with beta but not the other way around.

Below I have an example.

role_example::data::read> match 
                          $x isa person, has name "alpha";
                          ($x, $r:$y) isa is_friends_with;
                          $y has name $ans;
                          get $ans, $r;
                          
{ $r type is_friends_with:target sub relation:role; $ans "beta" isa name; }
{ $r type relation:role; $ans "beta" isa name; }
answers: 2, duration: 164 ms

So I get an answer with relation:role. This is not what I expect and in my original database this would give wrong answers when I aggregate with the count function.

Below is the schema and the data for this example:

With the schema:

define

################
## ATTRIBUTES ##
################

name sub attribute, value string;

##############
## ENTITIES ##
##############

person sub entity,
  owns name @key,
  plays is_friends_with:source,
  plays is_friends_with:target;

###############
## RELATIONS ##
###############

is_friends_with sub relation,
  relates source,
  relates target;

And the data:

insert

##############
## ENTITIES ##
##############

$person1 isa person,
  has name "alpha";

$person2 isa person,
  has name "beta";

###############
## RELATIONS ##
###############

$fship (source: $person1, target: $person2) isa is_friends_with;

Yes this is a quirk of being a declarative language with subtyping! The super-type of every role is actually relation:role. So when you variabilise a role, you’ll also get all super types of the role (as you do with any variabilised type).

For example:

match $x isa $t, has name "alpha"; get $t;

you’ll get person, entity, and thing for the type of the person with name alpha.

To restrict this, for instances of types, you’ll do the following:

match $x isa! $t, has name "alpha"; get $t;

which will only get the exact type of the person.

Unfortunately, there is no such syntax for role types… here’s the next best thing:

match 
    $x isa person, has name "alpha";
    ($x, $r:$y) isa! $rel_type; $rel_type type is_friends_with;
    $rel_type relates $r;
    $y has name $ans; 
    get $ans, $r;

So basically what we do is restrict the relation to only be the type is_friends_with, and force $r to be a role that the relation type relates directly.