Are your legacy databases holding up application development and slowing down performance?

With Couchbase you can:

  • ● Use SQL for familiar query access
  • ● Store data as JSON and avoid a restrictive relational data model
  • ● Build new features using our built-in multi-model services, including full-text search, analytics, eventing, and key-value

Check out the code

                                        Java - Upsert
                                        import com.couchbase.client.core.error.subdoc.PathNotFoundException;
import com.couchbase.client.java.*;
import com.couchbase.client.java.kv.*;
import com.couchbase.client.java.kv.MutationResult;
import com.couchbase.client.java.json.JsonObject;
import com.couchbase.client.java.kv.LookupInResult;
import static com.couchbase.client.java.kv.LookupInSpec.get;
import static com.couchbase.client.java.kv.MutateInSpec.upsert;
import java.util.Collections;

class Program {
  public static void main(String[] args) {
    var cluster = Cluster.connect(
      "couchbase://127.0.0.1", "username", "password"
    );
    var bucket = cluster.bucket("travel-sample");
    var collection = bucket.defaultCollection();

    JsonObject content = JsonObject.create()
      .put("country", "Iceland")
      .put("callsign", "ICEAIR")
      .put("iata", "FI")
      .put("icao", "ICE")
      .put("id", 123)
      .put("name", "Icelandair")
      .put("type", "airline");

    collection.upsert("airline_123", content);

    try {
      LookupInResult lookupResult = collection.lookupIn(
        "airline_123", Collections.singletonList(get("name"))
      );

      var str = lookupResult.contentAs(0, String.class);
      System.out.println("New Document name = " + str);

    } catch (PathNotFoundException ex) {
      System.out.println("Document not found!");
    }

  }
}
                                
                                        NodeJS - Upsert
                                        const couchbase = require('couchbase')

const main = async () => {
  const cluster = await couchbase.connect('couchbase://127.0.0.1', {
    username: 'username', password: 'password'
  })

  cluster.bucket('travel-sample')

  const getHotelsByCity = async (city) => {
    try {
      const query = `
        SELECT h.name, h.city, h.state
        FROM \`travel-sample\` h
        WHERE h.type = $1
          AND h.city = $2 LIMIT 5;
      `
      const options = { parameters: ['hotel', city] }

      const result = await cluster.query(query, options)
      console.log('Query Result: ')
      console.log(result.rows)
    } catch (error) {
      console.error(error)
    }
  }

  getHotelsByCity('Malibu')
    .then(() => process.exit(0))
}

main()
                                
                                        Python - Upsert
                                        #!/usr/bin/python3

import sys

from couchbase.cluster import Cluster, ClusterOptions
from couchbase.auth import PasswordAuthenticator

pa = PasswordAuthenticator('username', 'password')

cluster = Cluster('couchbase://127.0.0.1', ClusterOptions(pa))
bucket = cluster.bucket('travel-sample')

query = """
  SELECT h.name, h.city, h.state
  FROM `travel-sample` h
  WHERE h.type = $1
    AND h.city = $2 LIMIT 5
"""

try:
  result = cluster.query(query, 'hotel', 'Malibu')

  for row in result:
    # each row is an instance of the query call
    name = row['name']
    city = row['city']
    print("Hotel: " + name + ", " + city)

except:
  print("exception:", sys.exc_info()[0])
                                
                                        .NET - Upsert
                                        using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Couchbase;
using Couchbase.Core.Exceptions.KeyValue;
using Couchbase.KeyValue;

