Search:

Search all manuals
Search this manual
Manual
Couchbase Developer's Guide 1.8
Additional Resources
Community Wiki
Community Forums
Couchbase SDKs
Parent Section
2.9 Updating Information
Chapter Sections
Chapters

2.9.5. Incrementing and Decrementing

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:

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:

Figure 2.16. Using Incr for Unique User Ids

Using Incr for Unique User Ids

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.

Tip

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”