Java FoundationDB中的getKey返回意外结果

Java FoundationDB中的getKey返回意外结果,java,scala,foundationdb,Java,Scala,Foundationdb,我试图用getKey和KeySelector在FoundationDB的某个子空间中找到一个密钥。在这种情况下,若结果存在于子空间中,那个么它工作得相当好 val key = new Tuple().add(3) val subspace = new Subspace(new Tuple().add("test-subspace")) tr.set(key.pack(), new Tuple().pack()) tr.set(subspace.pack(key), new Tuple

我试图用getKey和KeySelector在FoundationDB的某个子空间中找到一个密钥。在这种情况下,若结果存在于子空间中,那个么它工作得相当好

val key      = new Tuple().add(3)
val subspace = new Subspace(new Tuple().add("test-subspace"))

tr.set(key.pack(), new Tuple().pack())
tr.set(subspace.pack(key), new Tuple().pack())

tr.getKey(KeySelector.firstGreaterOrEqual(subspace.pack(key)))
              .thenApply[Tuple] { result =>
                println(Tuple.fromBytes(result)) // ("test-subspace", 3)
                subspace.unpack(result) // (3)
              }
同时,如果密钥在目标子空间中不存在,它将返回在默认子空间中找到的密钥。这不是我所期望的

val key      = new Tuple().add(3)
val subspace = new Subspace(new Tuple().add("test-subspace"))

tr.set(key.pack(), new Tuple().pack())

tr.getKey(KeySelector.firstGreaterOrEqual(subspace.pack(key)))
              .thenApply[Tuple] { result =>
                println(Tuple.fromBytes(result)) // (3)
                subspace.unpack(result) // Cannot unpack key that is not contained in subspace.
              }
此外,如果db为空,则getKey而不是返回null,返回一些无法由Tuple.fromBytes解析的奇怪字节数组

val key = new Tuple().add("my-key")    

tr.getKey(KeySelector.firstGreaterOrEqual(key.pack()))
              .thenApply[Tuple] { result =>
                println(result == null) // false
                Tuple.fromBytes(result) // throws java.lang.IllegalArgumentException: Unknown tuple data type -1 at index 0
              }

当目标子空间不包含搜索结果时,我应该如何处理这种情况

这是预期的行为。Keyselector返回与条件匹配的键—在本例中,是大于或等于传递的字节[]的第一个键。您需要根据您的子空间要求检查返回的密钥是否有效-使用subspace.contains()或对返回的密钥进行任何其他验证


对第二个问题的解释相同-返回的键可能是数据库中某个特殊的预先存在的行,而不是使用元组层创建的。因此,无法使用元组层对其进行解析。您需要使用subspace.contains或类似的检查来检查密钥的有效性

再加上Guarav所说的,当一个键选择器解析为数据库开始之前的一个键时,它返回空键(
'
)。如果密钥解析超过数据库的末尾,则在正常事务中将获得
'\xff'
,或者如果允许您的事务读取系统密钥,则将获得
'\xff\xff'
。在钥匙选择器文档的末尾简要介绍了这一点

至于不返回子空间之外的结果,这样做可能需要
getKey
接受一个绑定键参数,该参数限制搜索超出该键。它当前没有该参数,但是
getRange
有该参数,如果使用1的限制,则可以使用它执行相同的查询。例如,您可以执行以下操作:

tr.getRange(KeySelector.firstGreaterOrEqual(subspace.pack(key)), subspace.range().end, 1)

在这种情况下,如果可以在与密钥选择器匹配的子空间中找到密钥,则结果将具有密钥;如果无法找到,则结果将为空。当然,您也会在这个查询中返回值。

可能是的,但tbh会带来糟糕的用户体验,因为没有文档描述这种行为,通常这是非常棘手的逻辑。您可以使用开始键和结束键生成的子空间.range()方法将返回的键限制到预期的工作区。键选择器有点棘手,但它们使高级扫描案例成为可能。