Query to find references to the subtree

Hi there!

I am working on implementing emf on top of orientdb. My task now is to find all objects that refer to a specific one.

Let’s say we have two trees: a-> b-> c, x-> y-> z. Here the arrow means the “contains” link.
Each element can refer to any other element. e.g. b-> y, z-> y. Here the arrow means the link refers.

I need to make a query that finds all root edements whose subtree refers to the subtree of the given element. In our example, we must find the element a, which refers to the element x through the connection b-> y, but we must exclude the element x, which refers to itself through the connection z-> y.

If necessary (although not desirable), I can mark the links b-> y and z-> y as external and internal, respectively, at the time of their creation.

First try:

select inE (’_Refers’) [isExternal = true] .outV () from (traverse out (’_Contains’) from # 186: 0)

We found all external elements that refers to our subtree.

Now, we need to find the root element and make distinct.
How can I change this query?
Maybe I should look towards match?

attachment:

drop class _Object if exists unsafe;
create class _Object extends V;
create property _Object.name STRING;
create index _Object_pk on _Object(name) unique;
drop class _Contains if exists unsafe;
create class _Contains extends E;
drop class _Refers if exists unsafe;
create class _Refers extends E;
create property _Refers.isExternal BOOLEAN;
insert into _Object(name) values ('a'), ('b'), ('c'), ('x'), ('y'), ('z');
create edge _Contains from (select from _Object where name = 'a') to (select from _Object where name = 'b');
create edge _Contains from (select from _Object where name = 'b') to (select from _Object where name = 'c');
create edge _Contains from (select from _Object where name = 'x') to (select from _Object where name = 'y');
create edge _Contains from (select from _Object where name = 'y') to (select from _Object where name = 'z');
create edge _Refers from (select from _Object where name = 'b') to (select from _Object where name = 'y') set isExternal = true;
create edge _Refers from (select from _Object where name = 'z') to (select from _Object where name = 'y') set isExternal = false;

ok. this query do the job

select distinct * from (
  traverse in('_Contains') from (
    select expand(inE('_Refers')[isExternal = true].outV()) from (
      traverse out('_Contains') from (select from _Object where name='x')
    )
  )
)
where in('_Contains').size() == 0

and without ugly isExternal:

select distinct * from (
  traverse in('_Contains') from (
    select expand(in('_Refers')) from (
      traverse out('_Contains') from (select from _Object where name='x')
    )
  )
)
where in('_Contains').size() == 0 and name != 'x'