Skip to content
Srdjan Pejic edited this page May 21, 2013 · 1 revision

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.

How Links work

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:

  1. A bucket where the original record resides
  2. The key pointing to the record
  3. A tag that can be used to pluck out specific links from the list a record can hold

Let's get to the code.

Adding links

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.

Traversing aka Link Walking

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.

Additional usage

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.