Шаг объединения не работает с несколькими элементами - PullRequest
0 голосов
/ 12 апреля 2020

Следующий запрос возвращает карту пользователя со «введенным» свойством, называемым «вопросы», он работает, как и ожидалось, когда g.V().has() возвращает одного пользователя, но не когда возвращает нескольких пользователей:

  return 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));

Это работает, но когда я изменяю первую строку для возврата нескольких пользователей:

g.V().hasLabel("user").union(....

Я заканчиваю sh запрос, вызывающий .toList(), поэтому я ожидал получить список всех пользователей в одном и том же как это работает с одним пользователем, но вместо этого я все еще получаю одного пользователя. Как я могу заставить мой запрос работать как для нескольких пользователей, так и для одного?

1 Ответ

1 голос
/ 12 апреля 2020

При использовании 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)
       )
...