I am developing Clojure bindings for FoundationDB and I came across a strange behavior where if I add a number to KeySelector it seems to go to the lowest value and then move from there if I give a number higher than the result set. The implementation is as below where I take a key and make it a tuple. Then I add the limit value to the keyselector object.
Pseudo-code Java implementation of the Clojure code
function last-less-than (Transaction tr, string key, int limit) {
var begin = KeySelector.LastLessThan(ToTuple(key));
var end = kv.add(limit);
var range = tr.getRange(begin, end);
return RangeToList(range);
}
Test cases for last-less-than. Assume Keys are set with the given value i.e. [“bar”] => 1, [“bar1”] => 1, etc. Then to-search is the key passed along with the limit.
Keys : [[“bar”] [“bar1”] [“bar2”] [“car”]]
Value : 1
limit : 1
to-search : bar1
[[[“bar”] “1”]]
Keys : [[“bar”] [“bar1”] [“bar2”] [“car”]]
Value : 1
limit : 2
to-search : bar1
[[[“bar”] “1”] [[“bar1”] “1”]]
Keys : [[“bar”] [“bar1”] [“bar2”] [“car”]]
Value : 1
limit : 2
to-search : bar1
[[[“bar”] “1”] [[“bar1”] “1”] [[“bar2”] “1”]]
(defn last-less-than
"Returns key and value pairs with keys less than the given key for the given limit
"
([tr key]
(last-less-than tr key 1))
([tr key limit]
(let [key (KeySelector/lastLessThan (key->packed-tuple key))
end (.add key limit)
range-query (.getRange tr key end)]
(range->kv range-query))))
Some test cases
(let [fd (. FDB selectAPIVersion 510)
keys [["bar"] ["bar1"] ["bar2"] ["car"]]
value "1"]
(with-open [db (.open fd)]
(tr! db (set-keys tr keys value))))
nil
(let [fd (. FDB selectAPIVersion 510)]
(with-open [db (.open fd)]
(tr! db (last-less-than "bar1"))))
[[["bar"] "1"]] ;; limit 1 by default
(let [fd (. FDB selectAPIVersion 510)]
(with-open [db (.open fd)]
(tr! db (last-less-than tr "bar1" 2))))
[[["bar"] "1"] [["bar1"] "1"]] ;; Seems to go to last less than and then add from there
(let [fd (. FDB selectAPIVersion 510)]
(with-open [db (.open fd)]
(tr! db (last-less-than tr "bar1" 3))))
[[["bar"] "1"] [["bar1"] "1"] [["bar2"] "1"]] ;; Goes to bar2
(let [fd (. FDB selectAPIVersion 510)]
(with-open [db (.open fd)]
(tr! db (last-less-or-equal tr "bar1"))))
[["bar1" "1"]]
(let [fd (. FDB selectAPIVersion 510)]
(with-open [db (.open fd)]
(tr! db (last-less-or-equal tr "bar1" 3))))
[[["bar1"] "1"] [["bar2"] "1"] [["car"] "1"]]
(let [fd (. FDB selectAPIVersion 510)]
(with-open [db (.open fd)]
(tr! db (last-less-or-equal tr "bar1" 10))))
[[["bar1"] "1"] [["bar2"] "1"] [["car"] "1"] [["foo"] 1]]
(let [fd (. FDB selectAPIVersion 510)]
(with-open [db (.open fd)]
(tr! db (last-less-than tr "bar1" 10))))
[[["bar"] "1"] [["bar1"] "1"] [["bar2"] "1"] [["car"] "1"] [["foo"] 1]]