Key Value Operations

These pages cover the first Developer Preview of the Couchbase .NET SDK 3.0 (DP1). As such they are likely to change without notice. The DP1 code should not be used in production.

The complete code sample used on this page can be downloaded from /// here - from which you can see in context how to authenticate and connect to a Couchbase Cluster, then perform these Bucket operations.

Documents

A document refers to an entry in the database (other databases may refer to the same concept as a row). A document has an ID (primary key in other databases), which is unique to the document and by which it can be located. The document also has a value which contains the actual application data. See :concept-docs:documents for a deeper dive into documents in the Couchbase Data Platform. Or read on, for a hands-on introduction to working with documents from the .NET SDK.

CRUD Operations

The core interface to Couchbase Server is simple KV operations on full documents. Make sure you’re familiar with the basics of authorization and connecting to a Cluster from the :hello-world:start-using-sdk. We’re going to expand on the short Upsert example we used there, adding options as we move through the various CRUD operations. Here is the Insert operation at its simplest:

Insert
var document = new {foo = "bar", bar = "foo"};
var result = await collection.Insert("document-key", document);

Options may be added to operations:

Insert (with options)
var document = new {foo = "bar", bar = "foo"};
var result = await collection.Insert("document-key", document,
    new InsertOptions
    {
        Cas = 12345,
        Timeout = TimeSpan.FromSeconds(5)
    }
);

Setting a Compare and Swap (CAS) value is a form of optimistic locking - dealt with in depth in the CAS page. Here we just note that the CAS is a value representing the current state of an item; each time the item is modified, its CAS changes. The CAS value is returned as part of a document’s metadata whenever a document is accessed. Without explicitly setting it, a newly-created document would have a CAS value of 0.

Timeout is an optional parameter which in the .NET SDK has a type value of TimeSpan. Timeout sets the timeout value for the underlying network connection. We will add to these options for the Replace example:

var document = new {foo = "bar", bar = "foo"};
var result = await collection.Replace("document-key", document,
    new ReplaceOptions
    {
        Cas = 12345,
        Expiration = TimeSpan.FromMinutes(1),
        Timeout = TimeSpan.FromSeconds(5)
    }
);

Expiration sets an explicit time to live (TTL) for a document, for which you can also see a more detailed example of TTL discovery later in the docs. We’ll discuss modifying Expiration in more details below. For a discussion of item (Document) vs Bucket expiration, see the Expiration Overview page.

var document = new {foo = "bar", bar = "foo"};
var result = await collection.Upsert("document-key", document,
    new UpsertOptions
    {
        Cas = 12345,
        Expiration = TimeSpan.FromMinutes(1),
        PersistTo = PersistTo.One,
        ReplicateTo = ReplicateTo.One,
        Timeout = TimeSpan.FromSeconds(5)
    }
);

Here, we have add Durability options, namely PersistTo and ReplicateTo. In Couchbase Server releases before 6.5, Durability was set with these two options — see the 6.0 Durability documentation — covering how many replicas the operation must be propagated to and how many persisted copies of the modified record must exist. Couchbase Data Platform 6.5 refines these two options, with Synchronous Replication — although they remain essentially the same in use — see Durability, below.

Sub-Document Operations

All of these operations involve fetching the complete document from the Cluster. Where the number of operations or other circumstances make bandwidth a significant issue, the SDK can work on just a specific path of the document with Sub-Docunent Operations.

Retrieving full documents

Using the Get() method with the document key can be done in a similar fashion to the other operations:

var result = await collection.Get(“document-key”);
var content = result.ContentAs<string>();

Timeout can also be set - as in the earlier Insert example:

Get (with options)
var result = await collection.Get(“document-key”,
    new GetOptions
    {
        Timeout = TimeSpan.FromSeconds(5)
    }
);
var content = result.ContentAs<string>();

Removing

When removing a document, you will have the same concern for durability as with any additive modification to the Bucket:

Remove (with options)