namespace CouchbaseDotNetExample
{
  class Program
  {
    static async Task Main(string[] args)
    {
      var cluster = await Cluster.ConnectAsync(
        "couchbase://127.0.0.1", "username", "password"
      );

      var bucket = await cluster.BucketAsync("travel-sample");
      var scope = await bucket.ScopeAsync("_default");
      var collection = await scope.CollectionAsync("_default");

      var content = new
        {
          Country = "Iceland",
          Callsign = "ICEAIR",
          Iata = "FI",
          Icao = "ICE",
          Id = 123,
          Name = "Icelandair",
          Type = "airline"
        };

      await collection.UpsertAsync("airline_123", content);

      try
      {
        var lookupResult = await collection.LookupInAsync("airline_123",
          new List
            {
              LookupInSpec.Get("name")
            });

        var name = lookupResult.ContentAs(0);
        Console.WriteLine($"New Document name = {name}");
      }
      catch (PathNotFoundException)
      {
        Console.WriteLine("Document not found!");
      }

      await cluster.DisposeAsync();
    }
  }
}
                                
                                        PHP - Upsert
                                        credentials("username", "password");
  $cluster = new \Couchbase\Cluster($connectionString, $options);

  $bucket = $cluster->bucket("travel-sample");
  $collection = $bucket->defaultCollection();

  $content = ["country" => "Iceland",
              "callsign" => "ICEAIR",
              "iata" => "FI",
              "icao" => "ICE",
              "id" => 123,
              "name" => "Icelandair",
              "type" => "airline"];

  $collection->upsert("airline_123", $content);
  try {
    $result = $collection->lookupIn("airline_123", [new \Couchbase\LookupGetSpec("name")]);
    $name = $result->content(0);
    print("New Document name = $name");
  } catch (\Couchbase\PathNotFoundException $pnfe) {
    print("Sub-doc path not found!");
  } catch (\Couchbase\BaseException $ex) {
    print("Exception $ex\n");
  }
?>
                                
                                        Ruby - Upsert
                                        require "couchbase"
include Couchbase

options = Cluster::ClusterOptions.new
options.authenticate("username", "password")
cluster = Cluster.connect("couchbase://127.0.0.1", options)

bucket = cluster.bucket("travel-sample")

begin
  options = Cluster::QueryOptions.new
  options.positional_parameters(["hotel"])
  result = cluster.query('SELECT x.* FROM `travel-sample` x WHERE x.`type`=$1 LIMIT 10;', options)
  result.rows.each do |row|
    puts row
  end
rescue Couchbase::Error::CouchbaseError => ex
  puts "Couchbase Error: #{ex}"
end
                                
                                        Scala - Upsert
                                        package com.couchbase

import com.couchbase.client.core.error.{CouchbaseException, DocumentNotFoundException}
import com.couchbase.client.scala.Cluster
import com.couchbase.client.scala.query.{QueryResult, QueryOptions, QueryParameters}
import scala.util.{Failure, Success, Try}
import com.couchbase.client.scala.json.{JsonObject, JsonObjectSafe}

object Program extends App {
  val cluster = Cluster.connect("127.0.0.1", "username", "password").get
  var bucket = cluster.bucket("travel-sample");
  val collection = bucket.defaultCollection

  val options = QueryOptions().parameters(
                    QueryParameters.Positional("hotel")
                  )
  val result: Try[QueryResult] = cluster.query("""SELECT x.* FROM `travel-sample` x WHERE x.`type`=$1 LIMIT 10;""", options)
  result match {
    case Success(result: QueryResult) =>
      result.rowsAs[JsonObject] match {
        case Success(rows) =>
          rows.foreach(row => println(row))
        case Failure(err) => println("Error decoding result: " + err)
      }
    case Failure(err: CouchbaseException) => println("Couchbase error: " + err)
    case Failure(err) => println("Error: " + err)
  }
}
                                
                                        Golang - Upsert
                                        package main

import (
  "fmt"
  "log"
  "time"

  "github.com/couchbase/gocb/v2"
)

