При использовании Gremlin, вы должны мыслить с точки зрения потока. Поток содержит traversers , которые проходят через написанные вами шаги. В вашем случае, с вашим первоначальным тестом:
g.V().has("user", "userId", 1)
.union(
__.valueMap().by(__.unfold()),
__.project('questions').by(
__.outE('response').valueMap().by(__.unfold()).fold()
)
)
.unfold()
.group()
.by(__.select(column.keys))
.by(__.select(column.values))
у вас есть один traverser (то есть V().has("user", "userId", 1)
производит одного пользователя), который передается в union()
и разделяется так, что он переходит к обоим valueMap()
и project()
оба производят Map
экземпляров. Теперь у вас есть два траверсера, которые развернуты в потоке и сгруппированы в один финальный Map
traverser.
Итак, что изменится, когда вы выполните hasLabel("user")
? Итак, теперь у вас есть более одного начального traverser, что означает, что вы получите два traversrs для каждого из этих пользователей, когда вы доберетесь до union()
. Каждый из них будет перенаправлен на поток unfold()
, а затем просто перезапишет друг друга (поскольку у них одинаковые ключи), чтобы получить один окончательный Map
.
Вы действительно хотите выполнить union()
и выполнять операции один раз для исходного "пользовательского" обхода вершин. Вы можете сказать Gremlin сделать это с помощью map()
:
g.V().has("user", "userId", 1)
.map(
.union(
__.valueMap().by(__.unfold()),
__.project('questions').by(
__.outE('response').valueMap().by(__.unfold()).fold()
)
)
.unfold()
.group()
.by(__.select(column.keys))
.by(__.select(column.values))
)
Наконец, вы можете упростить ваши окончательные by()
модуляторы как:
g.V().has("user", "userId", 1)
.map(
.union(
__.valueMap().by(__.unfold()),
__.project('questions').by(
__.outE('response').valueMap().by(__.unfold()).fold()
)
)
.unfold()
.group()
.by(keys)
.by(values)
)