var result = await collection.Remove("document-key",
    new RemoveOptions
    {
        Cas = 12345,
        PersistTo = PersistTo.One,
        ReplicateTo = ReplicateTo.One,
        Timeout = TimeSpan.FromSeconds(5)
    }
);

Durability

Writes in Couchbase are written to a single node, and from there the Couchbase Server will take care of sending that mutation to any configured replicas.

The optional durability parameter, which all mutating operations accept, allows the application to wait until this replication (or persistence) is successful before proceeding.

It can be used like this:

// durability kv snippet

If no argument is provided the application will report success back as soon as the primary node has acknowledged the mutation in its memory. However, we recognize that there are times when the application needs that extra certainty that especially vital mutations have been successfully replicated, and the other durability options provide the means to achieve this.

The options differ depend on what Couchbase Server version is in use. If 6.5 or above is being used, you can take advantage of the Durable Write feature, in which Couchbase Server will only return success to the SDK after the requested replication level has been achieved. The three replication levels are:

  • Majority - The server will ensure that the change is available in memory on the majority of configured replicas.

  • MajorityAndPersistToActive - Majority level, plus persisted to disk on the active node.

  • PersistToMajority - Majority level, plus persisted to disk on the majority of configured replicas.

The options are in increasing levels of safety. Note that nothing comes for free - for a given node, waiting for writes to storage is considerably slower than waiting for it to be available in-memory. These trade offs, as well as which settings may be tuned, are discussed in the durability page.

In a version of Couchbase Server lower than 6.5 is being used then the application can fall-back to 'client verified' durability. Here the SDK will do a simple poll of the replicas and only return once the requested durability level is achieved. This can be achieved like this:

// Durability observed snippet

To stress, durability is a useful feature but should not be the default for most applications, as there is a performance consideration, and the default level of safety provided by Couchbase will be reasonable for the majority of situations.

Expiration / TTL

By default, Couchbase documents do not expire, but transient or temporary data may be needed for user sessions, caches, or other temporary documents. Using Touch(), you can set expiration values on documents to handle transient data:

var result = await collection.Touch("document-key", TimeSpan.FromSeconds(10));

A network timeout can be set with the optional TouchOptions(), in the same fashion as earlier examples on this page:

var result = await collection.Touch("document-key", TimeSpan.FromSeconds(30),
    new TouchOptions
    {
        Timeout = TimeSpan.FromSeconds(5)
    }
);

Atomic document modifications

The value of a document can be increased or decreased atomically using Binary.Increment() and .Binary.Decrement().

Increment
// increment binary value by 1, if document doesn’t exist, seed it at 1000
await collection.Binary.Increment("document-key", 1, 1000);
.Increment (with options)
// increment binary value by 1, if document doesn’t exist, seed it at 1000
// optional arguments:
// - Timeout (TimeSpan)
// - Expiration (TimeSpan)
// - CAS (ulong)

await collection.Binary.Increment("document-key", 1, 1000, TimeSpan.FromSeconds(5), TimeSpan.FromDays(1), cas);
Decrement
// decrement binary value by 1, if document doesn’t exist, seed it at 1000
await collection.Binary.Decrement("document-key", 1, 1000);
Increment (with options)
// decrement binary value by 1, if document doesn’t exist, seed it at 1000
// optional arguments:
// - Timeout (TimeSpan)
// - Expiration (TimeSpan)
// - CAS (ulong)
await collection.Binary.Decrement("document-key", 1, 1000, TimeSpan.FromSeconds(5), TimeSpan.FromDays(1), cas);
Increment & Decrement are considered part of the ‘binary’ API and as such may still be subject to change

Additional Resources

Working on just a specific path within a JSON document will reduce network bandwidth requirements - see the Sub-Document pages. For working with metadata on a document, reference our Extended Attributes pages.

Another way of increasing network performance is to pipeline operations with Batching Operations.

As well as various Formats of JSON, Couchbase can work directly with arbitary bytes, or binary format.

Our Query Engine enables retrieval of information using the SQL-like syntax of N1QL.