These methods can increment or decrement a value for a given key, if that value can be interpreted as an integer value. Couchbase Server requires that the value be an ASCII number to be incremented or decremented
Both of these methods are atomic; this means that multiple threads can be incrementing/decrementing a key without conflicting with other threads that are also incrementing/decrementing the value. Note however that if concurrent threads make a request to increment or decrement a value, there is no guarantee on which thread will change a value first.
The operations are provided as convenience methods for scenarios where you want to have some sort of counter; they eliminate the need for you to explicitly get, update and then reset an integer item through separate database operations.
The primary use for these the incr
method is to increment a counter, typically to represent the
number of page visits. Generally they can be used for any
scenario where you have a frequently updated counter. For
instance, if you have a coupon with a limited number of
redemptions, you could store the redemptions as a separate key,
and decrement the redemptions each time someone uses the coupon.
There are several other uses for incr
that enable you to create unique keys be incrementing a value.
Here are some suggested uses:
Provide an index for individual items such as comments, users, products, and other lists of items that grow considerably.
Generate keys based on an atomic counter, and use that key as a reference to other documents in Couchbase.
For instance, you can use incr to
create a unique user id for a system. First you would need a
document that represents the counter. In Ruby we could do this:
c = Couchbase.new # => setup default connection c.set("user::count", 0)
Then you would increment the counter each time you store a new user to the system and store the new counter value as part of the unique key for the new user:
# increment the counter-id and assign to user id new_id = c.incr("user::count") # store the counter-id as a self-reference user_hash = { :uid => new_id, :username => "donp", :firstname => "Don", :lastname => "Pinto" } # create the document with the counter-id and hash c.add("user::#{new_id}", user_hash)
The entire process would be as follows, if you imagine we want to create a unique user id for a spaceship game. In this case we increment the user count, and then apply it to the new key for the user:
Both incr and
decr are considered 'binary' methods in
that they operate on binary data, not JSON documents. Because of
this, keys used by incr and
decr cannot be queried or indexed with
Couchbase Server 2.0.
Couchbase Server stores and transmits numbers as unsigned numbers, therefore if you try to store negative number and then increment, it will cause overflow. In this case, an integer overflow value will be returned. See the integer overflow example that follows. In the case of decrement, if you attempt to decrement zero or a negative number, you will always get a result of zero.
The next example demonstrates use of
incr to identify documents with unique
ids and retrieve them with the id:
# initialize the counter c = Couchbase.new # => setup default connection c.set("user::count", 0) # => initialize counter
First we create a new Couchbase client instance and create a new item which represents the counter. then we increment the counter each time we create a new user in Couchbase Server:
# retrieve the latest (so you see incr adds one...) c.get("user::count") # => 3 # increment the counter-id new_id = c.incr("user::count") # => new_id = 4 # store the counter-id as a reference to the new user user_hash = { :uid => new_id, :username => "jsmith", :firstname => "John", :lastname => "Smith" } # create the document with the counter-id as key and hash as value c.add("user::#{new_id}", user_hash) # => save new user, with document key = "user::4"
We first start by retrieving the current counter, to find out
the most recently used number for current users. Then we
increment the counter by one and store this new count to
new_id which we will use as part of the
new key. Finally we add the new user
item.
If we want to retrieve the newest user to the system, we can use the latest counter item and use that in the key we retrieve:
# retrieve the latest latest_user = c.get("user::count") # => latest_user = 4 # retrieve the document with the index user_info = c.get("user::#{latest_user}") # => retrieve user document # outputs { "uid" => 4, "username" => "jsmith", "firstname" => "John", "lastname" => "Smith" } puts user_info
The memcached protocol equivalents for this method are
incr and decr
which are the commands for incrementing and decrementing. For
more information about the underlying protocol, see
memcached
protocol.
Couchbase Server returns no specific operation-level error
objects when you perform this operation. If a key does not
exist, incr and
decr at the SDK-level will create the
new key and initialize it with the value you provide, or set the
default of 0. As demonstrated above, if you try to increment a
negative number, Couchbase Server will return an integer
overflow number. If you try to decrement so the result is a
negative number, Couchbase server will return 0.
The types of errors that can occur during this operation include 1) inability to connect to a node, or 2) some error exists while attempting to use a key being stored. If you have a connection-level error you may need to reattempt connection, and possibly check the status of the server.
For more information about connections and connection-level settings, see Section 6.4.4, “Optimizing Client Instances” and Section 6.6.1, “Client-Side Timeouts”