Getting Started:
CRUD Operations with Erlang
Creating Objects In Riak
First, let’s create a few Riak objects. For these examples we’ll be
using the bucket test
.
MyBucket = <<"test">>.
Val1 = 1.
Obj1 = riakc_obj:new(MyBucket, <<"one">>, Val1).
riakc_pb_socket:put(Pid, Obj1).
In this first example, we have stored the integer 1 with the lookup key
of one
. Next, let’s store a simple string value of two
with a
matching key.
Val2 = <<"two">>.
Obj2 = riakc_obj:new(MyBucket, <<"two">>, Val2).
riakc_pb_socket:put(Pid, Obj2).
That was easy. Finally, let’s store something more complex, a tuple this time. You will probably recognize the pattern by now.
Val3 = {value, 3}.
Obj3 = riakc_obj:new(MyBucket, <<"three">>, Val3).
riakc_pb_socket:put(Pid, Obj3).
Reading Objects From Riak
Now that we have a few objects stored, let’s retrieve them and make sure they contain the values we expect.
{ok, Fetched1} = riakc_pb_socket:get(Pid, MyBucket, <<"one">>).
{ok, Fetched2} = riakc_pb_socket:get(Pid, MyBucket, <<"two">>).
{ok, Fetched3} = riakc_pb_socket:get(Pid, MyBucket, <<"three">>).
Val1 =:= binary_to_term(riakc_obj:get_value(Fetched1)). %% true
Val2 =:= riakc_obj:get_value(Fetched2). %% true
Val3 =:= binary_to_term(riakc_obj:get_value(Fetched3)). %% true
That was easy. We simply request the objects by bucket and key.
Updating Objects In Riak
While some data may be static, other forms of data may need to be updated. This is also easy to do. Let’s update the value in the third example to 42, update the Riak object, and then save it.
NewVal3 = setelement(2, Val3, 42).
UpdatedObj3 = riakc_obj:update_value(Fetched3, NewVal3).
{ok, NewestObj3} = riakc_pb_socket:put(Pid, UpdatedObj3, [return_body]).
We can verify that our new value was saved by looking at the value returned.
rp(binary_to_term(riakc_obj:get_value(NewestObj3))).
Deleting Objects From Riak
Nothing is complete without a delete, as they say. Fortunately, that’s easy too.
riakc_pb_socket:delete(Pid, MyBucket, <<"one">>).
riakc_pb_socket:delete(Pid, MyBucket, <<"two">>).
riakc_pb_socket:delete(Pid, MyBucket, <<"three">>).
Now we can verify that the objects have been removed from Riak.
{error,notfound} =:= riakc_pb_socket:get(Pid, MyBucket, <<"one">>).
{error,notfound} =:= riakc_pb_socket:get(Pid, MyBucket, <<"two">>).
{error,notfound} =:= riakc_pb_socket:get(Pid, MyBucket, <<"three">>).
Working With Complex Objects
Since the world is a little more complicated than simple integers and bits of strings, let’s see how we can work with more complex objects. Take, for example, this record that encapsulates some information about a book.
rd(book, {title, author, body, isbn, copies_owned}).
MobyDickBook = #book{title="Moby Dick",
isbn="1111979723",
author="Herman Melville",
body="Call me Ishmael. Some years ago...",
copies_owned=3}.
So we have some information about our Moby Dick collection that we want to save. Storing this to Riak should look familiar by now:
MobyObj = riakc_obj:new(<<"books">>,
list_to_binary(MobyDickBook#book.isbn),
MobyDickBook).
riakc_pb_socket:put(Pid, MobyObj).
Some of you may be thinking: “How does the Erlang Riak client encode/decode my object?” If we fetch our book back and print the value, we shall know:
{ok, FetchedBook} = riakc_pb_socket:get(Pid,
<<"books">>,
<<"1111979723">>).
rp(riakc_obj:get_value(FetchedBook)).
The response:
<<131,104,6,100,0,4,98,111,111,107,107,0,9,77,111,98,121,
32,68,105,99,107,107,0,15,72,101,114,109,97,110,32,77,
101,108,118,105,108,108,101,107,0,34,67,97,108,108,32,
109,101,32,73,115,104,109,97,101,108,46,32,83,111,109,
101,32,121,101,97,114,115,32,97,103,111,46,46,46,107,0,
10,49,49,49,49,57,55,57,55,50,51,97,3>>
Erlang binaries! The Riak Erlang client library encodes everything as
binaries. If we wanted to get a book
object back we could use
binary_to_term/1
to get our original object back:
rp(binary_to_term(riakc_obj:get_value(FetchedBook))).
Next let’s clean up our mess:
riakc_pb_socket:delete(Pid, <<"books">>, <<"1111979723">>).
riakc_pb_socket:stop(Pid).