Getting Started

View Source

This guide walks you through installing and using Barrel DocDB from Erlang. barrel_docdb is an embedded document store: you call it in-process through the barrel_docdb module. You'll have a working database in under 5 minutes.

HTTP access

barrel_docdb has no built-in HTTP server. To reach a database over the wire (REST/JSON), run the barrel_server app, which exposes barrel_docdb over HTTP. See the umbrella REST server guide (docs/guides/rest-server.md).

Prerequisites

  • Erlang/OTP 28+

Installation

Erlang (Embedded)

Add to your rebar.config:

{deps, [
    {barrel_docdb, "~> 1.0"}
]}.

Then fetch dependencies:

rebar3 get-deps
rebar3 compile

Build from Source

Clone and build:

git clone https://github.com/barrel-db/barrel.git
cd barrel
rebar3 compile
rebar3 shell

Your First Database

Start the Application

application:ensure_all_started(barrel_docdb).

Create a Database

{ok, _Db} = barrel_docdb:create_db(<<"myapp">>).

Store a Document

With an auto-generated ID:

{ok, #{<<"id">> := DocId, <<"rev">> := Rev}} =
    barrel_docdb:put_doc(<<"myapp">>, #{
        <<"type">> => <<"user">>,
        <<"name">> => <<"Alice">>,
        <<"email">> => <<"alice@example.com">>
    }).

With a specific ID:

{ok, #{<<"rev">> := Rev}} =
    barrel_docdb:put_doc(<<"myapp">>, #{
        <<"id">> => <<"user-alice">>,
        <<"type">> => <<"user">>,
        <<"name">> => <<"Alice">>
    }).

Retrieve a Document

{ok, Doc} = barrel_docdb:get_doc(<<"myapp">>, <<"user-alice">>).
%% Doc = #{<<"id">> => <<"user-alice">>, <<"_rev">> => <<"1-...">>, ...}

Update a Document

Include the current <<"_rev">> value from the document you fetched:

{ok, #{<<"rev">> := NewRev}} =
    barrel_docdb:put_doc(<<"myapp">>, Doc#{
        <<"name">> => <<"Alice Smith">>,
        <<"role">> => <<"admin">>
    }).

Delete a Document

Pass the current revision in the options:

{ok, _} = barrel_docdb:delete_doc(<<"myapp">>, <<"user-alice">>, #{rev => NewRev}).

Querying Documents

Barrel DocDB provides declarative queries with automatic path indexing. No need to create indexes manually.

Find all users:

{ok, Users, _Meta} = barrel_docdb:find(<<"myapp">>, #{
    where => [{path, [<<"type">>], <<"user">>}]
}).

Find admins:

{ok, Admins, _Meta} = barrel_docdb:find(<<"myapp">>, #{
    where => [
        {path, [<<"type">>], <<"user">>},
        {path, [<<"role">>], <<"admin">>}
    ]
}).

With pagination. Meta carries has_more and, when there is more, a continuation token to pass back:

{ok, Page, Meta} = barrel_docdb:find(<<"myapp">>, #{
    where => [{path, [<<"type">>], <<"user">>}],
    limit => 10
}),
case Meta of
    #{has_more := true, continuation := Token} ->
        {ok, More, _} = barrel_docdb:find(<<"myapp">>,
            #{where => [{path, [<<"type">>], <<"user">>}], limit => 10},
            #{continuation => Token});
    #{has_more := false} ->
        ok
end.

You can also run BQL text with barrel_docdb:query/2,3:

{ok, Rows, _Meta} = barrel_docdb:query(<<"myapp">>,
    <<"SELECT name FROM db WHERE type = 'user' LIMIT 10">>).

Watching for Changes

Subscribe to real-time changes using MQTT-style path patterns. Notifications are delivered to the calling process as messages.

Subscribe to all changes:

{ok, _SubRef} = barrel_docdb:subscribe(<<"myapp">>, <<"#">>),
receive
    {barrel_change, <<"myapp">>, Change} ->
        io:format("Change: ~p~n", [Change])
end.

Subscribe to user changes only:

{ok, SubRef} = barrel_docdb:subscribe(<<"myapp">>, <<"type/user/#">>).

Unsubscribe:

barrel_docdb:unsubscribe(SubRef).

To read changes since a point instead of subscribing, use barrel_docdb:get_changes/2,3. See Changes Feed.

Working with Attachments

Store binary files (images, documents, etc.) alongside your documents.

Store an attachment:

Data = <<"Hello, World!">>,
{ok, _} = barrel_docdb:put_attachment(<<"myapp">>, <<"user-alice">>,
    <<"greeting.txt">>, Data).

Retrieve an attachment:

{ok, Binary} = barrel_docdb:get_attachment(<<"myapp">>, <<"user-alice">>,
    <<"greeting.txt">>).

List attachments:

AttNames = barrel_docdb:list_attachments(<<"myapp">>, <<"user-alice">>).
%% Returns [<<"greeting.txt">>]

For large files, stream with open_attachment_stream/3 and read_attachment_chunk/1.

Configuration

Environment Variables

VariableDefaultDescription
BARREL_DATA_DIRdata/barrel_docdbData directory

Erlang Configuration

In sys.config:

[
  {barrel_docdb, [
    {data_dir, "data/barrel_docdb"}
  ]}
].

HTTP listener settings (port, TLS) live in barrel_server, not barrel_docdb. See the umbrella REST server guide (docs/guides/rest-server.md).

Next Steps

Now that you have Barrel DocDB running, explore these features:

  • Queries - Advanced query syntax, operators, and filtering
  • Changes Feed - Real-time subscriptions and MQTT-style patterns
  • Replication - Sync data between nodes with filtering
  • API reference - Complete function documentation

Troubleshooting

Document Update Fails with Conflict

If you get a conflict error when updating, ensure you're passing the current revision. barrel_docdb uses MVCC (Multi-Version Concurrency Control) to prevent lost updates: read the document first, then include its <<"_rev">> in the update (or pass #{rev => Rev} to delete_doc/3).

%% Get the current revision first
{ok, Doc} = barrel_docdb:get_doc(<<"myapp">>, <<"doc1">>),

%% Then write back the document you just read
{ok, _} = barrel_docdb:put_doc(<<"myapp">>, Doc#{<<"name">> => <<"updated">>}).

Serving over HTTP

To expose a database over REST/JSON (including TLS), run the barrel_server app rather than barrel_docdb on its own. See the umbrella REST server guide (docs/guides/rest-server.md).