Skip to content

Latest commit

 

History

History
237 lines (166 loc) · 6.45 KB

File metadata and controls

237 lines (166 loc) · 6.45 KB
.. currentmodule:: riak.datatypes

Data Types

Traditionally all data stored in Riak was an opaque binary type. Then in version 1.4 came the introduction of a :ref:`counter <legacy_counters>`, the first Convergent Data Type supported in Riak. In Riak 2.0, several additional Data Types were introduced. Riak "knows" about these data types, and conflicting writes to them will converge automatically without presenting :ref:`sibling values <siblings>` to the user.

Here is the list of current Data Types:

All Data Types must be stored in buckets bearing a :class:`~riak.bucket.BucketType` that sets the :attr:`~riak.bucket.BucketType.datatype` property to one of "counter", "set", or "map". Note that the bucket must have the allow_mult property set to true.

These Data Types are stored just like :class:`RiakObjects <riak.riak_object.RiakObject>`, so size constraints that apply to normal Riak values apply to Riak Data Types too.

An in-depth discussion of Data Types, also known as CRDTs, can be found at Data Types.

Examples of using Data Types can be found at Using Data Types.

Sending Operations

Riak Data Types provide a further departure from Riak's usual operation, in that the API is operation-based. Rather than fetching the data structure, reconciling conflicts, mutating the result, and writing it back, you instead tell Riak what operations to perform on the Data Type. Here are some example operations:

Datatypes can be fetched and created just like :class:`~riak.riak_object.RiakObject` instances, using :meth:`RiakBucket.get <riak.bucket.RiakBucket.get>` and :meth:`RiakBucket.new <riak.bucket.RiakBucket.new>`, except that the bucket must belong to a bucket-type that has a valid datatype property. If we have a bucket-type named "social-graph" that has the datatype "set", we would fetch a :class:`Set` like so:

graph = client.bucket_type('social-graph')
graph.datatype  # => 'set'
myfollowers = graph.bucket('followers').get('seancribbs')
# => a Set datatype

Once we have a datatype, we can stage operations against it and then send those operations to Riak:

myfollowers.add('javajolt')
myfollowers.discard('roach')
myfollowers.update()

While this looks in code very similar to manipulating :class:`~riak.riak_object.RiakObject` instances, only mutations are enqueued locally, not the new value.

Context and Observed-Remove

In order for Riak Data Types to behave well, you must have an opaque context received from a read when you:

The basic rule is "you cannot remove something you haven't seen", and the context tells Riak what you've actually seen, similar to the :ref:`vclock` on :class:`~riak.riak_object.RiakObject`. The Python client handles opaque contexts for you transparently as long as you fetch before performing one of these actions.

Datatype abstract class

.. autoclass:: Datatype

   .. autoattribute:: value
   .. autoattribute:: context
   .. autoattribute:: modified

Persistence methods

.. automethod:: Datatype.reload
.. automethod:: Datatype.update
.. function:: Datatype.store(**params)

    This is an alias for :meth:`~riak.datatypes.Datatype.update`.

.. automethod:: Datatype.delete
.. automethod:: Datatype.clear

Counter

.. autoclass:: Counter

.. attribute:: Counter.value

   The current value of the counter.

   :rtype: int

.. automethod:: Counter.increment
.. automethod:: Counter.decrement

Set

.. autoclass:: Set

.. attribute:: Set.value

   An immutable copy of the current value of the set.

   :rtype: frozenset

.. automethod:: Set.add
.. automethod:: Set.discard

Map

.. autoclass:: Map

.. autoattribute:: Map.value

.. attribute:: Map.counters

   Filters keys in the map to only those of counter types. Example::

        map.counters['views'].increment()
        del map.counters['points']


.. attribute:: Map.flags

   Filters keys in the map to only those of flag types. Example::

        map.flags['confirmed'].enable()
        del map.flags['attending']


.. attribute:: Map.maps

   Filters keys in the map to only those of map types. Example::

        map.maps['emails'].registers['home'].set("user@example.com")
        del map.maps['spam']


.. attribute:: Map.registers

   Filters keys in the map to only those of register types. Example::

        map.registers['username'].set_value("riak-user")
        del map.registers['access_key']

.. attribute:: Map.sets

   Filters keys in the map to only those of set types. Example::

        map.sets['friends'].add("brett")
        del map.sets['favorites']

Map-only datatypes

Two of the new Data Types may only be embedded in :py:class:`Map <riak.datatypes.Map>` objects (in addition to :py:class:`Map <riak.datatypes.Map>` itself):

Register

.. autoclass:: Register

.. autoattribute:: Register.value
.. automethod:: Register.assign

Flag

.. autoclass:: Flag

.. attribute:: Flag.value

   The current value of the flag.

   :rtype: bool, None

.. automethod:: Flag.enable
.. automethod:: Flag.disable