Only this pageAll pages
Powered by GitBook
1 of 34

CFCouchbase SDK

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

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.

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

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

  • [] -Add RBAC Support

  • [] -Upgraded JARs to latest (v2.5.4)

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 and 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.

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

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 . 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

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.

COUCHBASESDK-49
COUCHBASESDK-50

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

127.0.0.1:8091

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.

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 (in the download). Click on the cfcouchbase package and then the CouchbaseClient class.

Executing Queries

One of the most powerful parts of Couchbase Server is the ability to find data through map / reduce views and indexes or by executing N1QL (SQL like) 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. We focus on how to leverage them from CFCouchbase.

There are 2 types of queries available in the SDK:

  • View 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().

component {

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

}
// 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' );
WireBox
CacheBox
// Only return breweries
results = client.query(
    designDocumentName = 'beer', 
    viewName = 'brewery_beers', 
    filter = function( row ){
        if( row.document.type == 'brewery' ) {
            return true;
        }
        return false;
    }
);

Retrieving Documents

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

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

There are many other methods for getting data. Please check the API Docs (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

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.

// 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.

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!

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.

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

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

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.

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

Introduction

Welcome to CFCouchbase SDK v2.2.0

The CFCouchbase SDK is a CFML library for interacting with Couchbase NoSQL Server. 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)

Couchbase is copyright and a registered trademark by Couchbase, Inc.

Versioning

CFCouchbase is maintained under the guidelines as much as possible. Releases will be numbered with the following format:

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 License.

Discussion & Help

The CFCouchbase help and discussion group can be found here:

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:

  • By Jira:

Professional Open Source

CFCouchbase is a professional open source software backed by offering services like:

  • Custom Development

  • Professional Support & Mentoring

  • Training

  • Server Tuning

Resources

  • Source Code -

  • Tracker Site (Bug Tracking, Issues) -

  • Documentation -

  • Blog -

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

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 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 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 - . 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 () 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.

Overview

The CFCouchbase SDK is a CFML library for interacting with Couchbase NoSQL Server. 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

  • Auto-sharding of documents evenly across cluster

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.

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 .

  • If your application requires you to confirm that a document has been persisted to disk, use the persistTo argument.

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.

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

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

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()

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.

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.

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.

Authors

Luis Fernando Majano Lainez

Luis Majano is a Computer Engineer with over 16 years of software development and systems architecture experience. He was born in 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 . Luis resides in The Woodlands, Texas with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!

He is the CEO of , 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

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.

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

