У меня есть простой запрос, который создает новую вершину и добавляет ребро между старой и новой вершиной в том же запросе. Этот запрос в большинстве случаев работает хорошо. Странное поведение проявляется, когда система сильно загружена и RU исчерпаны.

g.V('2f9d5fe8-6270-4928-8164-2580ad61e57a').AddE('likes').to(g.AddV('fruit').property('id','1').property('name','apple'))

При низкой / нормальной нагрузке указанный выше запрос создает вершину плода 1 и создает ребро likes между user и fruit. Ожидаемое поведение.

При большой нагрузке (доступные RU ограничены) указанный выше запрос создает вершину fruit, но не создает ребро likes между user и fruit. Запрос выдает код статуса 429. Если я попытаюсь воспроизвести запрос, я получу 409, поскольку вершина fruit уже существует. Такое поведение повреждает данные.

Во многих местах в запросе есть g.AddV. Так что все эти запросы могут сломаться при большой нагрузке.

Есть ли разница, если я использую __.addV вместо g.AddV?

ОБНОВЛЕНО : использование __.addV не имеет никакого значения.

Итак, мой запрос неверен? мне нужно делать upsert везде, где мне нужно добавить ребро?

0
Venky 30 Дек 2019 в 20:29

2 ответа

Я не знаю, как Microsoft реализовала TinkerPop, и поэтому я не уверен, поможет ли следующее, но вы можете сначала попытаться создать новую вершину, а затем добавить ребро в / из существующей вершины.

g.addV('fruit').
    property('id','1').
    property('name','apple').
  addE('likes').
    from(V('2f9d5fe8-6270-4928-8164-2580ad61e57a'))

Если и это не помогло, то да, вероятно, лучше всего будет выполнить upsert, так как вы можете повторять один и тот же запрос бесконечно. Однако, поскольку у меня нет глубоких знаний о CosmosDB, я не могу сказать, могут ли его обновления предотвратить дублирование краев.

1
Daniel Kuppitz 31 Дек 2019 в 05:49

В Cosmos DB Gremlin API область транзакций ограничена операциями записи для объекта (вершины или края). Таким образом, для запросов Gremlin, которым необходимо выполнить несколько операций записи, возможно, что в случае сбоя будет зафиксировано частичное состояние.

Учитывая это, рекомендуется использовать идемпотентные обходы гремлинов, чтобы запрос можно было повторить при ошибках, таких как RequestRateTooLarge (429), без блокирования из-за ошибок конфликта при повторной попытке.

Вот обход, переписанный с использованием шага coalesce(), так что он идемпотентный (я предположил, что 'name' - это ключ раздела).

g.V('1').has('name', 'apple').fold()
  coalesce(
    __.unfold(),
    __.addV('fruit').
       property('id','1').
       property('name','apple')).
 addE('likes').
    from(V('2f9d5fe8-6270-4928-8164-2580ad61e57a'))

Примечание. Я не заключал addE() в coalesce(), поскольку это последняя операция, выполняемая во время выполнения. Вы можете подумать о том, чтобы сделать это, если будут дополнительные операции записи после ребра в том же запросе или если вам нужно предотвратить дублирование ребер для одновременных запросов на добавление ребер.

0
Oliver Towers 21 Янв 2020 в 23:58