OrientDB - множественный LEFT JOIN

Давайте попробуем разобраться, как работать с джоинами классов.

Данную статью следует читать, если Вы разобрались с предыдущими статьями, поэтому сначала изучите их.

И для начала, кому интересно:

Суть задачи

Мы имеем 2 таблицы (2 класса вершин):

  • Cities - города
  • Phones - телефоны

Необходимо узнать, по какому телефону можно дозвониться в город Rome.

Поехали

Первым делом создадим классы-вершин и добавим в них данные:

create class Cities extends V

create vertex Cities set city="Rome"
create vertex Cities set city="London"
create vertex Cities set city="Berlin"

create class Phones extends V

create vertex Phones set phone = "123456789"
create vertex Phones set phone = "567891234" 

Получили такой результат:

orientdb {cities}> select from Cities

----+-----+------
#   |@RID |city
----+-----+------
0   |#16:0|Rome
1   |#16:1|London
2   |#16:2|Berlin
----+-----+------

orientdb {cities}> select from Phones

----+-----+---------
#   |@RID |phone
----+-----+---------
0   |#17:0|123456789
1   |#17:1|567891234
----+-----+---------

Отлично, теперь укажим, куда можно дозониться по имеющимся телефонам. Это можно сделать указывая ребра (EDGE).

Первым делом хочу сказать, что в предыдущих статьях, я намеренно упрощал работу с графами, тем самым делая немного неправильное их использование. Это было сделано, чтобы было проще понять, как работают графы, но не переживайте, теперь я покажу, как правильно.

В предыдущих примерах мы создавали ребра, даже не прибегая к созданию класса-ребер:

1. Раньше (неправильно) 2. Теперь (правильно)

create edge from #16:0 to #17:0

и получали:

orientdb {cities}> select from Cities

----+-----+------+-----
#   |@RID |city  |out_
----+-----+------+-----
0   |#16:0|Rome  |#17:0
1   |#16:1|London|null
2   |#16:2|Berlin|null
----+-----+------+-----

select from Cities where out_.phone = '123456789'

----+-----+-----+----
#   |@RID |out_|city
----+-----+-----+----
0   |#16:0|#17:0|Rome
----+-----+-----+----

create edge CitiesPhones from #16:0 to #17:0

и получили:

orientdb {cities}> select from Cities

----+-----+------+----------------
#   |@RID |city  |out_CitiesPhones
----+-----+------+----------------
0   |#16:0|Rome  |#17:0
1   |#16:1|London|null
2   |#16:2|Berlin|null
----+-----+------+----------------

select from Cities where out_CitiesPhones.phone = '123456789'

----+-----+----------------+----
#   |@RID |out_CitiesPhones|city
----+-----+----------------+----
0   |#16:0|#17:0           |Rome
----+-----+----------------+----

Заметка: для воплощения правильного варианта, мы обязаны создать еще один класс-ребер под названием CitiesPhones:

create class CitiesPhones extends E

Казалось бы, в 1-ом варианте проще имя поля связи, зачем нам второй вариант? Ответ прост: 1-ый вариант перестанет работать, если у класса Cities появится out_-связь с еще одним классом-вершиной. Произойдет это потому, что OrientDB постарается держать все связи класса Cities со всеми другими классами-вершинами, в поле out_. И казалось бы, что здесь плохого? Но мы ведь понимаем, что может произойти такой случай, когда вы решите связать класс Cities например с классом граждан, которые проживают в указанных городах, назовем его Persons. И в классе Persons может быть такое же одноименное поле phone, как и в классе Phones. Таким образом выполнив запрос:

select from Cities where out_.phone = '123456789'

мы не получим результата, т.к.  OrientDB не знает, указали Вы поле phone класса Phones или Вы указал поле phone класса Persons.

Именно в этом и заключается отличие использования правильного варианта. Удачного изучения, господа.


23.08.2014 12:25