# Introduction

```
          __       __________________                 __    __                  
      ____\ \     / ____/ ____/ ____/___  __  _______/ /_  / /_  ____ _________ 
     /____/\ \   / /   / /_  / /   / __ \/ / / / ___/ __ \/ __ \/ __ `/ ___/ _ \
    /____/ / /  / /___/ __/ / /___/ /_/ / /_/ / /__/ / / / /_/ / /_/ (__  )  __/
          /_/   \____/_/    \____/\____/\__,_/\___/_/ /_/_.___/\__,_/____/\___/
```

![](https://3913943779-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvAnI0cY_mWVYJE%2F-LA-UdCGWmrQ8Xvggj60%2F-LA-UqjlHA3d75TpDqUW%2Fcfcouchbase-185-logo.png?generation=1523648000981242\&alt=media)

## Welcome to CFCouchbase SDK v2.2.0

The CFCouchbase SDK is a CFML library for interacting with [Couchbase NoSQL Server](http://www.couchbase.com). It can be used by any CFML application or CFML framework to provide them with NoSQL, distributed caching, dynamic queries and many more capabilities. The CFCouchbase SDK wraps the Couchbase Java SDK and enhances it to provide with a nice dynamic language syntax and usability.

> **Info** Initially sponsored by Guardly, Inc ([www.guardly.com](http://www.guardly.com))
>
> Couchbase is copyright and a registered trademark by Couchbase, Inc.

## Versioning

CFCouchbase is maintained under the [Semantic Versioning](https://semver.org) guidelines as much as possible. Releases will be numbered with the following format:

```
<major>.<minor>.<patch>
```

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

### License

CFCouchbase is open source and licensed under the [Apache 2](http://www.apache.org/licenses/LICENSE-2.0.html) License.

## Discussion & Help

The CFCouchbase help and discussion group can be found here: <https://groups.google.com/a/ortussolutions.com/forum/#!forum/cfcouchbase>

## Reporting a Bug

We all make mistakes from time to time :) So why not let us know about it and help us out. We also love pull requests, so please star us and fork us: <https://github.com/Ortus-Solutions/cfcouchbase-sdk>

* By Jira: <https://ortussolutions.atlassian.net/browse/COUCHBASESDK>

## Professional Open Source

![Ortus Solutions, Corp](https://3913943779-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvAnI0cY_mWVYJE%2F-LA-UdCGWmrQ8Xvggj60%2F-LA-UqkepONrxKPpy21d%2Fortussolutions_button.png?generation=1523648000961561\&alt=media)

CFCouchbase is a professional open source software backed by [Ortus Solutions, Corp](http://www.ortussolutions.com/products/cfcouchbase) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](http://www.ortussolutions.com/services)

### Resources

* Source Code - <https://github.com/Ortus-Solutions/cfcouchbase-sdk>
* Tracker Site (Bug Tracking, Issues) - <https://ortussolutions.atlassian.net/browse/COUCHBASESDK>
* Documentation - <https://cfcouchbase.ortusbooks.com/>
* Blog - <http://www.ortussolutions.com/blog>
* Official Site - <https://www.ortussolutions.com/products/cfcouchbase>

#### HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, its not for you.

> Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God. - Romans 5:5


# What's New With 2.2.0

This release of the CFCouchbase SDK brings support for the latest JDK v2.5.4, adds support for RBAC (Role Based Access Control) which was introduced in Couchbase Server 5.0.0.

These changes will allow you to take advantage of the new Ephemeral buckets in Couchbase Server 5, which are memory only buckets and ideal candidates for caching implementations. To find out more about all of the features in Couchbase Server 5 check out the SDK release notes <https://developer.couchbase.com/documentation/server/current/release-notes/relnotes.html> and blog post <https://blog.couchbase.com/announcing-couchbase-server-5-0/>

## Release Notes

### Improvements

* \[[COUCHBASESDK-49](https://ortussolutions.atlassian.net/browse/COUCHBASESDK-49)] -Add RBAC Support&#x20;
* \[[COUCHBASESDK-50](https://ortussolutions.atlassian.net/browse/COUCHBASESDK-50)] -Upgraded JARs to latest (v2.5.4)


# What's New With 2.0.0

More than two years have passed since our SDK v1.1 was released. The SDK has been updated to support the new functionality available in Couchbase Server 4.x, including:

* N1QL Queries
* GSI Indexes
* Replica Reads
* Document Locking
* Prepared Statements
* Improved Design Document Management
* Expanded Configuration Options
* And more...

## Changes

CFCouchbase uses the [Java SDK](http://developer.couchbase.com/documentation/server/current/sdks/java-2.2/java-intro.html) from Couchbase, when it went from version 1.x to 2.x breaking changes occurred (for the better). We have tried to mitigate these changes where possible. Many methods that were removed from the Java SDK and we created as facades for backwards compatibility. All of these methods have been marked from deprecation, but are still supported for the time being.

* `add()` => `insert()`
* `decr()` => `counter()`
* `incr()` => `counter()`&#x20;
* `delete()` => `remove()`&#x20;
* `set()` => `upsert()`
* `setMulti()` => `upsertMulti()`
* `setWithCAS()` > `replaceWithCAS()`

The SDK also brings many new methods, some of which we will cover in detail.

* `exists()`
* `getAndLock()`
* `getEnvironment()`
* `getFromReplica()`
* `invalidateQueryCache()`
* `n1qlQuery()`
* `publishDesignDocument()`
* `replace()`
* `unlock()`

## N1QL Queries

One of the biggest additions to the SDK is support for [N1QL](http://developer.couchbase.com/documentation/server/current/getting-started/first-n1ql-query.html) (pronounced "nickel"). N1QL is a "SQL like" syntax for working with JSON documents in Couchbase Server. You can perform a N1QL query by calling the `query(type="n1ql", statement="...")` method or by calling the `n1qlQuery("...")` method directly. Just as with View queries, the same options are available to N1QL queries, this includes:

* `deserialize`
* `deserializeOptions`
* `inflateTo`
* `filter`
* `transform`

The most basic (and fastest) N1QL operation is to retrieve document(s) by their document id.

```
// query
couchbase.n1qlQuery('
  SELECT u.* 
  FROM users AS u
  USE KEYS "user_101"
');
```

Notice the `FROM` clause, in this example "users" is the name of a bucket. This query can be described as:

> "Get every property from the 'user\_101' document in the 'users' bucket"

All N1QL queries will return an array, the response from this query would return an array of structures.

```javascript
[
  {
    "email": "Judah66@gmail.com",
    "first_name": "Albin",
    "last_name": "Price",
    "user_id": 101,
    "username": "Eudora43"
  }
]
```

The `USE KEYS` statement is not limited to single values either, multiple documents can be retrieved by declaring an array.

```
couchbase.n1qlQuery('
  SELECT u.* 
  FROM users AS u
  USE KEYS [ "user_101", "user_454" ]
');
```

N1QL supports the standard DML operations that you would expect.

```
// insert a new document
couchbase.n1qlQuery('
  INSERT INTO users (KEY, VALUE)
  VALUES ("user_2343", {
    "user_id": 2343,
    "name": "John Smith",
    "email": "john.smith@gmail.com"
  })
');

// update a specific property of a document
couchbase.n1qlQuery('
  UPDATE users
  USE KEYS "user_2343"
  SET email = "elmariachi@gmail.com"
');

// remove a document
couchbase.n1qlQuery('
  DELETE 
  FROM users
  USE KEYS "user_2343"
');

// update or insert an entire document
couchbase.n1qlQuery('
  UPSERT INTO users (KEY, VALUE)
  VALUES ("user_2343", {
    "user_id": 2343,
    "name": "John Smith",
    "email": "elmariachi@gmail.com"
  })
');
```

Up to this point our queries have used just an ID when working with documents. What if we wanted to find documents based on a properties value? To do this we need to create [GSI (Global Secondary) Indexes](http://developer.couchbase.com/documentation/server/current/architecture/global-secondary-indexes.html).

```
// create an index of usernames
couchbase.n1qlQuery('
  CREATE INDEX idx_users_username 
    ON ecommerce( username )
  USING GSI
');

// query based on username
couchbase.n1qlQuery('
  SELECT users.* 
  FROM ecommerce AS users
  WHERE users.username = 'Eudora43'
');
```

There are several [options](http://developer.couchbase.com/documentation/server/current/n1ql/n1ql-language-reference/createindex.html) for creating indexes, such as partitioning, building, covering, array indexing, etc. that are not covered in this post.

A common practice in SQL is to `JOIN` results across tables. N1QL supports joining results in a bucket as well as across buckets. `JOIN` statements utilize the `USE KEYS` clause.

```
// query to get all of the orders by username
couchbase.n1qlQuery('
  SELECT orders.order_id, orders.order_date, orders.total
  FROM ecommerce AS users
  INNER JOIN ecommerce AS orders 
    ON KEYS users.order_history
  WHERE u.username = 'Eudora43'
');
```

## Document Locking

There may be instances where your application needs to prevent retrieval and updates to a given document. Document updates can be prevented by using the CAS operations, but this is not always guaranteed. The 2.0 SDK allows you to retrieve a document and lock it (for up to 30 seconds), then unlock it by updating it with CAS value at a later point in time.

```
// get the user document and lock it
user = couchbase.getAndLock("user_101");

// update and unlock the document using CAS
couchbase.replaceWithCAS(
  id="user_101",
  value=doc,
  cas=user.cas
);

// unlock the document without updating it
couchbase.unlock(
  id="user_101",
  cas=user.cas
);
```

Calls to retrieve or update document that has been locked, will fail until the document has been successfully unlocked or the maximum time of 30 seconds has passed.

## Config

There are 44 new configuration options supported by the SDK. The options will allow you to tweak and tune your configuration to meet your needs. Examples include `caseSensitiveKeys`, `connectTimeout`, `sslEnabled`, `queryTimeout`. Please see the [documentation](http://developer.couchbase.com/documentation/server/current/sdks/java-2.2/env-config.html#story-h2-2) for detailed descriptions of each configuration option.

With the changes from the 1.x to 2.x SDK the following configuration options are no longer supported:

* maxReconnectDelay
* obsPollInterval
* obsPollMax
* opQueueMaxBlockTime
* opTimeout
* readBufferSize
* shouldOptimize
* timeoutExceptionThreshold

## Resources

Please visit our [CFCouchbase](https://www.ortussolutions.com/products/cfcouchbase) page for all the necessary resources.

* [ITB Presentation - CFCouchbase 2.0 + N1QL](https://www.slideshare.net/secret/425CbL6sce5N2b)
* [Couchbase Developer Portal](http://developer.couchbase.com)
* [N1QL Query Tutorial](http://query.pub.couchbase.com/)
* [ColdBox Travel Sample](https://github.com/coldbox-samples/cfcouchbase-travel)
* [N1QL Flight Data Examples](https://github.com/bentonam/fakeit-examples/tree/master/flight-data/docs/n1ql)


# About This Book

The source code for this book is hosted in GitHub: <https://github.com/Ortus-Solutions/cfcouchbase-sdk-docs>. You can freely contribute to it and submit pull requests. The contents of this book is copyright by [Ortus Solutions, Corp](http://www.ortussolutions.com) and cannot be altered or reproduced without author's consent. All content is provided *"As-Is"* and can be freely distributed.

* The majority of code examples in this book are done in `cfscript`.
* The majority of code generation and running of examples are done via **CommandBox**: The ColdFusion (CFML) CLI, Package Manager, REPL - <http://www.ortussolutions.com/products/commandbox>
* All ColdFusion examples designed to run on the open soure Lucee Platform or Adobe ColdFusion 9.0.2+

## External Trademarks & Copyrights

Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc.

## Notice of Liability

The information in this book is distributed “as is”, without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity with respect to loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software and resources described in it.

## Contributing

We highly encourage contribution to this book and our open source software. The source code for this book can be found in our [GitHub repository](https://github.com/Ortus-Solutions/cfcouchbase-sdk-docs) where you can submit pull requests.

## Charitable Proceeds

15% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - <http://www.harvesting.org/>. So please donate and purchase the printed version of this book, every book sold can help a child for almost 2 months.

### Shalom Children's Home

![Shalom Children's Home](https://3913943779-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvAnI0cY_mWVYJE%2F-LA-UdCGWmrQ8Xvggj60%2F-LA-UqkafWh6fAdOKyqD%2Fshalom.jpg?generation=1523648000854719\&alt=media)

Shalom Children’s Home (<http://www.harvesting.org/>) is one of the ministries that is dear to our hearts located in El Salvador. During the 12 year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children werecame on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded.

Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education and life skills training in a Christian environment. The home is supported by a child sponsorship program.

We have personally supported Shalom for over 6 years now; it is a place of blessing for many children in El Salvador that either have no families or have been abandoned. This is good earth to seed and plant.


# Authors

## Luis Fernando Majano Lainez

![](https://3913943779-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvAnI0cY_mWVYJE%2F-LA-UdCGWmrQ8Xvggj60%2F-LA-UqmOMGRBLDv1Phl6%2Fluismajano.jpg?generation=1523648000579238\&alt=media)

Luis Majano is a Computer Engineer with over 16 years of software development and systems architecture experience. He was born in [San Salvador, El Salvador](http://en.wikipedia.org/wiki/El_Salvador) in the late 70’s, during a period of economical instability and civil war. He lived in El Salvador until 1995 and then moved to Miami, Florida where he completed his Bachelors of Science in Computer Engineering at [Florida International University](http://fiu.edu). Luis resides in The Woodlands, Texas with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!

He is the CEO of [Ortus Solutions](http://www.ortussolutions.com), a consulting firm specializing in web development, ColdFusion (CFML), Java development and all open source professional services under the ColdBox and ContentBox stack. He is the creator of ColdBox, ContentBox, WireBox, MockBox, LogBox and anything “BOX”, and contributes to many open source ColdFusion projects. He is also the Adobe ColdFusion user group manager for the [Inland Empire](http://www.iecfug.org). You can read his blog at [www.luismajano.com](http://www.luismajano.com)

Luis has a passion for Jesus, tennis, golf, volleyball and anything electronic. Random Author Facts:

* He played volleyball in the Salvadorean National Team at the tender age of 17
* The Lord of the Rings and The Hobbit is something he reads every 5 years. (Geek!)
* His first ever computer was a Texas Instrument TI-86 that his parents gave him in 1986. After some time digesting his very first BASIC book, he had written his own tic-tac-toe game at the age of 9. (Extra geek!)
* He has a geek love for circuits, microcontrollers and overall embedded systems.
* He has of late (during old age) become a fan of running and bike riding with his family.

> Keep Jesus number one in your life and in your heart. I did and it changed my life from desolation, defeat and failure to an abundant life full of love, thankfulness, joy and overwhelming peace. As this world breathes failure and fear upon any life, Jesus brings power, love and a sound mind to everybody!
>
> “Trust in the LORD with all your heart, and do not lean on your own understanding.” \
> &#x20;Proverbs 3:5

## Brad Wood

Brad grew up in southern Missouri where he systematically disassembled every toy he ever owned which occasionally led to unintentional shock therapy (TVs hold charge long after they've been unplugged, you know) After high school he majored in Computer Science with a music minor at [MidAmerica Nazarene University](http://www.mnu.edu) (Olathe, KS). Today he lives in Kansas City with his wife and three girls where he still disassembles most of his belongings (including automobiles) just with a slightly higher success rate of putting them back together again.) Brad enjoys church, all sorts of international food, and the great outdoors.

Brad has been programming CFML for 12+ years and has used every version of CF since 4.5. He first fell in love with ColdFusion as a way to easily connect a database to his website for dynamic pages. Brad blogs at (<http://www.codersrevolution.com>) and likes to work on solder-at-home digitial and analog circuits with his daughter as well as building projects with Arduino-based microcontrollers.

Brad's CommandBox Snake high score is 141.

## Contributors

* Aaron Benton


# Overview

The CFCouchbase SDK is a CFML library for interacting with [Couchbase NoSQL Server](http://www.couchbase.com). It can be used by any CFML application or CFML framework to provide them with NoSQL, distributed caching, dynamic queries and many more capabilities. The CFCouchbase SDK wraps the Couchbase Java SDK and enhances it to provide with a nice dynamic language syntax and usability.

## Couchbase SDK Version

The Couchbase SDK Version used is 2.2.6

## Capabilities

* Lightweight, standalone library can be used with any CFML application or CFML framework
* High performance
* Asynchronous calls&#x20;
* Auto-sharding of documents evenly across cluster
* 24/7 uptime via on-the-fly node removal and rebalance operations  &#x20;
* Easily configurable
* Fully-featured API includes view management and execution
* Built on the official Java SDK, but customized to take advantage of CFML
* Optimistic concurrency control (Documents are not locked by default for maximum throughput)
* Conflict management via Compare And Swap (CAS) mechanism
* Full cluster and document stats available
* Provides direct access to underlying Java SDK for advanced usage&#x20;
* Ability to create as many Couchbase clients as necessary


# Installation

CFCouchbase ships with the following contents:

* `/cfcouchbase` - This is the actual SDK code
* `/apidocs` - The API docs that show you the FULL list of SDK methods and their arguments (even ones not covered here). There is also an \[Online Version] as well.
* `/samples` - A collection of sample apps that use the "beer-sample" bucket. &#x20;
  * `/beer-brewery-manager` - Showcases view creation, and basic CRUD operations utilizing native CF data structures
  * `/beer-brewery-manager-oo` - Same as above but with OO design patterns.  Showcases Couchbase CFC inflation
  * `/beer-brewery-manager-mvc` - Same as above but as an MVC application. Requires a /coldbox mapping on your server.
  * `/coldbox-sample` - A sample ColdBox application that shows loading CFCouchbase via a module. Requires a /coldbox mapping.&#x20;

> **Hint** The API Docs also have descriptions and code samples for every method. They are a must read as well!

## System Requirements

* Lucee 4.5+
* ColdFusion 10+

## CommandBox Installation

The easiest way to get started with CFCouchbase is to use [CommandBox CLI](https://www.ortussolutions.com/products/commandbox) to install in any directory:

```bash
box install cfcouchbase
```

This approach can be used for the following application approaches:

* [ColdBox Module](/installation/coldbox-module)
* [Traditional ColdFusion Apps](/installation/traditional-apps)


# ColdBox Module

The CFCouchbase SDK is already a ColdBox Module. So if you are building a ColdBox MVC application you can install the SDK with CommandBox via: `box install cfcouchbase`. The SDK will be installed in your `modules` directory, create a mapping called `cfcouchbase` for you, manage all SDK instances and create all the WireBox binders for you.

## WireBox Mappings

The following objects are already mapped in the module edition and can be injected anywhere in your ColdBox application.

* `CouchbaseConfig@cfcouchbase` maps to `cfcouchbase.config.CouchbaseConfig`
* `CouchbaseClient@cfcouchbase` maps to `cfcouchbase.CouchbaseClient`

## ColdBox Settings

You can configure the SDK by creating a `couchbase` structure in your `ColdBox.cfc configuration file. This structure can contain any setting from the`CouchbaseConfig`object and ColdBox will configure the`CouchbaseClient\` for you.

```
couchbase = {
    servers     = "http://127.0.0.1:8091",
    bucketname     = "default",
    viewTimeout    = "1000"
};
```


# Traditional Apps

Download the SDK from the following sources or use CommandBox: `box install cfcouchbase` to install the SDK

* Official Releases: <http://www.ortussolutions.com/products/cfcouchbase>&#x20;
* Source: <https://github.com/Ortus-Solutions/cfcouchbase-sdk> Github
* Bleeding Edge + More: <http://integration.stg.ortussolutions.com/artifacts/ortussolutions/cfcouchbase/>

## The Mapping

The CFCouchase SDK is contained in a single folder. The easiest way to install it is to copy `cfcouchbase` in the web root. For a more secure installation, place it outside the web root and create a mapping called `cfcouchbase`.

```
this.mappings[ '/cfcouchbase' ] = 'C:\path\to\cfcouchbase';
```

Now that the code is in place, all you need to do is create an instance of `cfcouchbase.CouchbaseClient` for each bucket you want to connect to. The `CouchbaseClient` class is thread safe and you only need one instance per bucket for your entire application. It is recommended that you store the instantiated client in a persistent scope such as `application` when your app starts up so you can access it easily.

```
public boolean function onApplicationStart(){
    application.couchbase = new cfcouchbase.CouchbaseClient();
    return true;
}
```

## WireBox

However, we would recommend you use a dependency injection framework like [WireBox](https://wirebox.ortusbooks.com) to create and manage your Couchbase Client:

```
// Map our Couchbase Client via WireBox Binder
map( "CouchbaseClient" )
    .to( "cfcouchbase.CouchbaseClient" )
    .initArg( name="config", value={} )
    .asSingleton();
```

## Shutting Down The Client

When you are finished with the client, you need to call its `shutdown()` method to close open connections to the Couchbase server. The following code sample will wait up to 10 seconds for connections to be closed.

```
public boolean function onApplicationEnd(){        
    application.couchbase.shutdown( 10 );
    return true;
}
```

> **Danger:** Each Couchbase bucket operates independently and uses its own authentication mechanisms. You need an instance of `CouchbaseClient` for each bucket you want to interact with. It is also extremely important that you shutdown the clients whenever your application goes down in order to gracefully shutdown connections, else your server might degrade.


# Configuration

The most portable method for configuring the client is to use a CFC to place your config settings in much like our other libraries such as [WireBox](https://wirebox.ortusbooks.com) and [CacheBox](https://cachebox.ortusbooks.com) allow. To do this simply create a plain CFC with a public method called `configure()`. Inside of that method, put your config settings into the variables scope of the component. The `configure()` method does not need to return any value. It will be automatically invoked by the SDK prior to the config settings being extracted from the CFC.

```javascript
component {

    function configure() {
        servers = ['http://cache1:8091','http://cache2:8091'];
        bucketName = 'myBucket';
        password = 'myPass';
    }

}
```

To use the config CFC, simply pass it into the `CouchbaseClient's` constructor.

```javascript
// You can pass an instance
couchbase = new cfcouchbase.CouchbaseClient( new path.to.config() );

// You can also pass a path to the CFC
couchbase = new cfcouchbase.CouchbaseClient( 'path.to.config' );
```


# Settings

There are a number of configuration options you can set for the client, but most of them can be left at their default value. To see a full list of options, look in the `/cfcouchbase/config/CouchbaseConfig.cfc` or the user friendly [API Docs](http://apidocs.ortussolutions.com/cfcouchbase/2.0.0). Here are some of the most common setting you will need to use:

## Common Config Settings

| Setting           | Type    | Default        | Description                                                                                                                                                                                                                                         |
| ----------------- | ------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| servers           | any     | 127.0.0.1:8091 | The list of servers to connect to. Can be comma-delimited list or an array. If you have more than one server in your cluster, you only need to specify one, but adding more than one will help in the event a node is down when the client connect. |
| bucketName        | string  | default        | The name of the bucket to connect to on the cluster. This is case-sensitive                                                                                                                                                                         |
| password          | string  |                | The optional password of the bucket.                                                                                                                                                                                                                |
| caseSensitiveKeys | boolean | false          | Keys in Couchbase are case sensitive by, the SDK by default converts all keys to lowercase, setting this to *true* will prevent this behavior                                                                                                       |
| dataMarshaller    | any     |                | The data marshaller to use for serializations and deserializations, please put the class path or the instance of the marshaller to use. Remember that it must implement our interface: `cfcouchbase.data.IDataMarshaller`                           |


# Structure

The simplest way to get started using the SDK is to simply pass a struct of config settings into the constructor when you create the client.

```javascript
couchbase = new cfcouchbase.CouchbaseClient(
    {
        servers = [
            "http://cache1:8091", 
            "http://cache2:8091"
        ],
        bucketName  = "myBucket",
        viewTimeout = 1000
    } 
);
```


# Summary

The default configuration for CFCouchbase is located in `/cfcouchbase/config/CouchbaseConfig.cfc`. You can create the `CouchbaseClient` with no configuration and it will connect to the **default** bucket on [127.0.0.1:8091](http://127.0.0.1:8091). However, there are more ways to configure the Couchbase client via the `config` argument of the constructor so it can connect to your server and options of choice:

1. Pass a config structure
2. Pass a config CFC

> **Hint** The config CFC is the most contained and portable way to store your configuration.


# Usage

Whether you are using Couchbase for simple caching or as the NoSQL database for an application, your most common operations are going to be getting and setting data.

Data is most commonly a JSON document, but can really be any string you want including binary representations of serialized objects.

For the comprehensive list of SDK methods, parameters, descriptions, and code samples, please look in the [API Docs](http://apidocs.ortussolutions.com/cfcouchbase/2.0.0) (in the download). Click on the `cfcouchbase` package and then the `CouchbaseClient` class.


# Storing Documents

The easiest way to store a document in your Couchbase cluster is by calling the `upsert()` method. In this example we are passing a struct directly in as the value to be stored. The SDK will automatically serialize the struct into a JSON document for storage in the cluster.

```javascript
client.upsert(
    id = "brad",
    value = { 
        name: "Brad", 
        age: 33, 
        hair: "red", 
        weird: true 
    } 
);
```

The `id` of the document is `brad` and it will live in the cluster forever until it is deleted. If I want my document to expire and be automatically removed from the cluster after a certain amount of time, I can specify the `timeout` argument.

This document will be cached for 20 minutes before expiring. Couchbase will automatically remove it for you once it has expired.

```javascript
client.upsert(
    id = "cached-site-menus",
    value = menuHTML,
    timeout = 20
);
```

> **Tip** The CFCouchbase SDK will try to be smart enough to translate any native CFML construct into JSON for you. You can also pass binary data or JSON as well. The SDK can also deal with CFC's to provide seamless CFC deserialization and inflation, please see the Data Serialization section.


# Storage Durability

Couchbase auto-shards `master` and `replica` documents across your cluster out-of-the-box. Documents are stored both in RAM for fast access and persisted to disk for long term storage. By default, all storage operations are `synchronous`, and will return once the document has been written to memory. Which means the `upsert()` call returns potentially before the document is fully stored and replicated. This is a break from the consistency offered by a typical RDBMS, but it is key to the high-performance and scalable architecture. See the [CAP Theorem](http://en.wikipedia.org/wiki/CAP_theorem).

* If your application requires you to confirm that a document has been persisted to disk, use the `persistTo` argument. &#x20;
* If you need to confirm that the document has been copied to a given number replica nodes, use the `replicateTo` argument.

```javascript
// This document will be persisted to disk on at least two nodes
client.upsert(
    ID = 'brad',
    value = { name: 'Brad', age: 33, hair: 'red' },
    persistTo = "TWO", 
    replicateTo = "TWO"
);
```

> **Hint** All documents will eventually replicate and persist by themselves. You only need these options if the application cannot continue without it.

There are many other methods for storing data. Please check the [API docs](http://apidocs.ortussolutions.com/cfcouchbase/2.0.0) to see full descriptions and code samples for all of them. Here are a few to wet your appetite:

* `upsertMulti()` -  Set multiple documents in the cache with a single operation.
* `replace()` - Replace an existing document.
* `insert()` - Insert a new document
* `replaceWithCAS()` - Update a document only if no one else has changed it since you last retreived it using Compare And Swap (CAS).
* `touch()` - Touch a document to reset its expiration time.
* `unlock()` - Unlock a previously locked document without modifying the document.
* `counter()` -  Increment or Decrement a numeric value
* `prepend()` / `append()` - add content to the beginning or end of an existing document


# Retrieving Documents

The easiest way to retrieve a specific document by ID from your Couchbase cluster is by calling the `get()` method.

```javascript
person = client.get( id = "brad" );
```

There are many other methods for getting data. Please check the [API Docs](http://apidocs.ortussolutions.com/cfcouchbase/2.0.0) (in the download) to see full descriptions and code samples for all of them.

* `getMulti()` - Get multiple objects from couchbase with a single call.
* `getAndTouch()` - Get a document and update its expiry value
* `getAndLock()` - Get a document and lock it for a specified amount of time
* `getFromReplica()` - Get a document from a replica
* `getWithCAS()` - Get an object from couchbase with a special Compare And Swap (CAS) version (for use wit `replaceWithCAS()`)
* `n1qlQuery()` - Get a document using a N1QL query


# Data Serialization

Couchbase can literally store anything in a bucket as long as it's represented as a string and no larger than 20MB.\
The CFCouchbase SDK will automatically serialize complex data for you when storing it and deserialize it when you ask for it again.

## Simple Values

Before we tell how CFCouchbase serializes your data, we'll tell you how to *avoid* this behavior if you don't want it.\
Simple values (strings) won't be touched, so if you want to control how an array is serialized, just turn it to a **string** first and then pass it into `set()` operations. These strings can be JSON or anything of your choosing. When you retrieve these documents back, CFCouchbase will try to deserialize them for you automatically according to our rules you will see soon. However, if you want the raw data back from Couchbase as a string (regardless of how it was stored), pass `deserialize=false` into your `get()` or `query()` methods and CFCouchbase will not automatically deserialize it but just pass it back to you.

```javascript
// Set my own JSON string
client.upsert( 
    id="IDidItMyWay", 
    value='{ "title": "My Way", "artist": "Frank Sinatra", "year": "1969"}'
);

// And get it back out as a string
song = client.get( id="IDidItMyWay", deserilize=false );
```

## Complex Data

Complex data (structs, queries, arrays) will be automatically serialized for you with no extra work on your part. Just pass them into `set()` and you'll get the same data structure back from `get()` operation.

* **Structs** and **Arrays** will be converted via `serializeJSON()` and stored as JSON so you can query them with views.
* **Queries** - Will be converted to binary with `objectSave()` and wrapped in a struct of metadata containing the *recordcount* and *columnlist*. They are converted to binary so they can be re-inflated back to CFML queries.

```javascript
client.upsert( 
    id='weekDays', 
    value=['Sunday','Monday','Tuesday','Wednesay','Thursday','Friday','Saturday']
);
days = client.get( 'weekDays' );

writeOutput( arrayLen( days ) );
```

## Query Representation

```javascript
{
  "recordcount": 3,
  "type": "cfcouchbase-query",
  "binary": "....",
  "columnlist": "ID,NAME"
}
```


# Components

There are a lot of different ways to handle **CFCs** and we allow for several different methods of handling them that come with varying degrees of control and convenience.

* [Auto Inflation](/usage/components/auto-inflation)
* [Manual Inflation](/usage/components/manual-inflation)
* [Custom Serialization](/usage/components/custom-serialization)
* [Binary](/usage/components/binary)


# Auto Inflation

You can annotate a CFC with `autoInflate` and CFCouchbase will be smart enough to detect the CFC's path and defined properties so it can store them in Couchbase. When storing the component, the data will be stored as a JSON struct along with some metadata about the component. When retrieving that document from Couchbase, a **new** component will be created with the inflated data. This is the easiest approach as it is completely seamless and pretty fast I might say!

## Song.cfc

```javascript
component accessors="true" autoInflate="true"{
    property name="title"  default="";
    property name="artist" default="";
}
```

## Usage

```javascript
funkyChicken = new path.to.song();
funkyChicken.setTitle( "Chicken Dance" );
funkyChicken.setArtist( "Werner Thomas" );

// Pass the CFC in
couchbase.upsert( 'funkyChicken', funkyChicken );

// And get a CFC out!
birdieSong = couchbase.get( 'funkyChicken' );

writeOutput( birdieSong.gettitle() );
writeOutput( birdieSong.getArtist() );
```

## CFC data in couchbase

```javascript
{
  "data": {
    "title": "Chicken Dance",
    "artist": "Majano",
  },
  "classpath": "model.funky.Song",
  "type": "cfcouchbase-cfcdata"
}
```

As you can see, this approach will allow you to still create views about your data in Couchbase if necessary and also provide a nice way to do CFC to Couchbase to CFC translations.


# Manual Inflation

If you pass a CFC with properties but it does not have the `autoInflate` attribute like above, the data will still be stored as a JSON struct, but without the extra metadata about the CFC. When retrieving this document, you will just get a struct back by default. You can build a CFC yourself, or specify an **inflateTo** argument to instruct CFCouchbase on how to reinflate your data back to an object. You can pass in a component path (or component instance) and the SDK will instantiate that component and call its property setters to repopulate it with the data from Couchbase.

```javascript
// path
person = client.get(
    id = "funkyChicken",
    inflateTo = "path.to.song"
);

// instance
person = client.get(
    id = "funkyChicken",
    inflateTo = new path.to.Song()
);
```

If you need even more control such as performing dependency injection, passing constructor arguments to the CFC, or dynamically choosing the component to create, you can supply a closure that acts as a provider and produces an empty object ready to be populated.

```javascript
person = client.get(
    id = "funkyChicken",
    inflateTo = function( document ){
        // Let WireBox create and autowire an instance for us
        return wirebox.getInstance( 'path.to.song' );
    }
);
```

If you are getting multiple documents back from Couchbase, your **inflateTo** closure will be called once per document.

> **Tip** You can even use `inflate` to when retrieving result sets, or querying Couchbase views and you'll get an array of populated CFCs!


# Custom Serialization

If you really want to get extra funky and control how your components are serialized, you can fall back on our conventions. If the CFC has a public method called `$serialize()`, it will be called and its output (must be a *string*) will be saved in Couchbase. The CFC can also have a public method called `$deserialize( id, data )`, that if declared will be called and given the data so it can populate itself.

## CustomUser.cfc

```javascript
// CustomUser is an object that implements its own serialization scheme
// using pipe-delimited lists to store the data instead of JSON.  It has both
// a $serialize() and $deserialize() method to facilitate that.
component accessors="true"{

    property name="firstName";
    property name="lastName";
    property name="age";

    function $serialize(){
        // Serialize as pipe-delimited list
        return '#getFirstName()#|#getLastName()#|#getAge()#';
    }

    function $deserialize( ID, data ){
        // Deserialize the pipe-delimited list
        setFirstName( listGetAt( data, 1, '|' ) );
        setLastName( listGetAt( data, 2, '|' ) );
        setAge( listGetAt( data, 3, '|' ) );        
    }
}
```

## Usage

```javascript
user = new CustomUser();
user.setFirstName( "Brad" );
user.setLastName( "Wood" );
user.setAge( 45 );

couchbase.upsert( 'half-pipe', user );

reinflatedUser = couchbase.get( id="half-pipe", inflateTo='CustomUser' );

writeOutput( reinflatedUser.getFirstName() );
writeOutput( reinflatedUser.getLastName() );
writeOutput( reinflatedUser.getAge() );
```


# Binary

If you pass a CFC instance in that has no properties and no `$serialize()` method, CFCouchbase will use ColdFusion's `objectSave()` to turn the component into binary and it will be saved as a base64-encoded string.


# Custom Transformers

If you don't like how we set up data serialization or just have super-custom requirements, you can provide your own data marshaller to have full control. Create a CFC that implements the `cfcouchbase.data.IDataMarshaller` interface. It only needs to have three methods:

* `serializeData()` - Returns the data in a string form so it can be persisted in Couchbase
* `deserializeData()` - Received the raw string data from Couchbase and inflates it as necessary to the original state
* `setCouchbaseClient()` - Gives the marshaller a chance to store a local reference to the client in case it needs to talk back.

```
interface{
    any function setCouchbaseClient( required couchcbaseClient );
    any function deserializeData( required string ID, required string data, any inflateTo="", struct deserializeOptions={} );
    string function serializeData( required any data );
}
```

## myDataMarshaller.cfc

```javascript
component implements='cfcouchbase.data.IDataMarshaller' {

    any function setCouchbaseClient( required couchcbaseClient ){
        variables.couchbaseClient = arguments.couchcbaseClient;
        return this;
    }

    string function serializeData( required any data ){
        if( !isSimpleValue( data ) ) {
            return serializeJSON( data );
        }
        return data;
    }

    any function deserializeData( required string data, any inflateTo="", struct deserializeOptions={} ){
        if( isJSON( data ) && deserialize ) {
            return deserializeJSON( data );
        }
        return data;
    }

}
```

After you have created your custom marshaller, simply pass in an instance of it or the full component path as a config setting:

```javascript
// path
couchbase = new cfcouchbase.CouchbaseClient(
    {
        bucketName = 'myBucket',
        dataMarshaller = 'path.to.myDataMarshaller'
    } 
);
// instance
couchbase = new cfcouchbase.CouchbaseClient(
    {
        bucketName = 'myBucket',
        dataMarshaller = new path.to.myDataMarshaller()
    } 
);
```

> **Tip** Once you specify a custom data marshaller, you are overriding all **Data Serialization** functionality above. So you are on your own now buddy! Like good 'ol spidey says: With Much Power Comes Much Responsibility!


# Executing Queries

One of the most powerful parts of Couchbase Server is the ability to find data through map / reduce [views and indexes](http://docs.couchbase.com/admin/admin/Views/views-intro.html) or by executing [N1QL (SQL like)](http://developer.couchbase.com/documentation/server/4.0/n1ql/index.html) queries which were introduced in Couchbase Server 4.0. We do not cover all the intricacies of views or N1QL, for that please visit the official [Couchbase Docs](http://developer.couchbase.com/documentation/server/4.0/introduction/intro.html). We focus on how to leverage them from CFCouchbase.

There are 2 types of queries available in the SDK:

* [View Queries](/usage/executing-queries/view-queries)
* [N1QL Queries](/usage/executing-queries/n1ql-queries)

Both types of queries can be executed through the parent facade of `query()` or through their standalone methods of `viewQuery()` and `n1qlQuery()`.


# View Queries

The minimum information you need to execute a view query is the name of the **design document** and the **view** you wish you use.

```javascript
results = client.query( designDocumentName='beer', viewName='brewery_beers' );

for( var result in results ) {
    writeOutput( result.document.name );
    writeOutput( '<br>' );
}
```

Here are the arguments you can pass into the `query()` or `viewQuery()` methods. For the latest and more in-depth information please visit our [API Docs](http://apidocs.ortussolutions.com/cfcouchbase/2.0.0).

| Argument           | Type       | Default | Description                                                                                                                                                                                                                                     |
| ------------------ | ---------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| designDocumentName | `string`   |         | The name of the design document in your Couchbase server                                                                                                                                                                                        |
| viewName           | `string`   |         | The name of the view to query from                                                                                                                                                                                                              |
| options            | `any`      | {}      | The query options to use for this query. This can be a structure of name-value pairs or an actual Couchbase query options object usually using the `newViewQuery()` method.                                                                     |
| deserialize        | `boolean`  | true    | If true, it will deserialize the documents if they are valid JSON, else they are ignored.                                                                                                                                                       |
| deserializeOptions | `struct`   |         | A struct of options to help control how the data is deserialized when populating an object. See ObjectPopulator.cfc for more info.                                                                                                              |
| inflateTo          | `any`      |         | A path to a CFC or closure that produces an object to try to inflate the document results on NON-Reduced views only!                                                                                                                            |
| filter             | `function` |         | A closure or UDF that must return boolean to use to filter out results from the returning array of records, the closure receives a struct that has id, document, key, and value: function( row ). A true will add the row to the final results. |
| transform          | `function` |         | A closure or UDF to use to transform records from the returning array of records, the closure receives a struct that has id, document, key, and value: function( row ). Since the struct is by reference, you do not need to return anything.   |
| returnType         | `any`      | array   | The type of return for us to return to you. Available options: array, native, iterator                                                                                                                                                          |

## Results

CFCouchbase will natively transform the data into an array of structs with a specific format. These keys are included in the struct that represents a row. This is the same struct that is returned in the result array and passed into the transform and filter closures.

* `id` - The unique document id. Only avaialble on non-reduced queries
* `document` - The JSON document reinflated back to its original form. Only available on non-reduced views
* `key` - For non-reduced queries, the key emitted from the map function. For reduced views, null.
* `value` - For non-reduced queries, the value emitted from the map function. For reduced views, the output of the reduce function.

## Example

```javascript
// Return 10 records, skipping the first 20.  Force fresh data
results = client.query( 
    designDocumentName='beer', 
    viewName='brewery_beers', 
    options={ limit = 10, offset = 20, stale = 'FALSE' } 
);

// Only return 20 records and skip the reduce function in the view
results = client.query( 
    designDocumentName='beer', 
    viewName='by_location', 
    options={ limit = 20, reduce = false } 
);

// Group results (Will return a single record with the count as the value)
results = client.query( 
    designDocumentName='beer', 
    viewName='brewery_beers', 
    options={ group = true } 
);

// Start at the specified key and sort descending 
results = client.query( 
    designDocumentName='beer', 
    viewName='brewery_beers', 
    options={ sortOrder = 'DESC', startKey = ["aldaris","aldaris-zelta"] } 
);
```


# n1ql Queries

N1QL (pronounced "nickel") queries are a SQL like syntax to query JSON documents in Couchbase Server.

Here are the arguments you can pass into the `query()` or `n1qlQuery()` methods. For the latest and more in-depth information please visit our [API Docs](http://apidocs.ortussolutions.com/cfcouchbase/2.0.0).

| Argument           | Type       | Default | Description                                                                                                                                                                                                                                                                                                           |
| ------------------ | ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| statement          | `string`   |         | The N1QL statement to be executed                                                                                                                                                                                                                                                                                     |
| parameters         | `any`      |         | Used with N1QL queries, can be a structure or array of parameters for the query                                                                                                                                                                                                                                       |
| options            | `any`      | {}      | The query options to use for this query. This can be a structure of name-value pairs or an actual Couchbase query options object usually using the `newViewQuery()` method.                                                                                                                                           |
| deserialize        | `boolean`  | true    | If true, it will deserialize the documents if they are valid JSON, else they are ignored.                                                                                                                                                                                                                             |
| deserializeOptions | `struct`   |         | A struct of options to help control how the data is deserialized when populating an object. See ObjectPopulator.cfc for more info.                                                                                                                                                                                    |
| inflateTo          | `any`      |         | A path to a CFC or closure that produces an object to try to inflate the document results on NON-Reduced views only!                                                                                                                                                                                                  |
| filter             | `function` |         | A closure or UDF that must return boolean to use to filter out results from the returning array of records, the closure receives a struct that has id, document, key, and value: function( row ). A true will add the row to the final results.                                                                       |
| transform          | `function` |         | A closure or UDF to use to transform records from the returning array of records, the closure receives a struct that has id, document, key, and value: function( row ). Since the struct is by reference, you do not need to return anything.                                                                         |
| returnType         | `any`      | struct  | <p>If returnType is "struct", will return struct containing the results, requestID, signature, and metrics. <br>If returnType is native, a Java ViewResponse object will be returned ( com.couchbase.client.protocol.views.ViewResponse )  <br>If returnType is iterator, a Java iterator object will be returned</p> |
| type               | `string`   | view    | The type of query being performed, values are: view or n1ql. \*Note this only required when calling query() to perform a n1ql query                                                                                                                                                                                   |

## Retrieve Document(s)

```
couchbase.n1qlQuery("
SELECT * 
FROM users
USE KEYS "user_101"
");
```

```
couchbase.n1qlQuery("
SELECT * 
FROM users
USE KEYS ["user_101","user_454"]
");
```

## DML Operations

### Insert

```
couchbase.n1qlQuery("
INSERT INTO users (KEY, VALUE)
VALUES ("user_2343", {
  "user_id": 2343,
  "name": "John Smith",
  "email": "john.smith@gmail.com"
})
");
```

### Update

```
couchbase.n1qlQuery("
UPDATE users
USE KEYS "user_2343"
SET email = "john.doe@gmail.com"
RETURNING email
");
```

### Upsert

```
couchbase.n1qlQuery("
UPSERT INTO users (KEY, VALUE)
VALUES ("user_2343", {
  "user_id": 2343,
  "name": "John Smith",
  "email": "john.smith@gmail.com"
})
RETURNING META().id AS document_id
");
```

### Delete

```
couchbase.n1qlQuery("
DELETE 
FROM users
USE KEYS "user_2343"
");
```

N1QL queries that do not use a `USE KEYS` statement require the use of [GSI Indexes](http://developer.couchbase.com/documentation/server/current/architecture/global-secondary-indexes.html)


# Query Options

Here are some of the most common keys you can pass in the struct of options to control how the query is executed. Please check the [API Docs](http://apidocs.ortussolutions.com/cfcouchbase/2.0.0) for the full list.

| Option        | Description                                                                                                                                                                                                                    |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `sortOrder`   | Specifies the direction to sort the results based on the map function's "key" value. Valid values are ASC and DESC.                                                                                                            |
| `limit`       | Number of records to return                                                                                                                                                                                                    |
| `offset`      | Number of records to skip when returning                                                                                                                                                                                       |
| `reduce`      | Flag to control whether the reduce portion of the view is run. If false, only the results of the map function are returned.                                                                                                    |
| `includeDocs` | Specifies whether or not to include the entire document in the results or just the key names. Default is false.                                                                                                                |
| `startkey`    | Specify the start of a range of keys to return.                                                                                                                                                                                |
| `endkey`      | Specify the end of a range of keys to return.                                                                                                                                                                                  |
| `group`       | Flag to control whether the results of the reduce function are grouped.                                                                                                                                                        |
| `keys`        | An array of keys to return. For complex keys, pass each key as an array.                                                                                                                                                       |
| `stale`       | Specifies if stale data can be returned with the view. Possible values are: `OK` - (default)stale data is ok, `FALSE` - force index of view, and `UPDATE_AFTER` potentially returns stale data, but starts an asynch re-index. |


# Filter Closures

You can specify a closure as the `filter` argument that returns true for records that should be included in the final output. This is a great way to filter out any unecessary documents you do not want in the end result array.

```javascript
// Only return breweries
results = client.query(
    designDocumentName = 'beer', 
    viewName = 'brewery_beers', 
    filter = function( row ){
        if( row.document.type == 'brewery' ) {
            return true;
        }
        return false;
    }
);
```


# Transform Closures

The `transform` closure will be called in each iteration as we build the native CF array of results. This can be used to normalize data, add or remove data, you name it.

```javascript
results = couchbase.query(
    designDocumentName = 'beer', 
    viewName = 'brewery_beers', 
    deserialize = false,
    transform = function( row ){
        row.document = deserializeJSON( row.document );
    }
);
```


# Return Types

You can ask the `query()` method to return an array `default`, a Java `ViewReponse` object, or a Java iterator. By default we use the native CFML array type which uses transformations, automatic deserializations and inflations.

```javascript
// Get an iterator of Java objects
iterator = couchbase.query(
    designDocumentName = 'beer', 
    viewName = 'brewery_beers', 
    returnType = 'Iterator' 
);

while( iterator.hasNex() ) {
    writeOutput( iterator.getNext().getKey() );
}
```


# Managing Views

Views defined via JavaScript a `map` function that populates keys from the data in your bucket. Views can also define an additional `reduce` function that is used to aggregate data down, much like in SQL. Finally, one or more views live inside of a design document, which you can query and construct.

> **Hint** Please read more about views in the Couchbase Docs at <http://docs.couchbase.com/couchbase-manual-2.2/#views-and-indexes>

You can manage views and design documents from the Couchbase web console and you can also manage them programatically via CFCouchbase as well. Here's a list of some useful methods for view operations:

* `designDocumentExists()` - Check for the existance of a design document.
* `getDesignDocument()` - Retreive a design document and all its views
* `deleteDesignDocument()` - Delete a design document and all its views from the cluster
* `viewExists()` - Check for the existance of a single view
* `saveView()` - Save/update a view and wait for it to index
* `asyncSaveView()` - Save/update a view but don't wait for it to become usable
* `deleteView()` - Delete a single view from its design document

The really nice thing about `saveView()` and `asyncSaveView()` is they either insert or udpate an existing view based on whether it already exists. They also only save to the cluster if the view doesn't exist or is different. This means you can repeatedly call saveView() and nothing will happen on any call but the first. This allows you to specify the views that you need in your application when it starts up and they will only save if neccessary:

```javascript
// application start
boolean function onApplicationStart(){
    application.couchbase = new cfcouchbase.CouchbaseClient( { bucketName="beer-sample" } );

    // Specify the views the applications needs here.  They will be created/updated
    // when the client is initialized if they don't already exist or are out of date.

    application.couchbase.saveView(
        'manager',
        'listBreweries',
        'function (doc, meta) {
          if ( doc.type == ''brewery'' ) {
            emit(doc.name, null);
          }
        }',
        '_count'
    );

    application.couchbase.saveView(
        'manager',
        'listBeersByBrewery',
        'function (doc, meta) {
          if ( doc.type == ''beer'' ) {
            emit(doc.brewery_id, null);
          }
        }',
        '_count'
    );

    return true;
}
```


# Working With Futures

You have probably noticed that all the asyncronous operations in the SDK return a Java [OperationFuture](http://www.couchbase.com/autodocs/spymemcached-2.8.1/net/spy/memcached/internal/OperationFuture.html) object. This allows control of your application to return immediately to your code without waiting for the remote calls to complete. The future object gives you a window into whats going on and you can elect to monitor the progress on your terms-- deciding how long you're willing to wait-- or ignore it entirely in order to complete the request as quickly as possible.

The most common method is `get()`. Calling this will instruct your code to wait until th eoperation is complete before continuing. Calling `future.get()` essentially makes an *ansynchronou call syncronous*.

```javascript
future = client.asyncGet( ID = 'brad' );
person = future.get();
```

`OperationFutures` are parameterized which means they can each return a different data type from their `get()`. Check the [API Docs](http://apidocs.ortussolutions.com/cfcouchbase/current/) to see what each asynchronous future returns.

> **Info** Operations are always subject to the timeouts configured for the client regardless of how you interact with the future.

Here are some other methods you can call on a future to handle the response on your terms:

* `cancel()` - Cancel this operation, if possible.
* `getStatus()` - Get the current status of this operation.
* `isDone()` - Whether or not the Operation is done and result can be retrieved with get().
* `get(duration, units)` - Get the results of the given operation, but specify how long you're willing to wait.
* More information on Futures is available here in the Java Docs: [OperationFuture](http://www.couchbase.com/autodocs/spymemcached-2.8.1/net/spy/memcached/internal/OperationFuture.html)


# Help & Support

## Help & Support

If you need any community help related to our CFCouchbase SDK, you can use our online help group at <https://community.ortussolutions.com/c/communities/cfcouchbase/12>

## Professional Open Source

![Ortus Solutions, Corp](https://3913943779-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvAnI0cY_mWVYJE%2F-LA-UdCGWmrQ8Xvggj60%2F-LA-UqkepONrxKPpy21d%2Fortussolutions_button.png?generation=1523648000961561\&alt=media)

CFCouchbase is a professional open source software backed by [Ortus Solutions, Corp](https://www.ortussolutions.com/products/cfcouchbase) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](https://www.ortussolutions.com/services)

### Resources

* Source Code - <https://github.com/Ortus-Solutions/cfcouchbase-sdk>
* Tracker Site (Bug Tracking, Issues) - <https://ortussolutions.atlassian.net/browse/COUCHBASESDK>
* Documentation - <https://cfcouchbase.ortusbooks.com/>
* Blog - <https://www.ortussolutions.com/blog>
* Official Site - <https://www.ortussolutions.com/products/cfcouchbase>


