getKey в FoundationDB возвращает неожиданный результат - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь найти ключ в некотором подпространстве в FoundationDB с помощью getKey и KeySelector. В случае, если результат существует в 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 голосов
/ 26 ноября 2018

Чтобы добавить то, что сказал Гуарав, когда ключевой селектор разрешает ключ до начала базы данных, он возвращает пустой ключ (''). Если ключ разрешается после конца базы данных, вы получите '\xff' в обычной транзакции или '\xff\xff', если вашей транзакции разрешено чтение системных ключей. Это кратко упоминается в конце документации по ключевому селектору здесь .

Что касается не возврата результата за пределы вашего подпространства, для этого, вероятно, потребуется getKey принятие параметра связанного ключа, который ограничивает поиск за пределами этого ключа. В настоящее время он не имеет этого параметра, но getRange имеет и может использоваться для выполнения того же запроса, если вы используете предел 1. Например, вы можете сделать:

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

В этом случае результат будет иметь либо ключ, если он может быть найден в подпространстве, соответствующем вашему ключевому селектору, либо он будет пустым, если не мог. Конечно, вы также вернете значение в этом запросе.

0 голосов
/ 14 ноября 2018

Это ожидаемое поведение.Keyselector возвращает вам ключ, который соответствует условию - в этом случае первый ключ, который больше или равен переданному байту [].Вам необходимо проверить, является ли возвращенный ключ действительным в соответствии с вашим требованием подпространства - с помощью subspace.contains () или любой другой проверки возвращаемого ключа.

То же самое объяснение для второго вопроса - возвращаемый ключ может быть какой-то специальной предварительно существующей строкой в ​​БД, которая не создается с использованием кортежного слоя.Следовательно, он не может быть проанализирован с использованием кортежного слоя.Вам необходимо проверить правильность ключа, используя subspace.contains или аналогичную проверку.

...