How to query role types in a TypeDB relation? - vaticle-typedb

Suppose I have the following in the schema:
define
person sub entity, plays employment:employee;
company sub entity, plays employment:employer;
employment sub relation, relates employee, relates employer;
Then it imposes the restriction that employer must be of type company and employee must be of type person.
How do I find about this restriction through a query?
So far the best that I know is:
match $x sub relation; get $x;
It does show that employment is a relation. But it doesn't show the role types that are allowed/ permitted. How to query that?

match $x sub relation;
$x relates $y;
get $x, $y;
You can use the same constructs for querying the schema (or data) as you did to write it. So you can also find which types play the roles through the query:
match $x sub relation;
$x relates $y;
$z plays $y;
get $x, $y, $z;

Related

How to query rules in a TypeDB database?

In my schema I think I defined this rule:
define rule transitive-hierarchy-rule:
when {
(before: $a, after: $b) isa hierarchy;
(before: $b, after: $c) isa hierarchy;
} then {
(before: $a, after: $c) isa hierarchy;
};
Notice from the documentation:
"facts defined via rules are not stored in the knowledge graph. [...]
However, by defining the rule in the schema, at query time the extra
fact will be generated."
Also notice from the documentation:
Currently, for a match query to trigger reasoning and obtain
inferences from rules, you must use a read transaction. We are working
towards enabling reasoning in write transactions in subsequent
releases.
However in my query match (before: $x, after: $y) isa hierarchy inside a read transaction doesn't return the expected results:
{ $x iid 0x826e800b8000000000000000 isa task; $y iid 0x826e80048000000000000002 isa task; }
{ $x iid 0x826e800a8000000000000000 isa task; $y iid 0x826e800b8000000000000000 isa task; }
The above two results I had explicity defined. I was expecting the third result to be inferred via the rule.
So I am trying to debug the situation. Could it be possible that I did not define the rule properly?
So question: how do I query more about the rules that have been defined in the database schema?
Have you been sure to turn on inference? The 'infer' option must be turned on for rules to be triggered whilst running queries.
See the infer option for the java client API: https://docs.vaticle.com/docs/client-api/java#options

Delete duplicate entities with the same attribute values

I am using Grakn. I'd like to delete a duplicate entity with the same attribute value (name). This is what I have now:
test> match $p isa person, has name $n; get;
{$p id V4176 isa person; $n "John" isa name;}
{$p id V40968336 isa person; $n "John" isa name;}
I would like to delete the one with id V4176. However if I do the query below, it deletes both entities:
match $p isa person, has name "John"; delete $p;
How do I just delete one of the two?
Grakn assigns an auto-generated id to each instance. Although this id is generated by Grakn solely for internal use, it is indeed possible to find an instance with its Grakn id. To do so, we use the id keyword followed by the id assigned to the instance by Grakn.
match $p id V4176; delete $p;
Now, the reason your query
match $p isa person, has name "John"; delete $p;
deletes both entities is because both of them are person and has name John, so they both match you match clause.
You can find more information here https://dev.grakn.ai/docs/query/match-clause#one-particular-instance

Query inner elements based on role in grakn

I have a keyspace name 'server' in grakn with one entity named 'node' having an attribute "name". This keyspace is having only one relation named 'node_relation' that connects entities. The entity node acts the role as 'base' and 'dependent' in the node_relation.
This graph is aligned in such a way that all the elements in the left side are acting as base and right side act ad dependent in the node_relation.
I need to query nodes that act as base node for an entity and if the queried node has any node that is acting as a base node, I need to get it also until the queried node is not having any nodes with role base.
For example, if I want all nodes with role base for node named "F", I should get the answer as of "A,B,C,D,E,DD,EE,FF,XX,YY,ZZ".
Currently i am using the query
match $x isa node, has name "F";$y isa node;$rel(base:$x,$y);get $y;**
This query return E and DD as result and i will execute this query until a node is not having any node with role base.
Is their any some way to get all the node in a single query ?
Disclaimer: I'm pretty new to Grakn still.
The kind of relation you are looking for is transitive (if a->b and b->c then a->c). You can use Grakn rules to model this relation then use it in your query; Grakn infers the transitive relation when you execute the query.
Here's how I wrote the rules, include this in your schema.gql:
node_superrelation sub relation,
relates base,
relates dependent;
node-relation-is-superrelation-rule sub rule,
when {
(base: $a, dependent: $b) isa node_relation;
},
then {
(base: $a, dependent: $b) isa node_superrelation;
};
node-superrelation-is-transitive-rule sub rule,
when {
(base: $a, dependent: $b) isa node_superrelation;
(base: $b, dependent: $c) isa node_superrelation;
},
then {
(base: $a, dependent: $c) isa node_superrelation;
};
Now you can use the following query to get all bases of node F. Note that we specifically request those related by a node_superrelation.
match $d isa node, has name "F";$b isa node; $rel(base:$b,dependent:$d) isa node_superrelation;get $b;
You could make node_relation transitive and achieve this in one rule, but then queries using node_relation of F would always include all of the results without using a limit, which is probably not what you want. You could also define new roles for node_superrelation, which may also further simplify things, or use the shared roles to some other advantage. Hopefully, you can see that Grakn's rules are really very powerful and should let you describe these kinds of relations in a way that makes sense for your model!
Hope this helps!
EDIT: Just to add quickly that the convention in Grakn is to use hyphens rather than underscores.

