FoundationDB中的getKey返回意外结果

时间:2018-11-13 15:15:40

标签: java scala foundationdb

我试图使用getKey和KeySelector在FoundationDB的某个子空间中找到一个键。如果结果在Subspace中存在,则效果很好。

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
              }

当目标子空间不包含搜索结果时,应如何处理?

2 个答案:

答案 0 :(得分:2)

要补充Guarav所说的内容,当键选择器在数据库开始之前解析为键时,它将返回空键('')。如果密钥解析到数据库末尾,则将在正常事务中获得'\xff',如果允许事务读取系统密钥,则将获得'\xff\xff'。密钥选择器文档here的末尾简要提到了这一点。

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

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

在这种情况下,如果可以在与您的键选择器匹配的子空间中找到一个键,则结果将具有一个键;否则,结果将为空。当然,您还将在此查询中取回值。

答案 1 :(得分:1)

这是预期的行为。 Keyselector返回符合条件的键-在这种情况下,第一个键大于或等于所传递的byte []。您需要根据子空间要求检查返回的键是否有效-通过使用subspace.contains()或对返回的键进行任何其他验证。

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