24/7 uptime via on-the-fly node removal and rebalance operations

  • 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

  • Ability to create as many Couchbase clients as necessary

  • Binary

    Auto Inflation
    Manual Inflation
    Custom Serialization
    client.upsert(
        id = "brad",
        value = { 
            name: "Brad", 
            age: 33, 
            hair: "red", 
            weird: true 
        } 
    );
    client.upsert(
        id = "cached-site-menus",
        value = menuHTML,
        timeout = 20
    );
    /samples - A collection of sample apps that use the "beer-sample" bucket.
    • /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.

    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 to install in any directory:

    This approach can be used for the following application approaches:

    • ColdBox Module

    • Traditional ColdFusion Apps

    If you need to confirm that the document has been copied to a given number replica nodes, use the replicateTo argument.

    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 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

    CAP Theorem
  • 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 theCouchbaseConfigobject and ColdBox will configure theCouchbaseClient` for you.

    couchbase = {
        servers     = "http://127.0.0.1:8091",
        bucketname     = "default",
        viewTimeout    = "1000"
    };
    Usage
    // 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, '|' ) );        
        }
    }
    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() );
    - 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:

    http://docs.couchbase.com/couchbase-manual-2.2/#views-and-indexes
    box install cfcouchbase
    // 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"
    );
    // 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;
    }

    Security Hardening

  • Code Reviews

  • Much More

  • Official Site - https://www.ortussolutions.com/products/cfcouchbase

  • Semantic Versioning
    Apache 2
    https://groups.google.com/a/ortussolutions.com/forum/#!forum/cfcouchbase
    https://github.com/Ortus-Solutions/cfcouchbase-sdk
    https://ortussolutions.atlassian.net/browse/COUCHBASESDK
    Ortus Solutions, Corp
    https://github.com/Ortus-Solutions/cfcouchbase-sdk
    https://ortussolutions.atlassian.net/browse/COUCHBASESDK
    https://cfcouchbase.ortusbooks.com/
    http://www.ortussolutions.com/blog
    Ortus Solutions, Corp
    . You can read his blog at

    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.” 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 (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

    San Salvador, El Salvador
    Florida International University
    Ortus Solutions
    Inland Empire
    www.luismajano.com
    GitHub repository
    http://www.harvesting.org/
    http://www.harvesting.org/
    Shalom Children's Home

    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. Here are some of the most common setting you will need to use:

    Common Config Settings

    Setting

    Type

    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.

    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.

    Query Representation

    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

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

    Usage

    CFC data in couchbase

    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.

    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

    • Source: https://github.com/Ortus-Solutions/cfcouchbase-sdk Github

    • Bleeding Edge + More:

    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.

    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.

    WireBox

    However, we would recommend you use a dependency injection framework like to create and manage your Couchbase Client:

    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.

    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.

    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.

    myDataMarshaller.cfc

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

    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!

    Working With Futures

    You have probably noticed that all the asyncronous operations in the SDK return a Java OperationFuture 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.

    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 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().

    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 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

    Help & Support

    Help & Support

    If you need any community help related to our CFCouchbase SDK, you can use our online help group at

    Professional Open Source

    <major>.<minor>.<patch>

    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

  • 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

    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.

    // 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 );
    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() );
    {
      "data": {
        "title": "Chicken Dance",
        "artist": "Majano",
      },
      "classpath": "model.funky.Song",
      "type": "cfcouchbase-cfcdata"
    }
    http://integration.stg.ortussolutions.com/artifacts/ortussolutions/cfcouchbase/
    WireBox
    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 );
    }
    // path
    couchbase = new cfcouchbase.CouchbaseClient(
        {
            bucketName = 'myBucket',
            dataMarshaller = 'path.to.myDataMarshaller'
        } 
    );
    // instance
    couchbase = new cfcouchbase.CouchbaseClient(
        {
            bucketName = 'myBucket',
            dataMarshaller = new path.to.myDataMarshaller()
        } 
    );
    client.upsert( 
        id='weekDays', 
        value=['Sunday','Monday','Tuesday','Wednesay','Thursday','Friday','Saturday']
    );
    days = client.get( 'weekDays' );
    
    writeOutput( arrayLen( days ) );
    {
      "recordcount": 3,
      "type": "cfcouchbase-query",
      "binary": "....",
      "columnlist": "ID,NAME"
    }
    this.mappings[ '/cfcouchbase' ] = 'C:\path\to\cfcouchbase';
    public boolean function onApplicationStart(){
        application.couchbase = new cfcouchbase.CouchbaseClient();
        return true;
    }
    // Map our Couchbase Client via WireBox Binder
    map( "CouchbaseClient" )
        .to( "cfcouchbase.CouchbaseClient" )
        .initArg( name="config", value={} )
        .asSingleton();
    public boolean function onApplicationEnd(){        
        application.couchbase.shutdown( 10 );
        return true;
    }
    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;
        }
    
    }
    Ortus Solutions, Corp

    CFCouchbase is a professional open source software backed by Ortus Solutions, Corp offering services like:

    • Custom Development

    • Professional Support & Mentoring

    • Training

    • Server Tuning

    • Security Hardening

    • Code Reviews

    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://community.ortussolutions.com/c/communities/cfcouchbase/12

    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 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()

    • delete() => remove()

    • 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 (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.

    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.

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

    N1QL supports the standard DML operations that you would expect.

    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.

    There are several options 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.

    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.

    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 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 page for all the necessary resources.

    • ITB Presentation - CFCouchbase 2.0 + N1QL

    • Couchbase Developer Portal

    • N1QL Query Tutorial

    • ColdBox Travel Sample

    Much More
    https://www.ortussolutions.com/products/cfcouchbase

    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.

    Here are the arguments you can pass into the query() or viewQuery() methods. For the latest and more in-depth information please visit our .

    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 .

    // query
    couchbase.n1qlQuery('
      SELECT u.* 
      FROM users AS u
      USE KEYS "user_101"
    ');
    [
      {
        "email": "[email protected]",
        "first_name": "Albin",
        "last_name": "Price",
        "user_id": 101,
        "username": "Eudora43"
      }
    ]
    couchbase.n1qlQuery('
      SELECT u.* 
      FROM users AS u
      USE KEYS [ "user_101", "user_454" ]
    ');
    // insert a new document
    couchbase.n1qlQuery('
      INSERT INTO users (KEY, VALUE)
      VALUES ("user_2343", {
        "user_id": 2343,
        "name": "John Smith",
        "email": "[email protected]"
      })
    ');
    
    // update a specific property of a document
    couchbase.n1qlQuery('
      UPDATE users
      USE KEYS "user_2343"
      SET email = "[email protected]"
    ');
    
    // 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": "[email protected]"
      })
    ');
    // 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'
    ');
    // 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'
    ');
    // 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
    );
    N1QL Flight Data Examples

    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

    Argument

    Type

    Default

    Description

    designDocumentName

    API Docs

    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

    If returnType is "struct", will return struct containing the results, requestID, signature, and metrics. If returnType is native, a Java ViewResponse object will be returned ( com.couchbase.client.protocol.views.ViewResponse ) If returnType is iterator, a Java iterator object will be returned

    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)

    DML Operations

    Insert

    Update

    Upsert

    Delete

    N1QL queries that do not use a USE KEYS statement require the use of GSI Indexes

    Argument

    Type

    Default

    Description

    statement

    string

    API Docs

    results = client.query( designDocumentName='beer', viewName='brewery_beers' );
    
    for( var result in results ) {
        writeOutput( result.document.name );
        writeOutput( '<br>' );
    }
    // 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"] } 
    );
    couchbase.n1qlQuery("
    SELECT * 
    FROM users
    USE KEYS "user_101"
    ");
    couchbase.n1qlQuery("
    SELECT * 
    FROM users
    USE KEYS ["user_101","user_454"]
    ");
    couchbase.n1qlQuery("
    INSERT INTO users (KEY, VALUE)
    VALUES ("user_2343", {
      "user_id": 2343,
      "name": "John Smith",
      "email": "[email protected]"
    })
    ");
    couchbase.n1qlQuery("
    UPDATE users
    USE KEYS "user_2343"
    SET email = "[email protected]"
    RETURNING email
    ");
    couchbase.n1qlQuery("
    UPSERT INTO users (KEY, VALUE)
    VALUES ("user_2343", {
      "user_id": 2343,
      "name": "John Smith",
      "email": "[email protected]"
    })
    RETURNING META().id AS document_id
    ");
    couchbase.n1qlQuery("
    DELETE 
    FROM users
    USE KEYS "user_2343"
    ");