Is there a way to 'get' all connected entities and their attributes connected to a specific instance of an entity?

I want to display all the data points for a specific instance of an entity.
I understand how to write the query in a specific form but I want it to be more general and be more concise.
This is what I currently have:
match
$t isa technology, has version "v9.5";
$as isa app-server, has database-server $ds, has dot-net-network $dnn, has XXXXXX $x1, has XXXXXX $x2;
$ds isa database-server, has XXXXXX $x3, has XXXXXX $x4;
$r1(container: $t, containee: $as);
$r2(container: $t, containee: $ds);
get; offset 0; limit 30;
There are several more entities connecting to my container.
In general in Graql we can make ambiguous queries by providing less constraints in the query, or changing a constraint to a more relaxed one.
In your case, I believe you want to ask a question specifically about an entity instance, described by this pattern: $t isa technology, has version "v9.5";. You want to find the entities it is connected to via a relation. You then wish to find all of the attributes of those connected entities, but without specifying all of the types of attribute those entities could own according to the schema.
The most generic way to get the connected concepts is:
match
$t isa technology, has version "v9.5";
$r($t, $e);
get $e;
If you want connected entities only:
match
$t isa technology, has version "v9.5";
$r($t, $e);
$e isa entity;
get $e;
This is because all of your user-defined entities inherit from entity. You can do the same for relation and attribute, or thing which is the super type of all three.
The full answer to get all of the attributes of a concept, is to use the same principal, giving the base type attribute:
match
$t isa technology, has version "v9.5";
$r($t, $e);
$e isa entity, has attribute $a;
get $e, $a;
Bonus
You can then find attributes common to two patterns, in this case two technology instances:
match
$t1 isa technology, has version "v9.5";
$e1 isa entity, has attribute $a;
$r1($t1, $e1);
$t2 isa technology, has version "v9.6";
$e2 isa entity, has attribute $e;
$r2($t2, $x2);
get $a;

Using an Entity's methods inside a query in Doctrine

I have a table of Customers with fields name, addressLine1, addressLine2 and postcode. The corresponding entity also has a method called address that returns the 2 address lines and the postcode concatenated together with comma/space separation, ignoring any empty fields.
I want to return a list of customers sorted by name and then address (for any customers with the same name). Currently I try
$this->getEntityManager()->createQuery(
'SELECT c FROM AppBundle:Customer c ORDER BY c.name ASC, c.address ASC'
)->getResult();
but I cannot use the method Customer::address() in the query like this. I get the error
Error: Class AppBundle\Entity\Customer has no field or association named address
Is there a way I can use an Entity's methods inside a query like this?
Short answer - no, and you don't really want to. You're conflating PHP logic with SQL logic. Your address() function is a pure PHP function. Even though it is using relationships within your entity, Doctrine itself has no way of knowing about it. Your function is literally returning a string, so how would it know how to convert that to SQL for your WHERE clause?
Just change your original query to this:
$this->getEntityManager()->createQuery('
SELECT c
FROM AppBundle:Customer c
ORDER BY c.name ASC, c.addressLine1 ASC, c.addressLine2 ASC, c.postcode ASC
')->getResult();
I suppose you could pseudo-do what you want like this:
Customer Entity:
public static function addressSort()
{
return ' c.addressLine1 ASC, c.addressLine2 ASC, c.postcode ';
}
and then do
$this->getEntityManager()->createQuery('
SELECT c
FROM AppBundle:Customer c
ORDER BY c.name ASC, ' . Customer::addressSort()
)->getResult();
However, now you're mixing PHP and SQL even further and I very highly recommend that you do NOT do this.

Resources