Search code examples
modelhierarchyrolesvaticle-typedbvaticle-typeql

How to model roles hierarchies (and relations between them) with Grakn / Graql?


I'm starting to use Grakn and I'm having a hard time with how roles and relationships are "linked". Specifically, I am having some difficulty modeling role hierarchies.

Considering a fictional example with two scenarios, first suppose I have only two types: person and object; and a purchasing relationship between a customer role hierarchy and a product role hierarchy.

So, I would have something like:

type: person

  • role: customer level 1
  • role: customer level 2 (sub customer level 1)
  • role: customer level 3 (sub customer level 2)

    ...

type: object

  • role: product level 1
  • role: product level 2 (sub product level 1)
  • role: product level 3 (sub product level 2) ...

The relationship is unique (buys) and is used to relate roles considering the respective levels in the hierarchy:

     customer level 1 --- buys --- product level 1
     customer level 2 --- buys --- product level 2
     customer level 3 --- buys --- product level 3

In a second scenario, I would have only one role hierarchy, the customer one and the object type would have only one role: product. So, the relationships would be something like:

     customer level 1 --- buys --- product
     customer level 2 --- buys --- product
     customer level 3 --- buys --- product

How can I model this kind of problem with Grakn (Graql)? I would appreciate it if someone could show how this (or similar) problem would be modeled with Graql.


Solution

  • To construct a role hierarchy in Graql you need to override a parent role with a child by defining a child relation.

    I think that for your first case there are two possible options, depending upon what you want to restrict:

    define
    
    buys sub relation,
      abstract,
      relates product,
      relates customer;
    
    buys-level-1 sub buys,
      relates product-level-1 as product,
      relates customer-level-1 as customer;
    
    buys-level-2 sub buys-level-1,
      relates product-level-2 as product-level-1,
      relates customer-level-2 as customer-level-1;
    
    buys-level-3 sub buys-level-2,
      relates product-level-3 as product-level-2,
      relates customer-level-3 as customer-level-2;
    
    person sub entity,
      plays customer-level-1,
      plays customer-level-2,
      plays customer-level-3;
    
    object sub entity,
      plays product-level-1,
      plays product-level-2,
      plays product-level-3;
    

    In this scenario, if you inserted a buys-level-3 relation:

    insert 
    $per isa person; $obj isa object;
    $b(product-level-3: $obj, customer-level-3: $per) isa buys-level-3;
    

    You will be able to match for it using buys-level-2, buys-level-1 and buys. So this query will get back the person and the relation we just inserted:

    match $b(customer-level-1: $per) isa buys-level-1; get;
    

    Alternatively, you can change the restriction like this:

    buys-level-3 sub buys,
      relates product-level-3 as product,
      relates customer-level-3 as customer;
    

    In this case the match we made would not return the inserted relation or person. Let the restrictions that you want to impose on your queries/data guide you here for the best model choice.

    The second scenario is then easy to see, we have:

    define
    
    buys sub relation,
      abstract,
      relates product,
      relates customer;
    
    buys-level-1 sub buys,
      relates product,
      relates customer-level-1 as customer;
    
    buys-level-2 sub buys-level-1,
      relates product,
      relates customer-level-2 as customer-level-1;
    
    buys-level-3 sub buys-level-2,
      relates product,
      relates customer-level-3 as customer-level-2;
    
    person sub entity,
      plays customer-level-1,
      plays customer-level-2,
      plays customer-level-3;
    
    object sub entity,
      plays product;
    

    In any of these scenarios, you can retrieve all buys relations and their roleplayers with:

    match $b(customer: $per, product: $obj) isa buys; get;