FoundationDB 中的 getKey returns 意外结果
getKey in FoundationDB returns unexpected result
我试图使用 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)
}
同时,如果目标子空间中不存在key,则returns默认子空间中找到的key。这不是我所期望的...
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,returns 一些无法被 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 returns 你匹配条件的键 - 在这种情况下第一个键大于或等于传递的 byte[]。您需要根据您的子空间要求检查返回的密钥是否有效 - 通过使用 subspace.contains() 或对返回的密钥进行任何其他验证。
第二个问题的解释相同——返回的键可能是数据库中一些特殊的预先存在的行,不是使用元组层创建的。因此它不能使用元组层进行解析。您需要使用 subspace.contains 或一些类似的检查来检查密钥有效性。
补充一下 Guarav 所说的,当键选择器解析为数据库开头之前的键时,它 returns 空键 (''
)。如果密钥解析超过数据库末尾,您将在正常事务中获得 '\xff'
或 '\xff\xff'
如果允许您的事务读取系统密钥。在密钥选择器文档 here.
的末尾简要提到了这一点
至于不在您的子空间之外返回结果,这样做可能需要 getKey
接受一个限制搜索超出该键的绑定键参数。它目前没有那个参数,但是 getRange
有并且可以用来执行相同的查询,如果你使用 1 的限制。例如,你可以这样做:
tr.getRange(KeySelector.firstGreaterOrEqual(subspace.pack(key)), subspace.range().end, 1)
在这种情况下,如果可以在与您的键选择器匹配的子空间中找到一个键,则结果将有一个键;如果找不到,则结果将为空。当然,您也将在此查询中取回值。
我试图使用 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)
}
同时,如果目标子空间中不存在key,则returns默认子空间中找到的key。这不是我所期望的...
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,returns 一些无法被 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 returns 你匹配条件的键 - 在这种情况下第一个键大于或等于传递的 byte[]。您需要根据您的子空间要求检查返回的密钥是否有效 - 通过使用 subspace.contains() 或对返回的密钥进行任何其他验证。
第二个问题的解释相同——返回的键可能是数据库中一些特殊的预先存在的行,不是使用元组层创建的。因此它不能使用元组层进行解析。您需要使用 subspace.contains 或一些类似的检查来检查密钥有效性。
补充一下 Guarav 所说的,当键选择器解析为数据库开头之前的键时,它 returns 空键 (''
)。如果密钥解析超过数据库末尾,您将在正常事务中获得 '\xff'
或 '\xff\xff'
如果允许您的事务读取系统密钥。在密钥选择器文档 here.
至于不在您的子空间之外返回结果,这样做可能需要 getKey
接受一个限制搜索超出该键的绑定键参数。它目前没有那个参数,但是 getRange
有并且可以用来执行相同的查询,如果你使用 1 的限制。例如,你可以这样做:
tr.getRange(KeySelector.firstGreaterOrEqual(subspace.pack(key)), subspace.range().end, 1)
在这种情况下,如果可以在与您的键选择器匹配的子空间中找到一个键,则结果将有一个键;如果找不到,则结果将为空。当然,您也将在此查询中取回值。