{"id":15010114,"url":"https://github.com/mnishiguchi/dbkv","last_synced_at":"2025-12-11T23:39:06.312Z","repository":{"id":57488614,"uuid":"381172413","full_name":"mnishiguchi/dbkv","owner":"mnishiguchi","description":"A disk-based key-value storage built on top of dets","archived":false,"fork":false,"pushed_at":"2021-09-29T23:58:05.000Z","size":80,"stargazers_count":5,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-15T04:46:30.098Z","etag":null,"topics":["database","elixir","embedded","key-value","key-value-store","nerves"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mnishiguchi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-28T22:07:12.000Z","updated_at":"2022-04-15T13:30:26.000Z","dependencies_parsed_at":"2022-08-28T11:50:12.492Z","dependency_job_id":null,"html_url":"https://github.com/mnishiguchi/dbkv","commit_stats":null,"previous_names":["mnishiguchi/dubdb"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/mnishiguchi/dbkv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnishiguchi%2Fdbkv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnishiguchi%2Fdbkv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnishiguchi%2Fdbkv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnishiguchi%2Fdbkv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mnishiguchi","download_url":"https://codeload.github.com/mnishiguchi/dbkv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnishiguchi%2Fdbkv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278703579,"owners_count":26031204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","elixir","embedded","key-value","key-value-store","nerves"],"created_at":"2024-09-24T19:30:21.369Z","updated_at":"2025-10-09T12:13:19.004Z","avatar_url":"https://github.com/mnishiguchi.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DBKV\n\n[![Hex version](https://img.shields.io/hexpm/v/dbkv.svg \"Hex version\")](https://hex.pm/packages/dbkv)\n[![API docs](https://img.shields.io/hexpm/v/dbkv.svg?label=docs \"API docs\")](https://hexdocs.pm/dbkv)\n[![CI](https://github.com/mnishiguchi/dbkv/actions/workflows/ci.yml/badge.svg)](https://github.com/mnishiguchi/dbkv/actions/workflows/ci.yml)\n[![Hex](https://github.com/mnishiguchi/dbkv/actions/workflows/hex.yml/badge.svg)](https://github.com/mnishiguchi/dbkv/actions/workflows/hex.yml)\n\nA disk-based embedded key-value storage built on top of [dets](https://erlang.org/doc/man/dets.html) set.\nInspired by [CubDB](https://github.com/lucaong/cubdb)'s intuitive API.\n\nA table has at most one entry with a given key. If an entry with a key already present in the table\nis inserted, the existing entry is overwritten by the new entry. The entries are not ordered. See\n[dets manual](https://erlang.org/doc/man/dets.html) for more info.\n\n## Usage\n\nDocumentation can be found at [https://hexdocs.pm/dbkv](https://hexdocs.pm/dbkv).\n\n### Open a table\n\n```elixir\niex\u003e {:ok, t} = DBKV.open(name: :my_table, data_dir: \"tmp\")\n{:ok, :my_table}\n\niex\u003e DBKV.open?(t)\ntrue\n\niex\u003e DBKV.filename(t)\n'tmp/my_table.db'\n```\n\nYou could omit `name` and `data_dir` options. In such a case, they will default to `DBKV` and `\"tmp\"` respectively.\n\n```elixir\niex\u003e DBKV.open()\n```\n\n### Upsert an entry\n\n```elixir\niex\u003e DBKV.put(t, \"greeting\", \"Hi\")\n:ok\n\niex\u003e DBKV.get(t, \"greeting\")\n\"Hi\"\n```\n\n### Insert an entry unless the entry key already exists in the table\n\n```elixir\niex\u003e DBKV.put_new(t, \"greeting\", \"Hello\")\n{:error, :exists}\n\niex\u003e DBKV.get(t, \"greeting\")\n\"Hi\"\n\niex\u003e DBKV.put_new(t, :temperature, 32)\n:ok\n\niex\u003e DBKV.get(t, :temperature)\n32\n```\n\n### Update an entry in the table with a function\n\n```elixir\niex\u003e DBKV.update(t, \"greeting\", \"default\", \u0026(\u00261 \u003c\u003e \"!!!\"))\n:ok\n\niex\u003e DBKV.get(t, \"greeting\")\n\"Hi!!!\"\n\niex\u003e DBKV.update(t, 123, \"default\", \u0026(\u00261 \u003c\u003e \"!!!\"))\n:ok\n\niex\u003e DBKV.get(t, 123)\n\"default\"\n```\n\n### Delete an entry\n\n```elixir\niex\u003e DBKV.delete(t, \"greeting\")\n:ok\n\niex\u003e DBKV.get(t, \"greeting\")\nnil\n```\n\n### Initialize a table with a specific dataset\n\nA table can be initialized with a list of two-element tulpes.\n\n```elixir\niex\u003e DBKV.init_table(t, [{:a, 0}, {:b, 1}, {:c, 2}, {:d, 3}, {:e, 4}])\n```\n\n### Select a range of entries from the table\n\n**By key range**\n\n```elixir\niex\u003e DBKV.select_by_key_range(t, :b, :d)\n[b: 1, c: 2, d: 3]\n```\n\n**By value range**\n\n```elixir\niex\u003e DBKV.select_by_value_range(t, 2, 3)\n[c: 2, d: 3]\n```\n\n**By [match spec](https://erlang.org/doc/apps/erts/match_spec.html)**\n\nThe [Ex2ms.fun/2](https://hexdocs.pm/ex2ms/Ex2ms.html#fun/1) macro is useful to build a match specification.\n\n```elixir\niex\u003e require Ex2ms\n\niex\u003e match_spec = Ex2ms.fun do {k, v} = kv when :b \u003c= k and k \u003c= :d -\u003e kv end\n[{{:\"$1\", :\"$2\"}, [{:andalso, {:\"=\u003c\", :b, :\"$1\"}, {:\"=\u003c\", :\"$1\", :d}}], [:\"$_\"]}]\n\niex\u003e DBKV.select_by_match_spec(t, match_spec)\n[b: 1, c: 2, d: 3]\n```\n\n### Use `:dets` functions\n\nYou could mix and match with any [dets functions](https://erlang.org/doc/man/dets.html) if you wish.\n\n```elixir\niex\u003e :dets.info(t)\n[\n  type: :set,\n  keypos: 1,\n  size: 0,\n  file_size: 5464,\n  filename: 'tmp/my_table.db'\n]\n```\n\n## Troubleshooting\n\n### `ArgumentError`\n\nWhen a table is not open, a function call results in `ArgumentError`.\nMake sure that the table is opened with a correct name.\n\n```elixir\niex\u003e DBKV.get(:nonexistent_table, :temperature)\n** (ArgumentError) argument error\n    (stdlib 3.15.1) dets.erl:1259: :dets.lookup(:nonexistent_table, :temperature)\n    (dbkv 0.2.0) lib/dvkv.ex:131: DBKV.get/3\n```\n\n## Installation\n\n`DBKV` can be installed by adding `dbkv` to your list of dependencies in mix.exs:\n\n```elixir\ndef deps do\n  [\n    {:dbkv, \"~\u003e 0.2\"}\n  ]\nend\n```\n\nUsing `Mix.install/2` in IEx:\n\n```elixir\n❯ iex\n\niex\u003e Mix.install([{:dbkv, \"~\u003e 0.2\"}])\n```\n\n## Alternatives\n\n- [CubDB](https://github.com/lucaong/cubdb)\n- [dets](https://erlang.org/doc/man/dets.html)\n- etc\n\nThere was a good discussion about Erlang/Elixir key-value stores in this [Elixir Forum thread](https://elixirforum.com/t/cubdb-a-pure-elixir-embedded-key-value-database/23397?u=mnishiguchi).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnishiguchi%2Fdbkv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmnishiguchi%2Fdbkv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnishiguchi%2Fdbkv/lists"}