Как я могу установить значения свойства списка в gremlin (CosmosDb) и спроецировать его в результат запроса?

У меня есть вершина, у которой есть свойство списка, и я хочу заменить значения в указанном свойстве и спроецировать результат в определенном формате. Для контекста предположим следующие данные:

g.AddV("Post").property("id", "1")
  .property(list, "Tags", "gremlin")
  .property(list, "Tags", "new")

Я хочу иметь возможность установить свойство Tags. Что я пробовал до сих пор:

g.V("1")
  .sideEffect( properties("Tags").drop() )
  .property(list, "Tags", "gremlin")
  .property(list, "Tags", "closed")
  .property(list, "Tags", "solved")
  .project("Tags").By(values("Tags"))

Я ожидал следующего

{
  "Tags": [
    "gremlin",
    "closed",
    "solved",
  ]
}

Но вместо этого я получаю сообщение об ошибке Project By: Next: The provided traverser of key "Tags" maps to nothing. Таким образом, похоже, что свойство Tags было полностью удалено. Если я сделаю запрос позже

g.V("1").project("Tags").By(values("Tags"))

Получаю ожидаемый результат:

{
  "Tags": [
    "gremlin",
    "closed",
    "solved",
  ]
}

Значит, данные должны быть изменены. Если я попробую без проецирования, результат будет содержать новые значения.

g.V("1")
  .sideEffect( properties("Tags").drop() )
  .property(list, "Tags", "gremlin")
  .property(list, "Tags", "closed")
  .property(list, "Tags", "solved")

В результате чего:

{
  "id": "1",
  "label": "Post",
  "type": "vertex",
  "properties": {
    "Tags": [
    {
      "id": "4eaf5599-511c-4245-aaf8-15c828073fac",
      "value": "gremlin"
    },
    {
      "id": "75e3ad96-a503-4608-a675-e28f3ffc2ab4",
      "value": "closed"
    },
    {
      "id": "aea1a33c-bd8e-47bb-b294-f01db8642db5",
      "value": "solved"
    },
    ]
  }
}

Но это оставляет меня неспособным спрогнозировать результат.

Как я могу одновременно обновлять данные и проецировать их?

Другие вещи, которые я пробовал:

  • Добавление barrier() шага после drop() шага не помогло
  • Добавление barrier() шага после sideEffect() шага не помогло
  • Добавление шага barrier() перед шагом project() не помогло
  • То же, что и три выше, но с .fold().unfold() вместо этого не сработало
  • Замена шага project() на optional(g.V("1").project("Tags").by(values("Tags"))) - этот шаг работает путем повторной выборки вершины, но стоит дорого.

person Benjamin    schedule 26.03.2020    source источник


Ответы (1)


В этом случае может что-то происходить с CosmosDB, а это значит, что вам, возможно, придется получить от них конкретную помощь. Обратите внимание, что ваш обход работает (почти так, как он написан) с TinkerGraph, который является эталонной реализацией того, как Gremlin должен работать:

gremlin> g = TinkerFactory.createTheCrew().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:14], standard]
gremlin> g.V().has('person','name','marko').
......1>   sideEffect(properties("location").drop()).
......2>   property(list,'location','bombay').
......3>   property(list,'location','calcutta').
......4>   project('location').
......5>     by(values('location').fold())
==>[location:[bombay,calcutta]]

Возможно, вам стоит попробовать выполнить свой запрос с моим by() модулятором на project(), чтобы увидеть, имеет ли добавленное fold() какое-либо значение. Между прочим, я не ожидаю, что ваш обход без fold() вернет то, о чем вы говорите, он вернет. Обратите внимание, что произойдет с TinkerGraph, если я попробую это сделать:

gremlin> g.V().has('person','name','marko').
......1>   sideEffect(properties("location").drop()).
......2>   property(list,'location','bombay').
......3>   property(list,'location','calcutta').
......4>   project('location').
......5>     by(values('location'))
==>[location:bombay]

Замена шага project() на optional(g.V("1").project("Tags").by(values("Tags"))) - этот шаг работает путем повторной выборки вершины, но стоит дорого.

Вышеупомянутое является интересным моментом, хотя мне лично не нравится использование g для создания дочерних обходов, поэтому я бы предпочел анонимный обход, порожденный как optional(V("1").project("Tags").by(values("Tags"))). Это заставляет меня задаться вопросом, не отражает ли CosmosDB мутации в текущем обходчике, поэтому вы получаете результат, который ищете, когда вы обновляете, выполняя повторный запрос. Я удивлен, что поиск в середине обхода обходится дорого, так как это поиск по элементу id и должен быть самым быстрым способом найти что-то на графике. Тем не менее, это не так хорошо, что вам приходится искать Vertex более одного раза в одном и том же обходе.

Из любопытства вы можете попробовать valueMap(true), а не project() в качестве еще одного теста, просто чтобы увидеть, вызывает ли это какое-либо другое поведение.

Еще можно попробовать использовать union() вместо sideEffect():

gremlin> g.V().has('person','name','marko').
......1>   union(properties("location").drop(), identity()).
......2>   property(list,'location','bombay').
......3>   property(list,'location','calcutta').
......4>   project('location').
......5>     by(values('location').fold())
==>[location:[bombay,calcutta]]

чтобы увидеть, имеет ли это значение.

person stephen mallette    schedule 26.03.2020
comment
Использование by(values('Tags')) дает следующий результат: Unsupported Error: Gremlin op does not support by(traversal) У меня те же подозрения насчет того, что CosmosDB не отражает мутации, однако, если я это сделаю, g.V('1').property(list, 'Tags', 'foo').values('Tags') результат будет включать недавно добавленный тег. Я попробовал valueMap(true), и, что интересно, он включил теги. Проблема, кажется, возникает только тогда, когда задействован drop(). Еще один интересный момент о формате проекции и fold(). - person Benjamin; 27.03.2020
comment
Что ж, определенно кажется, что вы столкнулись с несоответствиями в их реализации Gremlin. Я добавил еще один вариант, чтобы попробовать, но я чувствую, что вы застрянете либо (1) с двумя отдельными обходами, либо (2) с запросом в середине обхода V(). Также трудно придумать обходные пути, когда я не совсем уверен в том, что CosmosDB действительно поддерживает, а что нет. Я снова предлагаю вам поднять этот вопрос с ними. - person stephen mallette; 27.03.2020
comment
К сожалению, это дает Gremlin Query Compilation Error. Спасибо, что уделили время. Я продолжу расследование и попытаюсь связаться с MS. Если найду решение, обновлю. - person Benjamin; 27.03.2020