我有一个下面的简单查询,该查询创建一个新顶点并在同一查询中在旧顶点和新顶点之间添加一条边。该查询在大多数情况下都能正常运行。当系统上的负载很重并且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 :(得分:0)
我不知道Microsoft如何实现TinkerPop,因此不确定以下内容是否有帮助,但是您可以尝试先创建新顶点,然后向/从现有顶点添加边。
g.addV('fruit').
property('id','1').
property('name','apple').
addE('likes').
from(V('2f9d5fe8-6270-4928-8164-2580ad61e57a'))
如果同样失败,那么是的,最好是upsert,因为您可以无限期地重试相同的查询。但是,由于我对CosmosDB并不了解,所以我无法确定它的专家是否可以防止边缘重复。
答案 1 :(得分:0)
在Cosmos DB Gremlin API中,事务范围仅限于对实体(Vertex或Edge)的写入操作。因此,对于需要执行多个写入操作的Gremlin请求,有可能在失败时提交部分状态。
鉴于此,建议您使用幂等的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()
中,因为它是执行期间要执行的最后一个操作。如果在同一请求中的边缘之后还会有其他写操作,或者如果您需要防止重复的边缘用于并发添加边缘请求,则可能要考虑这样做。