func main() {
  cluster, err := gocb.Connect("couchbase://127.0.0.1", gocb.ClusterOptions{
    Authenticator: gocb.PasswordAuthenticator{
      Username: "username",
      Password: "password",
    },
  })
  if err != nil {
    log.Fatal(err)
  }

  bucket := cluster.Bucket("travel-sample")
  err = bucket.WaitUntilReady(5*time.Second, nil)
  if err != nil {
    log.Fatal(err)
  }

  collection := bucket.DefaultCollection()

  type Doc struct {
    Id int `json:"id"`
    Type string `json:"type"`
    Name string `json:"name"`
    Iata string `json:"iata"`
    Icao string `json:"icao"`
    Callsign string `json:"callsign"`
    Country string `json:"country"`
  }

  document := Doc {
    Country: "Iceland",
    Callsign: "ICEAIR",
    Iata: "FI",
    Icao: "ICE",
    Id: 123,
    Name: "Icelandair",
    Type: "airline",
  }

  _, err = collection.Upsert("airline_123", &document, nil)
  if err != nil {
    log.Fatal(err)
  }

  options := []gocb.LookupInSpec{
    gocb.GetSpec("name", &gocb.GetSpecOptions{}),
  }
  results, err := collection.LookupIn("airline_123", options, &gocb.LookupInOptions{})
  if err != nil {
    log.Fatal(err)
  }

  var country string
  err = results.ContentAt(0, &country)
  if err != nil {
    log.Fatal(err)
  }

  fmt.Printf("New document name: %s\n", country)
}
                                
                                        C++ - Upsert
                                        #include 
#include 
#include 

#include 

static void
check(lcb_STATUS err, const char* msg)
{
    if (err != LCB_SUCCESS) {
        std::cerr << "[ERROR] " << msg << ": " << lcb_strerror_short(err) << "\n";
        exit(EXIT_FAILURE);
    }
}

struct Result {
    std::string value{};
    lcb_STATUS status{ LCB_SUCCESS };
};

struct SubdocResults {
    lcb_STATUS status{ LCB_SUCCESS };
    std::vector entries{};
};

static void
sdget_callback(lcb_INSTANCE*, int, const lcb_RESPSUBDOC* resp)
{
    SubdocResults* results = nullptr;
    lcb_respsubdoc_cookie(resp, reinterpret_cast(&results));
    results->status = lcb_respsubdoc_status(resp);

    if (results->status != LCB_SUCCESS) {
        return;
    }

    std::size_t number_of_results = lcb_respsubdoc_result_size(resp);
    results->entries.resize(number_of_results);
    for (size_t idx = 0; idx < number_of_results; ++idx) {
        results->entries[idx].status = lcb_respsubdoc_result_status(resp, idx);
        const char* buf = nullptr;
        std::size_t buf_len = 0;
        lcb_respsubdoc_result_value(resp, idx, &buf, &buf_len);
        if (buf_len > 0) {
            results->entries[idx].value.assign(buf, buf_len);
        }
    }
}

