Packages
rocksdb
2.2.0
3.1.1
3.1.0
3.0.0
2.6.2
2.6.1
retired
2.6.0
retired
2.5.0
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
1.9.0
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.1
1.1.0
1.0.0
0.26.2
0.26.1
0.26.0
0.25.0
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.0
0.21.0
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
RocksDB for Erlang
Current section
Files
Jump to
Current section
Files
guides/erlang_merge_operator.md
Starting in version 0.21.0, Erlang Rocksdb support a [Merge Operator](Erlang-Merge-Operator) for Erlang data types.
RocksDB offers the possibility of doing appends to existing key values efficiently through the use of a [merge operator](https://github.com/facebook/rocksdb/wiki/Merge-Operator). This operator is a user-provided callback that knows how to merge the old value ("the message") and the new value ("the delta") into a single value ("the merged value").
The [Erlang Merge Operator](Erlang-Merge-Operator) allows two combine two values of the same Erlang data type in a single value. As long as your data is stored as Erlang binary term (encoded using the `term_to_binary` function), , it should be possible to apply a single predefined merge operator in order to take advantage of the RocksDB merge operation.
For example appending an item to a list (like `++`):
```erlang
%% store a list encoded using `term_to_binary`
ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b]), []),
{ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
[a, b] = binary_to_term(Bin0),
%% append two items
ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_append, [c, d]}), []),
{ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
[a, b, c, d] = binary_to_term(Bin1),
```
## Setup a merge operator
To set the merge operator, add it to the columns options (or the db options if only one column) by setting the `merge_operator` option:
```erlang
{ok, Db} = rocksdb:open("mydb",
[{create_if_missing, true},
{merge_operator, erlang_merge_operator}]).
```
## Operations:
### on integer
The Erlang merge operator support the `int_add` operation to add an integer value:
```erlang
ok = rocksdb:put(Db, <<"i">>, term_to_binary(0), []),
{ok, IBin0} = rocksdb:get(Db, <<"i">>, []),
0 = binary_to_term(IBin0),
ok = rocksdb:merge(Db, <<"i">>, term_to_binary({int_add, 1}), []),
{ok, IBin1} = rocksdb:get(Db, <<"i">>, []),
1 = binary_to_term(IBin1),
```
### on lists
The Erlang merge operator support the following operations on lists:
* `list_append` like `++` or `lists:append/2`: Returns a new list List3, which is made from the elements of List1 followed by the elements of List2.
```erlang
ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b]), []),
{ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
[a, b] = binary_to_term(Bin0),
ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_append, [c, d]}), []),
{ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
[a, b, c, d] = binary_to_term(Bin1),
```
* `list_substract`: like `lists:substract/2` or `--`, Returns a new list List3 that is a copy of List1, subjected to the following procedure: for each element in List2, its first occurrence in List1 is deleted.
```erlang
ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e, a, b, c]), []),
{ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
[a, b, c, d, e, a, b, c] = binary_to_term(Bin0),
ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_substract, [c, a]}), []),
{ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
[b, d, e, a, b, c] = binary_to_term(Bin1),
```
* `list_set`: to set an element in the list at a position:
```erlang
ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e]), []),
{ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
[a, b, c, d, e] = binary_to_term(Bin0),
ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_set, 2, 'c1'}), []),
{ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
[a, b, 'c1', d, e] = binary_to_term(Bin1),
```
* `list_delete` : to delete an 1 or more elements a at position in the list:
```erlang
ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e, f, g]), []),
{ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
[a, b, c, d, e, f, g] = binary_to_term(Bin0),
ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_delete, 2}), []),
{ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
[a, b, d, e, f, g] = binary_to_term(Bin1),
ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_delete, 2, 4}), []),
{ok, Bin2} = rocksdb:get(Db, <<"list">>, []),
[a, b, g] = binary_to_term(Bin2),
```
* `list_insert`: to insert N elements at a position in a list:
```erlang
ok = rocksdb:put(Db, <<"list">>, term_to_binary([a, b, c, d, e, f, g]), []),
{ok, Bin0} = rocksdb:get(Db, <<"list">>, []),
[a, b, c, d, e, f, g] = binary_to_term(Bin0),
ok = rocksdb:merge(Db, <<"list">>, term_to_binary({list_insert, 2, [h, i]}), []),
{ok, Bin1} = rocksdb:get(Db, <<"list">>, []),
[a, b, h, i, c, d, e, f, g] = binary_to_term(Bin1),
```
### on binary
The Erlang merge operator support the following operations on binaries:
* `binary_append`: to append a binary:
```erlang
ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_append, <<"abc">>}), []),
{ok, Bin1} = rocksdb:get(Db, <<"encbin">>, []),
<<"testabc">> = binary_to_term(Bin1),
ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_append, <<"de">>}), []),
{ok, Bin2} = rocksdb:get(Db, <<"encbin">>, []),
<<"testabcde">> = binary_to_term(Bin2),
```
* `binary_replace`: Constructs a new binary by replacing the part in the range with the content of replacement. The range is given in bits:
```erlang
ok = rocksdb:put(Db, <<"encbin">>, term_to_binary(<<"The quick brown fox jumps over the lazy dog.">>), []),
{ok, Bin} = rocksdb:get(Db, <<"encbin">>, []),
<<"The quick brown fox jumps over the lazy dog.">> = binary_to_term(Bin),
ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_replace, 10, 5, <<"red">>}), []),
ok = rocksdb:merge(Db, <<"encbin">>, term_to_binary({binary_replace, 0, 3, <<"A">>}), []),
{ok, Bin1} = rocksdb:get(Db, <<"encbin">>, []),
<<"A quick red fox jumps over the lazy dog.">> = binary_to_term(Bin1),
ok = rocksdb:put(Db, <<"bitmap">>, term_to_binary(<<1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1>>), []),
ok = rocksdb:merge(Db, <<"bitmap">>, term_to_binary({binary_replace, 2, 1, <<0>>}), []),
{ok, Bin2} = rocksdb:get(Db, <<"bitmap">>, []),
<<1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1>> = binary_to_term(Bin2),
```
* `binary_erase`: Constructs a new binary by deleting the part in the range. The range is given in bits:
```erlang
ok = rocksdb:put(Db, <<"eraseterm">>, term_to_binary(<<"abcdefghij">>), []),
ok = rocksdb:merge(Db, <<"eraseterm">>, term_to_binary({binary_erase, 2, 4}), []),
{ok, Bin} = rocksdb:get(Db, <<"eraseterm">>, []),
<<"abghij">> = binary_to_term(Bin),
```
* `binary_insert`: Constructs a new binary by inserting a part at a position given in bits:
```erlang
ok = rocksdb:put(Db, <<"insertterm">>, term_to_binary(<<"abcdefghij">>), []),
ok = rocksdb:merge(Db, <<"insertterm">>, term_to_binary({binary_insert, 2, <<"1234">>}), []),
{ok, Bin} = rocksdb:get(Db, <<"insertterm">>, []),
<<"ab1234cdefghij">> = binary_to_term(Bin),
```