Install and Start Using the Node.js SDK with Couchbase Server
The Couchbase Node.js SDK enables you to interact with a Couchbase Server cluster from the Node.js language.
The Couchbase Node.js SDK 3.x is a complete rewrite of the API, reducing the number of overloads to present a simplified surface area, and adding support for Couchbase Server features like Collections and Scopes (available from Couchbase Server 7.0).
The 3.x SDK also brings in promises, to reduce the complexity of asynchronous javascript in client applications, as well as extending the management APIs and bringing better debugging and logging options
Creating a New Node.js Project
Creating a Node.js project is as easy as making a directory and initializing it with npm. The next two commands will do that for us. Open up a terminal and run the following command:
$ mkdir node-couchbase-project && cd $_
The command above will make our directory and change our current working directory.
$ npm init -y
If a directory does not already have a package.json
at its root, this means it is not initialized. The command above will accomplish this.
Note: We have used the -y
flag to take the initialization defaults. To change any of these defaults, just open the package.json
and manually make any changes.
{
"name": "node-couchbase-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Installing the SDK
The Couchbase Node.js Client will run on any supported LTS version of Node.js.
$ npm install couchbase --save
Note: This will download the latest Couchbase Node.js SDK, and add a dependency to your package.json
.
Information on new features, fixes, known issues, as well as information on how to install older release versions is in the release notes.
TypeScript Support
Follow this section only if you intend to use TypeScript instead of JavaScript .
|
Since release 3.2, the Node.js SDK has added full support for the TypeScript programming language.
$ npm install -g typescript ts-node
This will install TypeScript globally on your machine and allow you to run commands with the tsc
cli. You will have noticed that we also install ts-node which is a handy execution utility that will help us run the example later on.
Before we can get started, run tsc --init
in the node-couchbase-project
directory
to generate a tsconfig.json
file. This will set you up with some initial configurations, which should suffice for our purposes.
Should you wish to make changes in future you can simply edit the file:
{
"compilerOptions": {
"disableReferencedProjectLoad": true,
"target": "es5",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Note that the example above does not include the generated comments for readability.
Hello Couchbase
At this point we want to transition from the terminal to your code editor of choice and point to the directory we have just created named node-couchbase-project
.
Let’s now create an empty file named index.js
, or alternatively index.ts
for TypeScript, and walk through step by step adding code to enable us to connect to a bucket, add a document and retrieve it using a key-value get operation:
const couchbase = require('couchbase')
async function main() {
const cluster = await couchbase.connect('couchbase://localhost', {
username: 'Administrator',
password: 'password',
})
import {
Bucket,
Cluster,
Collection,
connect,
GetResult,
MutationResult,
} from 'couchbase'
async function main() {
const cluster: Cluster = await connect('couchbase://localhost', {
username: 'Administrator',
password: 'password',
})
If you are connecting to Couchbase Capella rather than a local Couchbase Server, see the Cloud section, below.
Couchbase uses Role Based Access Control (RBAC) to control access to resources. For the sake of this example, we are connecting to Couchbase using the Full Admin role created during the installation of our Couchbase Server. Since we are running this locally, we are using the Couchbase alias for localhost.
// get a reference to our bucket
const bucket = cluster.bucket('travel-sample')
// get a reference to our bucket
const bucket: Bucket = cluster.bucket('travel-sample')
If you are not working with the travel-sample
data bucket, substitute travel-sample with your bucket-name.
The 3.2 SDK is ready for the introduction of Collections in the 7.0 release of the Couchbase Data Platform. The latest release, Couchbase Server 7.0, brings Collections, allowing Documents to be grouped by purpose or theme, according to specified Scope.
// get a reference to a collection
const collection = bucket.scope('inventory').collection('airline')
// get a reference to a collection
const collection: Collection = bucket.scope('inventory').collection('airline')
This feature was previously available as a developer preview from Couchbase Server 6.6. When connecting to a 6.6 cluster or earlier, we must use the DefaultCollection , which covers the whole Bucket.
|
// get a reference to the default collection, required for older Couchbase server versions
const collection_default = bucket.defaultCollection()
// get a reference to the default collection, required for older Couchbase server versions
const collection_default: Collection = bucket.defaultCollection()
Let’s create a document in our application that we can add to our travel-sample
bucket that conforms to the structure of a document of type airline
.
const airline = {
type: 'airline',
id: 8091,
callsign: 'CBS',
iata: 'IATA',
icao: 'ICAO',
name: 'Couchbase Airways',
}
interface Document {
type: string
id: number
callsign: string
iata: string
icao: string
name: string
}
const airline: Document = {
type: 'airline',
id: 8091,
callsign: 'CBS',
iata: 'IATA',
icao: 'ICAO',
name: 'Couchbase Airways',
}
Now we will create a function that will take care of upserting that document. This function is of type async
and simply awaits the result of the upsert and either logs out the result or error in our console:
const upsertDocument = async (doc) => {
try {
// key will equal: "airline_8091"
const key = `${doc.type}_${doc.id}`
const result = await collection.upsert(key, doc)
console.log('Upsert Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
const upsertDocument = async (doc: Document) => {
try {
// key will equal: "airline_8091"
const key: string = `${doc.type}_${doc.id}`
const result: MutationResult = await collection.upsert(key, doc)
console.log('Upsert Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
Now, we can simply call the upsertDocument
function passing in our airline
document:
We can turn around and retrieve that document using a key-value operation. Let’s create a function that takes a document key that is of type async
and awaits the result of the get operation and either logs out the result or error in our console:
const getAirlineByKey = async (key) => {
try {
const result = await collection.get(key)
console.log('Get Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
const getAirlineByKey = async (key: string) => {
try {
const result: GetResult = await collection.get(key)
console.log('Get Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
KV Operations are described in detail on the KV Operations page.
Now, we can simply call the getAirlineByKey
function passing in our valid document key airline_8091
and close our main
function:
To ensure that we can run the main function, we add this last line of code:
// Run the main function
main()
.catch((err) => {
console.log('ERR:', err)
process.exit(1)
})
.then(process.exit)
// Run the main function
main()
.catch((err) => {
console.log('ERR:', err)
process.exit(1)
})
.then(() => process.exit(0))
Now we can run our code:
The results you should expect are as follows:
Upsert Result:
MutationResult {
cas: CbCas { '0': <Buffer 00 00 3e b7 72 65 a0 16> },
token: CbMutationToken {
'0': <Buffer bf 02 e0 23 a7 4d 00 00 58 00 00 00 00 00 00 00 a9 03 00 00 00 00 00 00 74 72 61 76 65 6c 2d 73 61 6d 70 6c 65 00 00 00 48 54 83 05 01 00 00 00 30 54 ... 230 more bytes>
}
}
Get Result:
GetResult {
content: {
type: 'airline',
id: 8091,
callsign: 'CBS',
iata: null,
icao: null,
name: 'Couchbase Airways'
},
cas: CbCas { '0': <Buffer 00 00 3e b7 72 65 a0 16> },
expiryTime: undefined
}
Full Example
If you want to copy and paste to run the full example, here it is:
'use strict'
const couchbase = require('couchbase')
async function main() {
const cluster = await couchbase.connect('couchbase://localhost', {
username: 'Administrator',
password: 'password',
})
// get a reference to our bucket
const bucket = cluster.bucket('travel-sample')
// get a reference to a collection
const collection = bucket.scope('inventory').collection('airline')
// get a reference to the default collection, required for older Couchbase server versions
const collection_default = bucket.defaultCollection()
const airline = {
type: 'airline',
id: 8091,
callsign: 'CBS',
iata: 'IATA',
icao: 'ICAO',
name: 'Couchbase Airways',
}
const upsertDocument = async (doc) => {
try {
// key will equal: "airline_8091"
const key = `${doc.type}_${doc.id}`
const result = await collection.upsert(key, doc)
console.log('Upsert Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
await upsertDocument(airline)
const getAirlineByKey = async (key) => {
try {
const result = await collection.get(key)
console.log('Get Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
await getAirlineByKey('airline_8091')
}
// Run the main function
main()
.catch((err) => {
console.log('ERR:', err)
process.exit(1)
})
.then(process.exit)
'use strict'
import {
Bucket,
Cluster,
Collection,
connect,
GetResult,
MutationResult,
} from 'couchbase'
async function main() {
const cluster: Cluster = await connect('couchbase://localhost', {
username: 'Administrator',
password: 'password',
})
// get a reference to our bucket
const bucket: Bucket = cluster.bucket('travel-sample')
// get a reference to a collection
const collection: Collection = bucket.scope('inventory').collection('airline')
// get a reference to the default collection, required for older Couchbase server versions
const collection_default: Collection = bucket.defaultCollection()
interface Document {
type: string
id: number
callsign: string
iata: string
icao: string
name: string
}
const airline: Document = {
type: 'airline',
id: 8091,
callsign: 'CBS',
iata: 'IATA',
icao: 'ICAO',
name: 'Couchbase Airways',
}
const upsertDocument = async (doc: Document) => {
try {
// key will equal: "airline_8091"
const key: string = `${doc.type}_${doc.id}`
const result: MutationResult = await collection.upsert(key, doc)
console.log('Upsert Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
await upsertDocument(airline)
const getAirlineByKey = async (key: string) => {
try {
const result: GetResult = await collection.get(key)
console.log('Get Result: ')
console.log(result)
} catch (error) {
console.error(error)
}
}
await getAirlineByKey('airline_8091')
}
// Run the main function
main()
.catch((err) => {
console.log('ERR:', err)
process.exit(1)
})
.then(() => process.exit(0))
If you are connecting to Couchbase Capella, be sure to get the correct endpoint as well as user, password, and couchbasecloudbucket
— and see the Cloud section, below.
var couchbase = require('couchbase')
const clusterConnStr =
'couchbases://cb.abcdefab-cdef-abcd-efab-cdefabcdef.dp.cloud.couchbase.com'
const cloudRootCertificate = '/etc/x509-cert/SSLCA/clientdir/trust.pem'
const username = 'user'
const password = 'password'
const bucketName = 'couchbasecloudbucket'
async function go() {
const cluster = await couchbase.connect(clusterConnStr, {
username: username,
password: password,
trustStorePath: cloudRootCertificate,
})
const bucket = cluster.bucket(bucketName)
const collection = bucket.defaultCollection()
// Create a N1QL Primary Index (but ignore if it exists)
await cluster
.queryIndexes()
.createPrimaryIndex(bucketName, { ignoreExists: true })
// Create and store a document
await collection.upsert('user:king_arthur', {
name: 'Arthur',
email: 'kingarthur@couchbase.com',
interests: ['Holy Grail', 'African Swallows'],
})
// Load the Document and print it
// Prints Content and Metadata of the stored Document
let getResult = await collection.get('user:king_arthur')
console.log('got: ', getResult)
// Perform a N1QL Query
let queryResult = await cluster.query(
'SELECT name FROM ' + bucketName + ' WHERE $1 in interests LIMIT 1',
{ parameters: ['African Swallows'] }
)
queryResult.rows.forEach((row) => {
console.log('query row: ', row)
})
}
go()
Cloud Connections
If you are not working from the same Availability Zone as your Capella instance, refer to the following:
-
Notes on Constrained Network Environments,
-
If you have a consumer-grade router which has problems with DNS-SRV records review our Troubleshooting Guide.
Additional Resources
The API reference is generated for each release and the latest can be found here.
Links to each release are to be found in the individual release notes.
The Migrating from SDK2 to 3 page highlights the main differences to be aware of when migrating your code.
Couchbase welcomes community contributions to the Node.js SDK. The Node.js SDK source code is available on GitHub.
Ottoman is an ODM built for Couchbase and Node.js. Ottoman’s goal is to provide a better development experience while using Couchbase, bringing to developers a reliable tool to build systems that are easy to design, maintain, and scale.