如何在App Engine的数据存储区中使用64位无符号整数作为实体键并保留排序顺序?

时间:2013-07-18 13:45:24

标签: google-app-engine python-2.7 app-engine-ndb

我有无符号的64位整数,我想用它作为App Engine数据存储区密钥。不幸的是,NDB数据存储区API似乎只允许signed 64 bit integers的最大大小为pow(2, 63)

我可以对两个整数进行补充,但我依赖数据存储区中的排序顺序进行查询,所以我希望0xffffffffffffffff0x0之后的升序排序顺序而不是它。我相信如果我的二进制补码我的64位无符号整数会发生这种情况,因为数据存储索引会将0xffffffffffffffff解释为-1,而0x0会被解释为0

我可以将每个无符号64位密钥从整数更改为字符串甚至是十六进制字符串,但这会占用数据存储区中比将密钥保持为64位整数更多的空间。

2 个答案:

答案 0 :(得分:2)

感谢Tim HoffmanGuido van Rossum,答案是不能使用64位无符号整数作为App Engine数据存储区中的实体键并保留排序顺序。

如果您不关心排序顺序,那么您可以two's complement无符号的64位整数并使用它。

最后,我将无符号的64位整数更改为固定宽度的十六进制字符串,并将其保存为键,因为它似乎最方便,但代价是空间。

我使用的功能如下:

def to_hex_string(unsigned_64bit_int):
    return '{:016x}'.format(my_unsigned_64bit_int)

def to_unsigned_64bit_int(hex_string):
    return int(hex_string, 16)

如果空间很重要Guido van Rossum建议使用保留排序顺序的base-64编码。我不确定Python base64 module编码器是否保留排序顺序。

答案 1 :(得分:0)

只需将您的无符号值编码为带有 pow(2, 63) 的简单常量偏移量的有符号值。

这将所有值“向下移动”而不打乱排序顺序,从 [0, 2^64) 范围可表示为无符号 64 位整数到范围 [-2^63, 2^63) 可表示通过(a的典型实现)有符号的64位整数。

def encode(unsigned_64_bit_int):
    return unsigned_64_bit_int - pow(2, 63)

def decode(signed_64_bit_int):
    return signed_64_bit_int + pow(2, 63)

(您也可以将 pow(2, 63) 替换为等效常量 0x8000000000000000,如果您发现它更清晰或以重要的方式影响性能。)