DBKV
DBKV
is a disk-based embedded key-value storage built on top of :dets
. Inspired by CubDB's intuitive API.
Usage
Open a database
iex> {:ok, t} = DBKV.open(name: :my_table, data_dir: "tmp")
{:ok, :my_table}
iex> DBKV.open?(t)
true
Upsert a key-value pair
iex> DBKV.put(t, "greeting", "Hi")
:ok
iex> DBKV.get(t, "greeting")
"Hi"
Insert a key-value pair if it does not exist
iex> DBKV.put_new(t, "greeting", "Hello")
{:error, :exists}
iex> DBKV.get(t, "greeting")
"Hi"
iex> DBKV.put_new(t, "temperature", 32)
:ok
iex> DBKV.get(t, "temperature")
32
Update a key-value pair with a function
iex> DBKV.update(t, "greeting", "default", &(&1 <> "!!!"))
:ok
iex> DBKV.get(t, "greeting")
"Hi!!!"
iex> DBKV.update(t, "language", "default", &(&1 <> "!!!"))
:ok
iex> DBKV.get(t, "language")
"default"
Delete a key-value pair
iex> DBKV.delete(t, "greeting")
:ok
iex> DBKV.get(t, "greeting")
nil
Persistence across restart
iex> DBKV.close(t)
:ok
iex> DBKV.open?(t)
false
iex> DBKV.open(name: t, data_dir: "tmp")
{:ok, :my_table}
iex> DBKV.get(t, "temperature")
32
Initialize the table
iex> DBKV.init_table(t, [a: 0, b: 1, c: 2, d: 3, e: 4])
Select records
By key range
iex> DBKV.select_by_key_range(t, :b, :d)
[b: 1, c: 2, d: 3]
By match spec
iex> require Ex2ms
iex> match_spec = Ex2ms.fun do {k, v} = kv when :b <= k and k <= :d -> kv end
[{{:"$1", :"$2"}, [{:andalso, {:"=<", :b, :"$1"}, {:"=<", :"$1", :d}}], [:"$_"]}]
iex> DBKV.select_by_match_spec(t, match_spec)
[b: 1, c: 2, d: 3]
Troubleshooting
Argument Error
When a table is not open, underlying :dets
will raise ArgumentError
. Please make sure that the table is opened with a correct name.
iex> DBKV.get(:nonexistent_table, "temperature")
** (ArgumentError) argument error
(stdlib 3.15.1) dets.erl:1259: :dets.lookup(:nonexistent_table, "temperature")
(dbkv 0.2.0) lib/dvkv.ex:131: DBKV.get/3
Use :dets
functions
DBKV
is a thin wrapper of :dets
. You can mix and match with any :dets
functions if you wish.
iex> :dets.info(t)
[
type: :set,
keypos: 1,
size: 0,
file_size: 5464,
filename: 'tmp/my_table.db'
]
:invalid_objects_list
error
When a table is initialized inappropriately, the table may return {:error, :invalid_objects_list}
.
In such a case, re-opening the table will fix it.
iex> DBKV.init_table(t, ["invalid object list"])
{:error, :invalid_objects_list}
iex> DBKV.get(t, :a)
** (CaseClauseError) no case clause matching: {:error, :invalid_objects_list}
(dbkv 0.2.0) lib/dvkv.ex:131: DBKV.get/3
iex> DBKV.close(t)
{:error, :invalid_objects_list}
iex> {:ok, t} = DBKV.open(name: :my_table, data_dir: "tmp")
dets: file "tmp/Elixir.DBKV.db" not properly closed, repairing ...
{:ok, :my_table}
iex> DBKV.all(t)
[]
Installation
DBKV
can be installed by adding dbkv
to your list of dependencies in mix.exs:
def deps do
[
{:dbkv, "~> 0.2"}
]
end
Documentation can be found at https://hexdocs.pm/dbkv.