Managing Clusters
Edit this article in GitHub
Version 2.2

Managing Clusters

The primary means for managing clusters is through the Couchbase Web UI which provides an easy to use interface for adding, removing, monitoring and modifying buckets. In some instances you may wish to have a programmatic interface. For example, if you wish to manage a cluster from a setup script, or if you are setting up buckets in test scaffolding.

The Node SDK also comes with some convenience functionality for common Couchbase management requests.

You can manage Couchbase clusters by using the ClusterManager and BucketManager interfaces that are available through the manager(login, password) and manager() methods exposed in Cluster and Bucket instances.

Creating and removing buckets

Creating buckets and removing buckets is performed, for example, when running unit tests.

The ClusterManager class may be used to create and delete buckets from the Couchbase cluster. It is instantiated through the Cluster's manager() method, providing the administrative username and password.

var clusterManager = cluster.manager("Administrator", "123456")

To create a bucket, use the createBucket(name, opts, callback) method. The opts represents the options of the bucket, an object with the following structure (shown with default values):

var myOpts = {
  authType: 'sasl',
  bucketType: 'couchbase',
  ramQuotaMB: 100,
  replicaNumber: 1,
  saslPassword: null,
  flushEnabled: null
};

The parameters correspond to those in the REST API, most notably:

  • bucketType: Defaults to "couchbase", but can also be "memcached" to create a cache bucket.
  • ramQuotaMB: How much memory should each node use for the bucket. This number is specified in megabytes.
  • saslPassword: If specified, makes this bucket password protected, forcing future connects (using the Bucket) to specify the password parameter. Must be used together with the authType: 'sasl' (which is the default).
  • flushEnabled: Enables the BucketManager#flush() operation to be performed on this bucket (see the Flushing Buckets section below).
  • replicaNumber: The number of replicas to use for the bucket.
  • replicaIndex: Whether or not to replicate indexes.

The following example creates an "hello" bucket with only the flushEnabled differing from the defaults shown above:

var manager = cluster.manager("Administrator", "123456");
manager.createBucket("hello", { flushEnabled: true }, function(err) {
  console.log('Creation of hello bucket failed:', err);
});
You can completely delete a bucket using the removeBucket(name) method:
manager.removeBucket("hello", function(err) {
  console.log('Could not delete hello bucket: ', err);
});

Flushing Buckets

When a bucket is flushed, all content is removed. Because this operation is potentially dangerous it is disabled by default for each bucket. Bucket flushing may be useful in test environments where it becomes a simpler alternative to removing and creating a test bucket. You may enable bucket flushing on a per-bucket basis using the Couchbase Web Console or when creating a bucket.

You may flush a bucket in the Node SDK by using the BucketManager's flush() method:
var bucketMgr = bucket.manager();
bucketMgr.flush(function(err, status) {
  if (status) {
    console.log('Bucket flushed');
  } else {
    console.log('Could not flush bucket: ', err);
  }
});

The flush operation may notably fail if the bucket does not have flush enabled.

View Management

Views are stored in design documents. The SDK provides convenient methods to create, retrieve, and remove design documents. To set up views, you create design documents that contain one or more view definitions, and then insert the design documents into a bucket. Each view in a design document is represented by a name and a set of MapReduce functions. The mandatory map function describes how to select and transform the data from the bucket, and the optional reduce function describes how to aggregate the results.

To create a view, you can use the manager() method of your bucket instance to retrieve a BucketManager instance. After you have a BucketManager instance, invoke the upsertDesignDocument method to store the design document for later querying.

The following example creates or updates a "ddocname" design document with a single "by_name" view on the "hello" bucket (because it is created through hello's BucketManager):

var bucket = cluster.openBucket("hello");
var bucketMgr = bucket.manager();

var ddocdata = {
  views: {
    by_name: {
      map: [ 'function(doc, meta) {',
             '  if (doc.type && doc.type == "beer") {',
             '    emit(doc.name, null);',
             '  }',
             '}'
       ].join('\n')
     },
  }  
};

bucketMgr.upsertDesignDocument('ddocname', ddocdata, function(err) {
  console.log('Insertion of design document completed with error:', err);
});

Alternatively, you can just pass a JavaScript function into the design document manipulation methods and they will automatically be serialized to JavaScript. For instance, the following code snippets are functionally equivalent:

// Using a string
var ddocdata = {
  views: {
    by_name: {
      map: [ 'function(doc, meta) {',
             '  if (doc.type && doc.type == "beer") {',
             '    emit(doc.name, null);',
             '  }',
             '}'
      ].join('\n')
    },
  }
};

// Using a function
var ddocdata = {
  views: {
    by_name: {
      map: function(doc, meta) {
        if (doc.type && doc.type == "beer") {
          emit(doc.name, null);
        }
      }
    },
  }
};
Warning: When you want to update an existing document with a new view (or a modification of a view's definition), you can use the upsertDesignDocument method.

However, this method needs the list of views in the document to be exhaustive, meaning that if you just create the new view definition as previously and add it to a new DesignDocument that you upsert, all your other views will be erased!

The solution is to perform a getDesignDocument, add your view definition to the DesignDocument's views list, then upsert it. This also works with view modifications, provided the change is in the map or reduce functions (just reuse the same name for the modified View), or for deletion of one out of several views in the document.

Here is an example of deleting a view from an existing document, which follows the same principle:

var bucket = cluster.openBucket();
var bucketMgr = bucket.manager();

function deleteView(ddocname, viewname, callback) {
  bucketMgr.getDesignDocument(ddocname, function(err, ddoc, meta) {
    if (err) {
      return callback(err);
    }
    
    //we have the current exhaustive list of views, delete the one we want to remove
    delete ddoc.views[viewname];
    
    //update the new exhaustive design document
    bucketMgr.upsertDesignDocument(ddocname, ddoc, function(err) {
      if (err) {
        return callback(err);
      }
      
      callback(null);
    });
  });
}

deleteView('ddoc', 'view', function(err) {
  console.log('Deletion completed with error:', err);
});

To remove a complete design document from a bucket, pass its name to the removeDesignDocument method.