int
main()
{
    std::string username{ "username" };
    std::string password{ "password" };
    std::string connection_string{ "couchbase://127.0.0.1" };
    std::string bucket_name{ "travel-sample" };

    lcb_CREATEOPTS* create_options = nullptr;
    check(lcb_createopts_create(&create_options, LCB_TYPE_BUCKET), "build options object for lcb_create");
    check(lcb_createopts_credentials(create_options, username.c_str(), username.size(), password.c_str(), password.size()),
        "assign credentials");
    check(lcb_createopts_connstr(create_options, connection_string.c_str(), connection_string.size()), "assign connection string");
    check(lcb_createopts_bucket(create_options, bucket_name.c_str(), bucket_name.size()), "assign bucket name");

    lcb_INSTANCE* instance = nullptr;
    check(lcb_create(&instance, create_options), "create lcb_INSTANCE");
    check(lcb_createopts_destroy(create_options), "destroy options object");
    check(lcb_connect(instance), "schedule connection");
    check(lcb_wait(instance, LCB_WAIT_DEFAULT), "wait for connection");
    check(lcb_get_bootstrap_status(instance), "check bootstrap status");

    std::string key{ "airline_123" };
    {
      std::string value{ R"({"country":"Iceland", "callsign":"ICEAIR", "iata":"FI", "icao":"ICE", "id":123, "name":"Icelandair", "type":"airline"})" };

      lcb_CMDSTORE* cmd = nullptr;
      check(lcb_cmdstore_create(&cmd, LCB_STORE_UPSERT), "create UPSERT command");
      check(lcb_cmdstore_key(cmd, key.c_str(), key.size()), "assign ID for UPSERT command");
      check(lcb_cmdstore_value(cmd, value.c_str(), value.size()), "assign value for UPSERT command");
      check(lcb_store(instance, nullptr, cmd), "schedule UPSERT command");
      check(lcb_cmdstore_destroy(cmd), "destroy UPSERT command");
      lcb_wait(instance, LCB_WAIT_DEFAULT);
    }

    lcb_install_callback(instance, LCB_CALLBACK_SDLOOKUP, reinterpret_cast(sdget_callback));

    {
        SubdocResults results;

        lcb_SUBDOCSPECS* specs = nullptr;
        check(lcb_subdocspecs_create(&specs, 1), "create SUBDOC operations container");

        std::vector paths{
            "name",
        };

        check(lcb_subdocspecs_get(specs, 0, 0, paths[0].c_str(), paths[0].size()), "create SUBDOC-GET operation");

        lcb_CMDSUBDOC* cmd = nullptr;
        check(lcb_cmdsubdoc_create(&cmd), "create SUBDOC command");
        check(lcb_cmdsubdoc_key(cmd, key.c_str(), key.size()), "assign ID to SUBDOC command");
        check(lcb_cmdsubdoc_specs(cmd, specs), "assign operations to SUBDOC command");
        check(lcb_subdoc(instance, &results, cmd), "schedule SUBDOC command");
        check(lcb_cmdsubdoc_destroy(cmd), "destroy SUBDOC command");
        check(lcb_subdocspecs_destroy(specs), "destroy SUBDOC operations");

        lcb_wait(instance, LCB_WAIT_DEFAULT);

        check(results.status, "status of SUBDOC operation");
        std::size_t idx = 0;
        for (const auto& entry : results.entries) {
            if (entry.status == LCB_SUCCESS) {
                std::cout << "New Document name: " << (entry.value.empty() ? "(no value)" : entry.value) << "\n";
            } else {
                std::cout << "code=" << lcb_strerror_short(entry.status) << "\n";
            }
            ++idx;
        }
    }

    lcb_destroy(instance);
    return 0;
}
                                
Couchbase Capella DBaaS


Stay ahead of tomorrow’s database challenges

Challenge 1

Rigid data models slow down dev cycles

Legacy databases

  • Rigid data models make agile development difficult
  • Application objects are split into tables and need to be reassembled

Couchbase

  • JSON data supports agile development through flexible data models
  • Application objects can be directly serialized or deserialized

Challenge 2

Apps perform poorly

Legacy databases

  • Relational modeling often requires a high number of writes and reads
  • No built-in managed cache available

Couchbase

  • Caching delivers highly responsive user experiences and lower latency
  • Built-in managed cache provides sub-millisecond latency

Challenge 3

New functionality requires new tools

Legacy databases

  • Bolted on tools and time-consuming integrations are required to handle caching, analytics, eventing, and mobile syncing
  • Data access is limited to only SQL
  • More bolt-ons equal more work and more maintenance

Couchbase

  • Delivers the familiarity of SQL (with SQL++)
  • Provides multi-model capabilities (full-text search, query, key/value, analytics, and more, all on the same data set)
  • Automatically syncs your mobile and edge data in real time

Challenge 4

It’s hard to scale deployments with HA

Legacy databases

  • Optimized for single server deployments and expensive vertical scaling
  • Horizontal scaling is expensive and difficult
  • Upgrades and maintenance equal downtime equal 2 a.m. weekend office hours

Couchbase

  • Core distributed data architecture
  • Masterless, shared-nothing
    automatic horizontal scaling
  • No shard or partition keys to manage
  • Automatic replication
  • Automatic failover recovery and rebalancing
  • Maintenance and upgrades don't require downtime