OrientDB SQL - обход с сохранением веса ребер

Предположим, что в графе OrientDB используется следующая модель:

У меня есть вершина Profile. Профили связаны двумя гранями: Понравилось и Откомментировано. Оба ребра имеют поле "value", указывающее количество действий (или "вес" ребра).

Таким образом, если пользователь А 3 раза прокомментировал сообщения пользователя Б, будет ребро Комментировано от пользователя А к пользователю Б со значением = 3.

Теперь предположим, что я хочу отсортировать всех пользователей, взаимодействовавших с пользователем Б (поставивших лайки или прокомментировавших), по весу взаимодействия. Я могу сделать это с помощью следующего SQL:

select * from (traverse out from   
(select out, sum(value) as value from    
(traverse * from (select from Profile where username="B") while $depth < 3)    
where @class="Liked" or @class="Commented" group by out order by value desc)   
while $depth < 2  ) where @class="Profile" )

Но что, если я хочу знать также вес взаимодействия? Как мне увеличить «значение» при выполнении последнего хода?

Изменить

Согласно предложению, упрощенная версия этого запроса будет:

select expand(out) from (    
    select out, sum(value) as value from (    
       select expand(inE("Liked", "Commented")) from Profile 
           where username="B"    
    ) group by out order by value desc 
)

Но я все еще не могу найти способ использовать LET для вставки значения во внешний развернутый объект. $parent, похоже, не указывает на объект, который расширяется при самом внешнем выборе.

Изменить 2

Я играю с $parent всеми возможными способами. Я не понимаю, как вы можете использовать его в этом случае. Опять же, проблема, которую я пытаюсь решить, заключается в том, как передать сумму (значение) во внешний набор результатов. Я не вижу способа использовать LET для этого при выполнении GROUP BY, и я также не вижу способа использовать LET, когда самый внешний выбор выполняет расширение (поскольку вы не можете делать другие проекции вместе с расширять).

Кроме того, результаты использования $current кажутся не такими, как ожидалось. Например, следующий запрос:

select expand($v) from    
   (select from    
      (select expand(inE("Liked", "Commented")) from Profile where @rid=#11:0)   
    let $v  = $current   
   )

Возвращает это:

{  
   "result" : [{  
       "@type" : "d",
        "@rid" : "#14:4",
        "@version" : 2,
        "@class" : "Commented",
        "value" : 1,
        "out" : "#11:165",
        "in" : "#11:0"
    }, {
        "@type" : "d",
        "@rid" : "#14:4",
        "@version" : 2,
        "@class" : "Commented",
        "value" : 1,
        "out" : "#11:165",
        "in" : "#11:0"
    }, {
        "@type" : "d",
        "@rid" : "#14:4",
        "@version" : 2,
        "@class" : "Commented",
        "value" : 1,
        "out" : "#11:165",
        "in" : "#11:0"
    }
]
}

Один и тот же узел снова и снова вместо всех ребер, чего я и ожидал.


person Rotem Hermon    schedule 10.11.2013    source источник


Ответы (2)


Я вижу, вы используете старую версию OrientDB. В более поздних версиях вы можете упростить это. Пример: исходный запрос:

select * from (
 traverse out from (
  select out, sum(value) as value from (
   traverse * from (
    select from Profile where username="B"
   ) while $depth < 3
  ) where @class="Liked" or @class="Commented" group by out order by value desc
 ) while $depth < 2 
) where @class="Profile" )

Вы можете пропустить какой-то шаг, используя out()/in()/both(), передавая метки/класс Edge, например:

select expand( out(["Liked","Commented]) ) from Profile where username="B"

Однако для передачи значения вы можете использовать переменные с предложением LET. Пример:

select from XXX let $parent.a = value

Таким образом вы устанавливаете переменную «a» в контекст верхнего уровня, но вы также можете сделать это:

select from XXX let $parent.$parent.a = value

Чтобы установить его на 2 уровня вверх.

person Lvca    schedule 11.11.2013
comment
Я до сих пор не знаю, как добиться того, что мне нужно. Если я использую укороченную форму — выберите expand( in([Liked,Commented])) из профиля, где имя пользователя = B — я получаю подключенные профили, а не края, поэтому я не могу получить доступ к значению, которое на краю. Я также пытался использовать let в своем исходном запросе, но кажется, что $parent всегда пуст. - person Rotem Hermon; 12.11.2013
comment
Если быть более точным, эта часть: 'выберите out, sum(value) as value from ( traverse * from ( select from Profile where username=B ) while $depth ‹ 3 ' - объединяет значения 2 ребер и упорядочивает из край по агрегированной сумме. Я не уверен, как я могу выразить это с помощью более красивой и сокращенной формы. И я не вижу, как я могу объединить с ним LET для передачи агрегированного значения вверх. ) где @class= Понравившиеся или @class=комментированные группы по порядку по описанию значения - person Rotem Hermon; 12.11.2013
comment
Если вы хотите использовать преимущество: inE([Liked,Commented]) - person Lvca; 12.11.2013
comment
О, это мило. (Это где-нибудь задокументировано? Я никогда не сталкивался с этим вариантом). Но посмотрите мое редактирование - я не понимаю, как здесь можно использовать LET. $parent, похоже, не фиксирует возвращаемый объект (который является частью агрегированного запроса). - person Rotem Hermon; 13.11.2013

Я еще не пробовал это с группой, но вы должны иметь возможность сгруппировать результат с помощью подзапроса. Это работает для меня, где prop1, prop2, prop3 и т. д. являются свойствами вершин, выходящих из края (столбцы, полученные из select out() Profile where username="B")

select outV().prop1, outV().prop2, outV().prop3, value from (    
   select expand(inE("Liked", "Commented")) from Profile 
       where username="B"    
) order by value desc 
person Simon    schedule 18.04.2015