SQL 处理长整数类型时 SDK 和存储过程之间的不一致

Inconsistency between SQL SDK and Stored Procedure when handling long integer types

我们的团队使用 Cosmos DB 作为我们的后端图形存储。基本上我们使用 JAVA Gremlin SDK 对 vertices/edges 进行查询,并使用 SQL SDK 对 create/update 个顶点进行查询,由于 Gremlin [=89= 的大小和步长限制].

我在尝试更新包含 Long 类型属性的顶点时遇到了这个问题。 在我们的代码中,我们使用 CosmosDbElement 和另一个标志作为输入参数,调用 sqlClient.executeStoredProcedure(“sp_name”, pk, new Object[] { document, flag }); 我使用的存储过程只是做了一些验证,然后调用 collection.replaceDocument() 来替换文档。

当我为此属性设置不同的值时,我得到了不同的行为:

  1. [-2^53 + 1, 2 ^53 - 1]内的属性值(JavaScript中的MIN_SAFE_INTEGER至MAX_SAFE_INTEGER)

    • 替换为SQLSDK然后通过ID获取:效果很好
    • 替换为SP然后通过ID获取:效果很好
  2. 属性值超出范围但在Int64范围内

    • 替换为SQLSDK然后通过ID获取:效果很好
    • 替换为SP然后通过ID获取:最后3位四舍五入。例如。

9223372036854775107 -> 9223372036854775000;

9223372036854775807 -> 9223372036854776000.

我们可以使用 SQL SDK 获得相同的舍入值。

对于大多数情况,g.V([id]) 获得相同的舍入值。 但是如果四舍五入后的值在Int64范围之外,比如9223372036854775807 -> 9223372036854776000, g.V([id]) 抛出异常:Cannot create ValueField on non-primitive type BigInteger.

  1. 属性超出 Int64 范围
    • 替换为SQLSDK然后通过ID获取:效果很好
    • 替换为SP然后通过ID获取:效果很好

我使用 SP 的方式正确吗?

这是设计限制还是问题?

如何避免这种精度丢失并能够查询顶点?

如果您需要更多信息,请告诉我,谢谢。

The Stored Procedures are written in JavaScript.

As you know, JavaScript uses double-precision floating-point format numbers as specified in IEEE 754, and it can only safely hold numbers between -(2^53 - 1) and 2^53-1 (i.e., 9007199254740991).

So if you use a sproc to replace the value outside of the safe MIN_SAFE_INTEGER to MAX_SAFE_INTEGER in JavaScript, it will get rounded. This is a by-design limitation.

推荐的解决方法是:

  1. If you are ok with the precision-loss, then converting the Int64 values into doubles is recommended so that your application handles the conversion/rounding.
  2. If you need to maintain the precision then use strings, with the downside being that arithmetic ops cannot be applied server-side.