Как сложить список связанных вершин с первичной вершиной?

Я пытаюсь получить некоторые вершины идентичности и любые группы, частью которых они являются. Структура графа выглядит примерно так. Обратите внимание, что в Организации есть несколько пользователей, всех из которых я пытаюсь выбрать, и каждый из этих пользователей может входить в несколько групп. (По сути, это стандартная схема «учетная запись пользователя с группами».)

alice  = g.addV('Identity').property('email', '[email protected]').next()
alfred = g.addV('Identity').property('email', '[email protected]').next()

org = g.addV('Organization').property('name', 'Example Inc').next()
[alice, alfred].each { g.V(org).addE('user').to(it).iterate() }

a = g.addV('Group').property('name', 'starts with A').next()
f = g.addV('Group').property('name', 'five letters').next()
[a, f].each { g.V(it).addE('member').to(alice).iterate() }
g.V(A).addE('member').to(alfred).iterate()

Основная логика моего обхода работает так, как ожидалось:

gts.V(organization)
  .out(ORG_USERS).as('i')
  .in(GROUP_USERS)
    .valueMap('name').with(tokens)
    .as('g')
  .select('i', 'g')
    .by(__.valueMap('email').with(tokens))
  .toList()

Однако это создает список карт с ключами i и g, в частности, дублируя удостоверение, если оно находится в нескольких группах. Вместо этого я хотел бы свернуть группы. Я пробовал вот так (пока не пытаюсь дедуплицировать фактические результаты группы, просто сгруппировав их по идентификатору):

gts.V(organization)
  .out(ORG_USERS).as('i')
  .in(GROUP_USERS)
    .valueMap('name').with(tokens)
    .fold()
    .as('gs')
  .select('i', 'gs')
    .by(__.valueMap('email').with(tokens))
  .toList()

Однако, несмотря на то, что fold() принимает обходчик с входящей группой как карта и просто возвращает результат fold(), дает ожидаемый вложенный список, select('i', 'gs') возвращает нулевые результаты. (Я могу select('gs'), но и select('i'), и select('i', 'gs') пусты.)

Как мне структурировать обход, чтобы получить желаемый кортеж из (Identity, List [Group])?


person chrylis -cautiouslyoptimistic-    schedule 01.03.2021    source источник
comment
После шага fold предыдущие метки, такие как i, теряются. Вы сможете просто немного переписать и использовать project. Если вы можете добавить несколько базовых addE и addV шагов, которые построят образец графика, который упростит проверку ответа.   -  person Kelvin Lawrence    schedule 02.03.2021
comment
@KelvinLawrence Добавлен. В реальном коде также есть где группа определяется обратной ссылкой организации; Я отредактирую, чтобы включить это, если это будет иметь существенное значение, но это выглядело как просто подвешивание .where(...) сразу после in(GROUP_USERS).   -  person chrylis -cautiouslyoptimistic-    schedule 02.03.2021


Ответы (1)


Используя ваши образцы данных, я изменил запрос, в качестве примера, чтобы использовать шаг project. Если это не совсем то, что вы ищете, мы можем немного повторить.

gremlin>   g.V(org).
......1>     project('i','g').
......2>       by(out().valueMap().fold()).
......3>       by(out().in().valueMap().fold()) 

==>[i:[[email:[[email protected]]]],g:[[name:[starts with A]],[name:[five letters]],[name:[Example Inc]]]] 

Если вам нужно применить шаг project к разветвлению из организации, что может быть достигнуто с помощью

gremlin>  g.V(org).
......1>     out().
......2>     project('i','g').
......3>       by(valueMap().fold()).
......4>       by(__.in().valueMap().fold())      

==>[i:[[email:[[email protected]]]],g:[[name:[starts with A]],[name:[five letters]],[name:[Example Inc]]]] 

ОБНОВЛЕНО на основе обсуждения ниже. Использование шага group позволяет сгруппировать сообщения электронной почты по имеющимся у них соединениям.

gremlin> g.V(org).
......1>    out().
......2>    group().
......3>      by(values('email')).
......4>      by(__.in().values('name').fold()).
......5>    unfold()

==>[email protected]=[starts with A, Example Inc]
==>[email protected]=[starts with A, five letters, Example Inc]  
person Kelvin Lawrence    schedule 01.03.2021
comment
Похоже, что он собирает все i и все g, но без какой-либо корреляции между ними (то есть, какие пользователи связаны с какими группами). - person chrylis -cautiouslyoptimistic-; 02.03.2021
comment
В образце графа Алиса подключена ко всем этим группам. Не могли бы вы показать результат, который вы хотели бы видеть? gremlin> g.V(org).out().in().path().by(valueMap()) ==>[[name:[Example Inc]],[email:[[email protected]]],[name:[starts with A]]] ==>[[name:[Example Inc]],[email:[[email protected]]],[name:[five letters]]] ==>[[name:[Example Inc]],[email:[[email protected]]],[name:[Example Inc]]] - person Kelvin Lawrence; 02.03.2021
comment
Я расширю свой пример; Дело в том, что для каждой исходной вершины может быть много i, и мне нужно знать как список идентичностей, так и группы, в которых они находятся. - person chrylis -cautiouslyoptimistic-; 02.03.2021
comment
Кроме того, будет ли project работать, если мне также нужно будет сказать /*group*/.where(__in('definedBy').is('org'), что-то вроде project('gs').by(__.in('member').where(__.in('definedBy').is('org'))) (т. Е. Группы, членом которых является этот пользователь, а группа определяется исходной организацией)? - person chrylis -cautiouslyoptimistic-; 03.03.2021
comment
Я постараюсь обновить ответ (как только смогу). Однако замена project на group может быть всем, что вам здесь нужно. Сгруппируйте по всем i и по их входящим вершинам. - person Kelvin Lawrence; 03.03.2021
comment
Я добавил еще один пример, в котором используется group. Это ближе к тому, что вам нужно? - person Kelvin Lawrence; 03.03.2021