-
Notifications
You must be signed in to change notification settings - Fork 92
Link walking
At the end of this guide, you should be familiar with:
- Adding links to objects in your database
- Traversing links
This and the other guides in this wiki assume you have Riak installed locally. If you don't have Riak already, please read and follow how to install Riak and then come back to this guide. If you haven't yet installed the client library, please do so before starting this guide.
This guide also assumes you know how to
connect the client to Riak and
store and retrieve values. All examples
assume a local variable of client
which is an instance of
Riak::Client
and points at some Riak node you want to work with.
Riak Links are implemented as metadata on the stored object. They establish one-way relationships between pieces of data in Riak. This lets the developer relate data in Riak fairly easily.
A Riak Link requires three things:
- A bucket where the original record resides
- The key pointing to the record
- A tag that can be used to pluck out specific links from the list a record can hold
Let's get to the code.
Let's say we have a User record and some Bank account records and we want to relate those to one another.
#User object
user = users_bucket.get("TkwPo5A7x7UGVVqOigaoSZFq71J")
#<Riak::RObject {users,TkwPo5A7x7UGVVqOigaoSZFq71J} [#<Riak::RContent [application/json]:{"created_at"=>"2013-04-25T00:57:30-07:00", "login"=>"test-user", "name"=>"Test User"}>]>
#Bank accounts
visa = accounts_bucket.get("ZqE0aKune4xbFlzPNSfEVOUOucE")
#<Riak::RObject {accounts,ZqE0aKune4xbFlzPNSfEVOUOucE [#<Riak::RContent [application/json]:{"type"=>"CC", "name"=>"Visa Credit Card", "balance" => 450.12}>]>
chequing = accounts_bucket.get("XbLYOr5YwvvRRbtcs51JP3TESVi")
#<Riak::RObject {accounts,XbLYOr5YwvvRRbtcs51JP3TESVi} [#<Riak::RContent [application/json]:{"type"=>"Chequing", "name"=>"Bank Simple", "balance" => 1103.40}>]>
What we can do in this case is to add the key of each Account, as well as its bucket, to the User object and tag it with something meaningful. Assuming we collect the keys into an array, we can loop over them like this:
accounts_keys = [visa.key, chequing.key]
accounts_keys.each do |key|
user.links << Riak::Link.new("accounts", key, "owned")
end
user.store
That's pretty much it, as far as linking the records goes.
To retrieve the related records, we need to have a start point. That is usually the record holding the links. Link walking is a special case of the Map/Reduce functionality built into Riak.
To traverse the links, we start with the user object. We then issue it the walk command with a few parameters:
- The bucket name (optional)
- The tag name (also optional)
- Whether to keep the result of the walk or not
Code looks like this:
user = users_bucket.get("TkwPo5A7x7UGVVqOigaoSZFq71J")
user.walk("accounts", "owned", true)
[[#<Riak::RObject {accounts,XbLYOr5YwvvRRbtcs51JP3TESVi} [#<Riak::RContent [application/json]:{"type"=>"Chequing", "name"=>"Bank Simple", "balance" => 1103.40}>]>,#< Riak::RObject {accounts,ZqE0aKune4xbFlzPNSfEVOUOucE [#<Riak::RContent [application/json]:{"type"=>"CC", "name"=>"Visa Credit Card", "balance" => 450.12}>]>]]
That's it. The traversal returns a collection of Riak objects representing the records linked to the User record we had previously.
Links can be used as a phase in Map/Reduce jobs in order to get all related objects, assuming a starting object as in the normal traversal.