CubDB
is an embedded key-value database written in the Elixir language. Itruns locally, it is schema-less, and backed by a single file.
Head to the API reference for usagedetails, or read the Frequently AskedQuestions and the How Tosection for more information.
Both keys and values can be any arbitrary Elixir (or Erlang) term.
Simple get
, put
, and delete
operations
Arbitrary selection of ranges of entries sorted by key with select
Atomic transactions with put_multi
, get_and_update_multi
, etc.
Concurrent read operations, that do not block nor are blocked by writes
Unexpected shutdowns won't corrupt the database or break atomicity
Manual or automatic compaction to optimize space usage
To ensure consistency, performance, and robustness to data corruption, CubDB
database file uses an append-only, immutable B-tree data structure. Entries arenever changed in-place, and read operations are performend on immutablesnapshots.
Start CubDB
by specifying a directory for its database file (if not existing,it will be created):
{:ok, db} = CubDB.start_link(data_dir: "my/data/directory")
Important: avoid starting multiple CubDB
processes on the same datadirectory. Only one CubDB
process should use a specific data directory at anytime.
get
, put
, and delete
operations work as you probably expect:
CubDB.put(db, :foo, "some value")
#=> :ok
CubDB.get(db, :foo)
#=> "some value"
CubDB.delete(db, :foo)
#=> :ok
CubDB.get(db, :foo)
#=> nil
Multiple operations can be performed as an atomic transaction with put_multi
,delete_multi
, and the other [...]_multi
functions:
CubDB.put_multi(db, [a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8])
#=> :ok
Range of entries sorted by key are retrieved using select
:
CubDB.select(db, min_key: :b, max_key: :e)
#=> {:ok, [b: 2, c: 3, d: 4, e: 5]}
But select
can do much more than that. It can apply a pipeline of operations(map
, filter
, take
, drop
and more) to the selected entries, it canselect the entries in normal or reverse order, and it can reduce
the resultusing an arbitrary function:
# Take the sum of the last 3 even values:
CubDB.select(db,
# select entries in reverse order
reverse: true,
# apply a pipeline of operations to the entries
pipe: [
# map each entry discarding the key and keeping only the value
map: fn {_key, value} -> value end,
# filter only even integers
filter: fn value -> is_integer(value) && Integer.is_even(value) end,
# take the first 3 values
take: 3
],
# reduce the result to a sum
reduce: fn n, sum -> sum + n end
)
#=> {:ok, 18}
For more details, read the API documentation.
CubDB
can be installed by adding :cubdb
to your list of dependencies inmix.exs
:
def deps do
[
{:cubdb, "~> 1.1.0"}
]
end
The file data structure used by CubDB
is inspired byCouchDB. A big thanks goes to the CouchDBmaintainers for the readable codebase and extensive documentation.
Copyright 2021 Luca Ongaro
Licensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.