CINXE.COM
Hello World | Couchbase Docs
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv=content-security-policy content="default-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' https://fonts.gstatic.com; frame-src 'self' https:; img-src 'self' data: https:; connect-src 'self' https:; worker-src blob:;"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://metrics.couchbase.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-MVPNN2');</script> <!-- End Google Tag Manager --> <title>Hello World | Couchbase Docs</title> <link rel="canonical" href="https://docs.couchbase.com/scala-sdk/current/hello-world/start-using-sdk.html"> <link rel="stylesheet" href="../../../_/css/site.css"> <script src="../../../_/js/vendor/jquery.js"></script> <script src="https://cdn.cookielaw.org/scripttemplates/otSDKStub.js" data-domain-script="748511ff-10bf-44bf-88b8-36382e5b5fd9"></script> <script>function OptanonWrapper(){}</script> <meta name="description" content="Install, connect, try. A quick start guide to get you up and running with Couchbase and the Scala SDK."> <link rel="schema.dcterms" href="https://purl.org/dc/terms/"> <meta name="dcterms.subject" content="scala-sdk"> <meta name="dcterms.identifier" content="1.7"> <meta name="page-url" content="/scala-sdk/current/hello-world/start-using-sdk.html"> <meta name="page-nav-header-levels" content="2"> <meta name="docsearch:component" content="scala-sdk"> <meta name="docsearch:component_title" content="Scala SDK"> <meta name="docsearch:cversion" content="1.7"> <meta name="docsearch:component_version" content="scala-sdk@1.7"> <meta name="docsearch:module" content="hello-world"> <meta name="docsearch:breadcrumbs" content="Scala SDK / Hello World"> <meta name="docsearch:topic_type" content=""> <meta name="docsearch:version_rank" content="1"> <meta name="docsearch:status" content=""> <meta name="docsearch:edition" content=""> <meta name="docsearch:page_rank" content="50"> <meta name="generator" content="Antora 3.1.5"> <link rel="icon" href="../../../_/img/favicon.svg" type="image/svg+xml"> <link rel="icon" href="../../../_/img/favicon.ico" type="image/x-icon" sizes="any"> </head> <body class="article"> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-MVPNN2" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <header class="header fixed-top"> <div class="header-top-row"> <div class="container"> <nav class="navbar navbar-expand-md flex-nowrap justify-content-between navbar-new-top"> <ul class="navbar-brand-list"> <li class="brand-logo"> <a class="navbar-brand" href="https://www.couchbase.com"> <img src="../../../_/img/couchbase-logo.svg" alt="Couchbase" /> </a> </li> <li> <a class="navbar-brand cb-documentation" href="https://docs.couchbase.com/home/index.html"> <img src="../../../_/img/cb-documentation.svg" alt="Couchbase Documentation" class="cb-docs" /> <img src="../../../_/img/cb-docs-hover.svg" alt="Couchbase Documentation" class="hide cb-hover-docs" /> </a> </li> </ul> <button class="navbar-burger" data-target="topbar-menu"> <span></span> <span></span> <span></span> </button> </nav> </div> </div> <div class="header-bottom-row" id="topbar-menu"> <div class="container"> <nav class="navbar navbar-new-bottom "> <div class="navbar-collapse collapse" id="navbar2"> <ul class="navbar-nav w-100 justify-content-start"> <li class="nav-item ""> <a href="https://docs.couchbase.com/home/index.html" class="nav-link"> <i class="fas fa-home"></i> </a> </li> <li class="nav-item "> <a class="nav-link" href="../../../home/server.html"> Server </a> </li> <li class="nav-item "> <a class="nav-link" href="../../../home/mobile.html"> Mobile </a> </li> <li class="nav-item "> <a class="nav-link" href="../../../home/cloud.html"> Capella </a> </li> <li class="nav-item "> <a class="nav-link" href="../../../cloud-native-database/index.html"> Cloud-Native </a> </li> <li class="nav-item nav-item-selected"> <a class="nav-link" href="../../../home/sdk.html"> Couchbase SDKs </a> </li> <li class="nav-item "> <a class="nav-link" href="../../../home/columnar-sdk.html"> Columnar SDKs </a> </li> </ul> </div> <div class="primary-action"> <div class="navbar-item search" id="search"> <input class="dataLayer query" type="text" placeholder="Search Docs"><i class="fas fa-search"></i> </div> <a class="btn btn-primary btn-grey-reverse" onclick="(window.dataLayer=window.dataLayer||[]).push({'event':'customEvent', 'category':'CTA', 'action':'Button Click', 'label':'Download'});" href="https://www.couchbase.com/downloads"> Downloads <i class="far fa-arrow-to-bottom fa-fw"></i> </a> <a href="https://cloud.couchbase.com/sign-up" class="btn btn-primary" onclick="(window.dataLayer=window.dataLayer||[]).push({'event':'customEvent', 'category':'CTA', 'action':'Button Click', 'label':'Free Trial'});" > Try Free <i class="far fa-cloud fa-fw"></i> </a> </div> </nav> </div> </div> </header> <div class="body container"> <aside class="nav left-sidebar"> <div class="nav-container"> <a href="#" class="menu-expand-toggle"><span>Navigation</span><i class="fas fa-times-circle"></i><i class="fas fa-chevron-circle-left"></i></a> <template id="page-versions" style="display: none"> <select class="version_list" data-component="scala-sdk"> <option value="1.7" data-url="start-using-sdk.html" selected>1.7</option> <option value="1.6" data-url="../../1.6/hello-world/start-using-sdk.html">1.6</option> <option value="1.5" data-url="../../1.5/hello-world/start-using-sdk.html">1.5</option> <option value="1.4" data-url="../../1.4/hello-world/start-using-sdk.html">1.4</option> <option value="1.3" data-url="../../1.3/hello-world/start-using-sdk.html">1.3</option> </select> </template> </div> </aside> <aside class="toc sidebar" data-title="Contents" data-levels="3"> <div class="sidebar-box"> <div class="tools" role="navigation"> <ul> <li class="tool edit"><a href="https://github.com/couchbase/docs-sdk-scala/edit/release/1.7/modules/hello-world/pages/start-using-sdk.adoc" title="Edit Page" target="_blank" rel="noopener" class="remove-ext-icon">Edit on GitHub</a></li> </ul> </div> <div class="toc-menu"></div> <div class="is-this-helpful-box"> <h4> Is this page helpful?</h4> <div class="btn-row"> <a href="#" class="like-btn helpful-btn" id="yesBtn" data-page-rating="like" > <i class="far fa-thumbs-up"></i> Yes </a> <a href="#" class="dislike-btn helpful-btn" id="noBtn" data-page-rating="dislike"> <i class="far fa-thumbs-down"></i> No</a> </div> <div class="any-feedback"> <a href="#" class="btn any-feedback-btn" id="myCustomTrigger">Leave Additional Feedback? </a> </div> <div class="dialog-box" id="dialogBox"> <form> <div class="form-group " id="additionalFeedbackBox"> <textarea class="input-control feed-back-msg" rows="8" placeholder="Any Additonal Feedback?"></textarea> <div class="action-btn-row "> <a href="#" class="skip-btn" id="skipBtnMsg">Skip</a> <button class="submit-btn btn blue-btn disabled" > Submit </button> <a href="#" class="info-btn"><i class="fas fa-info-circle"></i></a> </div> </div> </form> </div> </div> </div> </aside> <div class="feedback-modal modal-popup"> <div class="modal-popup-dialogue"> <div class="popup-header"> <a href="#" class="close-popup"><i class="fa fa-times"></i></a> </div> <div class="popup-content"> <p> Please use the form below to provide your feedback. Because your feedback is valuable to us, the information you submit in this form is recorded in our issue tracking system (JIRA), which is publicly available. You can track the status of your feedback using the ticket number displayed in the dialog once you submit the form. </p> </div> </div> </div> <main class="article" data-ceiling="topbar"> <div class="article-header"> <nav class="crumbs" aria-label="breadcrumbs"> <ul> <li class="crumb"><a href="overview.html">Scala SDK</a></li> <li class="crumb"><a href="start-using-sdk.html">Hello World</a></li> </ul> </nav> </div> <article class="doc"> <div class="page-heading-title"> <h1 class="page">Hello World</h1> <div class="labels"> <ul></ul> </div> </div> <div class="contributor-list-box"> <span class="last-commit-date" id="commitdate"> </span> <ul id="contributorList"></ul> <span id="otherContributor"> + </span> </div><div id="preamble"> <div class="sectionbody"> <div class="quoteblock abstract"> <blockquote> Install, connect, try. A quick start guide to get you up and running with Couchbase and the Scala SDK. </blockquote> </div> <div class="paragraph"> <p>Couchbase has a simple interface for creating and modifying records in a document, based upon the <strong>collection</strong> into which the documents are organized. You can read more about data modeling <a href="#data-modeling">below</a>, but first let’s look at those data operations, and installing the Scala SDK.</p> </div> <div class="listingblock"> <div class="title">Upsert with a Unique ID</div> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L80-L84">val docId = UUID.randomUUID().toString collection.upsert(docId, json) match { case Success(result) => case Failure(exception) => println("Error: " + exception) }</code></pre> </div> </div> <div class="paragraph"> <p><code>upsert</code> inserts (creates) the document if it does not exist, or replaces it if it does. We’ll explore creating and retrieving data records in more detail <a href="#create-read-update-delete">below</a> (and touch lightly upon a little of Scala’s functional programming approach as we go), after walking through a quick installation.</p> </div> </div> </div> <div class="sect1"> <h2 id="before-you-start"><a class="anchor" href="#before-you-start"></a>Before You Start</h2> <div class="sectionbody"> <div class="paragraph"> <p>Couchbase Capella, our Database-as-a-Service, lets you get on with what matters, while we take care of the administration for you. Alternately, if you need to control every aspect of deployment — or just want to run the Server in a VM on your laptop — there are several self-managed options available:</p> </div> <div id="tabs-1" class="openblock tabs is-sync is-loading"> <div class="content"> <div class="ulist tablist"> <ul> <li id="tabs-1-couchbase-capella" class="tab"> <p>Couchbase Capella</p> </li> <li id="tabs-1-self-managed-couchbase-server" class="tab"> <p>Self-Managed Couchbase Server</p> </li> </ul> </div> <div id="tabs-1-couchbase-capella--panel" class="tabpanel" aria-labelledby="tabs-1-couchbase-capella"> <div class="paragraph"> <p>If you haven’t already got a cluster set up, the easiest route is to <a href="https://cloud.couchbase.com/sign-up" target="_blank" rel="noopener">sign up to Couchbase Capella and deploy a free tier cluster</a>, then come back to this page. Make a note of the <a href="../../../cloud/get-started/connect.html" class="xref page">endpoint</a> to connect to, and remember the credentials for the user that you set up.</p> </div> </div> <div id="tabs-1-self-managed-couchbase-server--panel" class="tabpanel" aria-labelledby="tabs-1-self-managed-couchbase-server"> <div class="paragraph"> <p>Install Couchbase Server locally, or in your private Cloud:</p> </div> <div class="ulist"> <ul> <li> <p><a href="../../../server/current/install/get-started.html" class="xref page">Deployment overview</a></p> </li> <li> <p><a href="../../../server/current/install/getting-started-docker.html" class="xref page">Docker Install</a></p> </li> <li> <p><a href="../../../operator/current/overview.html" class="xref page">Couchbase Autonomous Operator</a></p> <div class="ulist"> <ul> <li> <p><a href="../../../operator/current/install-kubernetes.html" class="xref page">Kubernetes</a></p> </li> <li> <p><a href="../../../operator/current/install-openshift.html" class="xref page">Openshift</a></p> </li> </ul> </div> </li> <li> <p><a href="#7.6server:cloud:couchbase-cloud-deployment.adoc" class="xref unresolved">Cloud Marketplace</a>:</p> <div class="ulist"> <ul> <li> <p><a href="../../../server/current/cloud/couchbase-aws-marketplace.html" class="xref page">AWS Marketplace</a></p> </li> <li> <p><a href="../../../server/current/cloud/couchbase-azure-marketplace.html" class="xref page">Azure Marketplace</a></p> </li> <li> <p><a href="../../../server/current/cloud/couchbase-gcp-cloud-launcher.html" class="xref page">GCP Marketplace</a></p> </li> </ul> </div> </li> </ul> </div> <div class="paragraph"> <p>For the example code below to run, you’ll need the username and password of the Administrator user that you create, and the IP address of at least one of the nodes of the cluster.</p> </div> </div> </div> </div> <div class="sect2"> <h3 id="prerequisites"><a class="anchor" href="#prerequisites"></a>Prerequisites</h3> <div class="ulist"> <ul> <li> <p>The Scala SDK is tested against LTS versions of Oracle JDK and OpenJDK — see the <a href="../project-docs/compatibility.html#jdk-compat" class="xref page">compatibility docs</a>.</p> </li> <li> <p>The Couchbase Scala SDK 1.7 Client supports Scala 2.12 and 2.13.</p> </li> </ul> </div> <div class="paragraph"> <p>The code examples also assume:</p> </div> <div id="tabs-2" class="openblock tabs is-sync is-loading"> <div class="content"> <div class="ulist tablist"> <ul> <li id="tabs-2-couchbase-capella" class="tab"> <p>Couchbase Capella</p> </li> <li id="tabs-2-self-managed-couchbase-server" class="tab"> <p>Self-Managed Couchbase Server</p> </li> </ul> </div> <div id="tabs-2-couchbase-capella--panel" class="tabpanel" aria-labelledby="tabs-2-couchbase-capella"> <div class="ulist"> <ul> <li> <p>You have signed up to <a href="https://cloud.couchbase.com/sign-up">Couchbase Capella</a>.</p> </li> <li> <p>You have created your own bucket, or loaded the Travel Sample dataset. Note, the Travel Sample dataset is installed automatically when deploying a Capella free tier cluster.</p> </li> <li> <p>A user is created with permissions to access the cluster (at least Application Access permissions). See the <a href="../../../cloud/get-started/run-first-queries.html#credentials" class="xref page">Capella connection page</a> for more details.</p> </li> </ul> </div> <div class="admonitionblock important"> <table> <tr> <td class="icon"> <i class="fa icon-important" title="Important"></i> </td> <td class="content"> Couchbase Capella uses <a href="../../../cloud/organizations/organization-projects-overview.html" class="xref page">Roles</a> to control user access to cluster resources. For the purposes of this guide, you can use the <strong>Organization Owner</strong> role automatically assigned to your account during installation of the Capella cluster. In production, Couchbase strongly recommends setting up users with more granular access roles as a best practice for data security. </td> </tr> </table> </div> </div> <div id="tabs-2-self-managed-couchbase-server--panel" class="tabpanel" aria-labelledby="tabs-2-self-managed-couchbase-server"> <div class="ulist"> <ul> <li> <p><a href="#7.6@server:getting-started/do-a-quick-install.adoc" class="xref unresolved">Couchbase Server</a> is installed and accessible locally.</p> </li> <li> <p>You have created your own bucket, or loaded the Travel Sample dataset using the <a href="../../../server/current/manage/manage-settings/install-sample-buckets.html#install-sample-buckets-with-the-ui" class="xref page">Web interface</a>.</p> </li> <li> <p>A user is created with permissions to access your cluster (at least Application Access permissions). See <a href="../../../server/current/manage/manage-security/manage-users-and-roles.html" class="xref page">Manage Users, Groups and Roles</a> for more details.</p> </li> </ul> </div> <div class="admonitionblock important"> <table> <tr> <td class="icon"> <i class="fa icon-important" title="Important"></i> </td> <td class="content"> Couchbase Server uses <a href="../../../server/current/learn/security/roles.html" class="xref page">Role-Based Access Control (RBAC)</a> to control access to cluster resources. In this guide we suggest using the <strong>Full Admin</strong> role created during setup of your local Couchbase Server cluster. In production, Couchbase strongly recommends setting up users with more granular access roles as a best practice for data security. </td> </tr> </table> </div> </div> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="installation"><a class="anchor" href="#installation"></a>Installation</h2> <div class="sectionbody"> <div class="paragraph"> <p>More details of the installation process are in the <a href="../project-docs/sdk-full-installation.html" class="xref page">full installation guide</a>. In most cases, given the above prerequisites, it’s a simple matter of the following for your favorite build tool:</p> </div> <div id="tabs-3" class="openblock tabs is-sync is-loading"> <div class="content"> <div class="ulist tablist"> <ul> <li id="tabs-3-scala-build-tool-sbt" class="tab"> <p>Scala Build Tool (SBT)</p> </li> <li id="tabs-3-gradle" class="tab"> <p>Gradle</p> </li> <li id="tabs-3-maven" class="tab"> <p>Maven</p> </li> </ul> </div> <div id="tabs-3-scala-build-tool-sbt--panel" class="tabpanel" aria-labelledby="tabs-3-scala-build-tool-sbt"> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-sbt hljs" data-lang="sbt">libraryDependencies += "com.couchbase.client" %% "scala-client" % "1.7.5"</code></pre> </div> </div> <div class="paragraph"> <p>This will automatically use the Scala 2.12 or 2.13 builds, as appropriate for your SBT project.</p> </div> </div> <div id="tabs-3-gradle--panel" class="tabpanel" aria-labelledby="tabs-3-gradle"> <div class="paragraph"> <p>For Scala 2.13, include the following in your <code>build.gradle</code>:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-groovy hljs" data-lang="groovy">dependencies { compile group: 'com.couchbase.client', name: 'scala-client_2.13', version: '1.7.5' }</code></pre> </div> </div> <div class="paragraph"> <p>For Scala 2.12, refer to the full <a href="../project-docs/sdk-full-installation.html" class="xref page">Installation page</a>.</p> </div> </div> <div id="tabs-3-maven--panel" class="tabpanel" aria-labelledby="tabs-3-maven"> <div class="paragraph"> <p>For Scala 2.13, include the following in your Maven <code>pom.xml</code>:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml"><dependencies> <dependency> <groupId>com.couchbase.client</groupId> <artifactId>scala-client_2.13</artifactId> <version>1.7.5</version> </dependency> </dependencies></code></pre> </div> </div> <div class="paragraph"> <p>For Scala 2.12, refer to the full <a href="../project-docs/sdk-full-installation.html" class="xref page">Installation page</a>.</p> </div> </div> </div> </div> <div class="sect2"> <h3 id="ide-plugins"><a class="anchor" href="#ide-plugins"></a>IDE Plugins</h3> <div class="paragraph"> <p>To make development easier, Couchbase plugins are available for VSCode and the IntelliJ family of IDEs and editors. For links and more information on these and other integrations across the Scala ecosystem, check out the <a href="../project-docs/third-party-integrations.html" class="xref page">Integrations & Ecosystem</a> page.</p> </div> </div> <div class="sect2"> <h3 id="grab-the-code"><a class="anchor" href="#grab-the-code"></a>Grab the Code</h3> <div class="paragraph"> <p>If you’re all set up and in a real hurry, just grab this code sample and add in your Capella details.</p> </div> <details> <summary class="title">Complete Hello World code sample [<strong>Click to open or collapse the listing</strong>]</summary> <div class="content"> <div class="literalblock"> <div class="content"> <pre>/* * Copyright (c) 2024 Couchbase, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // tag::imports[] import com.couchbase.client.scala.durability.Durability import com.couchbase.client.scala.env.{ ClusterEnvironment, SecurityConfig, TimeoutConfig } import com.couchbase.client.scala.json.{JsonObject, JsonObjectSafe} import com.couchbase.client.scala.kv.ReplaceOptions import com.couchbase.client.scala.{Cluster, ClusterOptions} import io.netty.handler.ssl.util.InsecureTrustManagerFactory import java.nio.file.Path import java.util.UUID import scala.concurrent.duration._ import scala.util.{Failure, Success, Try} // end::imports[] object Cloud { def main(args: Array[String]): Unit = { // tag::connect[] // Update this to your cluster val endpoint = "cb.<your-endpoint>.cloud.couchbase.com" val username = "username" val password = "Password!123" val bucketName = "travel-sample" val env = ClusterEnvironment.builder .securityConfig( SecurityConfig() .enableTls(true) ) // Sets a pre-configured profile called "wan-development" to help avoid latency issues // when accessing Capella from a different Wide Area Network // or Availability Zone (e.g. your laptop). .applyProfile(ClusterEnvironment.WanDevelopmentProfile) .build .get val cluster = Cluster .connect( "couchbases://" + endpoint, ClusterOptions .create(username, password) .environment(env) ) .get // end::connect[] // tag::bucket[] val bucket = cluster.bucket(bucketName) bucket.waitUntilReady(30.seconds).get // end::bucket[] // tag::collection[] val collection = bucket.scope("inventory").collection("airport") // end::collection[] // tag::json[] val json = JsonObject("status" -> "awesome") // end::json[] // tag::upsert[] val docId = UUID.randomUUID().toString collection.upsert(docId, json) match { case Success(result) => case Failure(exception) => println("Error: " + exception) } // end::upsert[] // tag::get[] // Get a document collection.get(docId) match { case Success(result) => // Convert the content to a JsonObjectSafe result.contentAs[JsonObjectSafe] match { case Success(json) => // Pull out the JSON's status field, if it exists json.str("status") match { case Success(hello) => println(s"Couchbase is $hello") case _ => println("Field 'status' did not exist") } case Failure(err) => println("Error decoding result: " + err) } case Failure(err) => println("Error getting document: " + err) } // end::get[] def getFor() { // tag::get-for[] val result: Try[String] = for { result <- collection.get(docId) json <- result.contentAs[JsonObjectSafe] status <- json.str("status") } yield status result match { case Success(status) => println(s"Couchbase is $status") case Failure(err) => println("Error: " + err) } // end::get-for[] } def getMap() { // tag::get-map[] val result: Try[String] = collection .get(docId) .flatMap(_.contentAs[JsonObjectSafe]) .flatMap(_.str("status")) result match { case Success(status) => println(s"Couchbase is $status") case Failure(err) => println("Error: " + err) } // end::get-map[] } def replaceOptions() { // tag::replace-options[] collection.replace( docId, json, ReplaceOptions() .expiry(10.seconds) .durability(Durability.Majority) ) match { case Success(status) => case Failure(err) => println("Error: " + err) } // end::replace-options[] } def replaceNamed() { // tag::replace-named[] collection.replace(docId, json, durability = Durability.Majority) match { case Success(status) => case Failure(err) => println("Error: " + err) } // end::replace-named[] } } }</pre> </div> </div> </div> </details> <div class="paragraph"> <p>Otherwise, read on as we introduce the CRUD API and connection to Capella or self-managed Couchbase Server.</p> </div> <div class="admonitionblock tip"> <table> <tr> <td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td> <td class="content"> There’s a <strong>View</strong> link to the complete sample code on GitHub above each of the snippets on these SDK pages, and a <strong>Copy</strong> icon to grab just the snippet shown. </td> </tr> </table> </div> </div> </div> </div> <div class="sect1"> <h2 id="connect-to-your-database"><a class="anchor" href="#connect-to-your-database"></a>Connect to your Database</h2> <div class="sectionbody"> <div class="paragraph"> <p>Connect to your Couchbase Capella operational cluster (or your local Couchbase Cluster, if you are trying out self-managed Couchbase).</p> </div> <div id="tabs-4" class="openblock tabs is-sync data-sync-group-id=Couchbase聽Capella|Self-Managed聽Couchbase聽Server is-loading"> <div class="content"> <div class="ulist tablist"> <ul> <li id="tabs-4-couchbase-capella" class="tab"> <p>Couchbase Capella</p> </li> <li id="tabs-4-self-managed-couchbase-server" class="tab"> <p>Self-Managed Couchbase Server</p> </li> <li id="tabs-4-cloud-native-gateway-cng" class="tab"> <p>Cloud Native Gateway (CNG)</p> </li> </ul> </div> <div id="tabs-4-couchbase-capella--panel" class="tabpanel" aria-labelledby="tabs-4-couchbase-capella"> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L38-L63">// Update this to your cluster val endpoint = "cb.<your-endpoint>.cloud.couchbase.com" val username = "username" val password = "Password!123" val bucketName = "travel-sample" val env = ClusterEnvironment.builder .securityConfig( SecurityConfig() .enableTls(true) ) // Sets a pre-configured profile called "wan-development" to help avoid latency issues // when accessing Capella from a different Wide Area Network // or Availability Zone (e.g. your laptop). .applyProfile(ClusterEnvironment.WanDevelopmentProfile) .build .get val cluster = Cluster .connect( "couchbases://" + endpoint, ClusterOptions .create(username, password) .environment(env) ) .get</code></pre> </div> </div> <div class="paragraph"> <p>Note, the client certificate for connecting to a Capella cluster is included in the SDK installation.</p> </div> </div> <div id="tabs-4-self-managed-couchbase-server--panel" class="tabpanel" aria-labelledby="tabs-4-self-managed-couchbase-server"> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/StartUsing.scala#L36-L58">// Update this to your cluster val username = "Administrator" val password = "password" val bucketName = "travel-sample" val env = ClusterEnvironment.builder // You should uncomment this if running in a production environment. // .securityConfig( // SecurityConfig() // .enableTls(true) // ) .build .get val cluster = Cluster .connect( // For a secure cluster connection, use `couchbases://<your-cluster-ip>` instead. "couchbase://localhost", ClusterOptions .create(username, password) .environment(env) ) .get</code></pre> </div> </div> </div> <div id="tabs-4-cloud-native-gateway-cng--panel" class="tabpanel" aria-labelledby="tabs-4-cloud-native-gateway-cng"> <div class="paragraph"> <p>Couchbase’s large number of ports across the URLs of many services can be proxied by using a <code>couchbase2://</code> endpoint as the connection string — currently only compatible with recent versions of <a href="../../../operator/current/concept-cloud-native-gateway.html" class="xref page">Couchbase Autonomous Operator</a>:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala">.connect( "couchbase2://10.12.14.16", ClusterOptions .create(username, password) .environment(env) )</code></pre> </div> </div> <div class="paragraph"> <p>Read more on the <a href="../howtos/managing-connections.html#cloud-native-gateway" class="xref page">Connections</a> page.</p> </div> </div> </div> </div> <div class="paragraph"> <p>The <code>ClusterEnvironment.builder</code> is covered more fully on the <a href="../ref/client-settings.html#the-environment-builder" class="xref page">Clint Settings</a> page.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <i class="fa icon-note" title="Note"></i> </td> <td class="content"> <code>Cluster.connect</code> returns a <code>Try[Cluster]</code>, as the Scala client uses functional error handling and does not throw exceptions. You’ll see examples later of how to better handle a <code>Try</code>, but for simplicity here we’ll assume the operation succeeded and get the result as a <code>Cluster</code> using <code>.get</code>. </td> </tr> </table> </div> <div class="paragraph"> <p>For a deeper look at connection options, read <a href="../howtos/managing-connections.html" class="xref page">Managing Connections</a>.</p> </div> <div class="admonitionblock tip"> <table> <tr> <td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td> <td class="content"> The connection code for getting started uses the Administrator password that you were given during set up. In any production app you should create a role restricted to the permissions needed for your app — more on this in <a href="../concept-docs/best-practices.html#roles-and-rbac" class="xref page">the Security documentation</a>. </td> </tr> </table> </div> <div class="sect2"> <h3 id="opening-a-bucket"><a class="anchor" href="#opening-a-bucket"></a>Opening a Bucket</h3> <div class="paragraph"> <p>Following successful authentication, open the bucket with:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L67-L68">val bucket = cluster.bucket(bucketName) bucket.waitUntilReady(30.seconds).get</code></pre> </div> </div> <div class="paragraph"> <p><code>waitUntilReady</code> is an optional call, but it is good practice to use it. Opening resources such as buckets is asynchronous — that is, the <code>cluster.bucket</code> call returns immediately and proceeds in the background. <code>waitUntilReady</code> ensures that the bucket resource is fully loaded before proceeding. If not present, then the first key-value (KV) operation on the bucket will wait for it to be ready. As with the earlier <code>Cluster.connect</code>, we use <code>.get</code> on the result here for simplicity.</p> </div> <div class="paragraph"> <p><strong>Collections</strong> allow documents to be grouped by purpose or theme, according to a specified <strong>scope</strong> — see data modeling, <a href="#data-modeling">below</a>. Here we will use the <code>airport</code> collection within the <code>inventory</code> scope from <code>travel-sample</code> bucket as an example.</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L72">val collection = bucket.scope("inventory").collection("airport")</code></pre> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="create-read-update-delete"><a class="anchor" href="#create-read-update-delete"></a>Create, Read, Update, Delete</h2> <div class="sectionbody"> <div class="paragraph"> <p>Couchbase documents are organized into buckets, scopes, and collections. <a href="https://en.wikipedia.org/wiki/CRUD" target="_blank" rel="noopener">CRUD operations</a> — Create, Read, Update, Delete — can be performed upon documents in a collection.</p> </div> <div class="sect2"> <h3 id="json"><a class="anchor" href="#json"></a>JSON</h3> <div class="paragraph"> <p>We’ll create a snippet of JSON to work with, using the client’s own JSON library, but you can read about the Scala SDK’s support for other JSON libraries on the <a href="../howtos/json.html" class="xref page">JSON Libraries</a> page.</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L76">val json = JsonObject("status" -> "awesome")</code></pre> </div> </div> </div> <div class="sect2"> <h3 id="insert-create-and-upsert"><a class="anchor" href="#insert-create-and-upsert"></a>Insert (Create) and Upsert</h3> <div class="paragraph"> <p><code>insert</code> and <code>upsert</code> will both create a new document. The difference between the two is that if a document with that key already exists, the <code>insert</code> operation will fail, while the <code>upsert</code> operation will succeed, replacing the content.</p> </div> <div class="paragraph"> <p>We need to provide a unique ID as the key, and we’ll use a UUID here:</p> </div> <div class="listingblock"> <div class="title">Creating a new document</div> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L80-L84">val docId = UUID.randomUUID().toString collection.upsert(docId, json) match { case Success(result) => case Failure(exception) => println("Error: " + exception) }</code></pre> </div> </div> </div> <div class="sect2"> <h3 id="get-read"><a class="anchor" href="#get-read"></a>Get (Read)</h3> <div class="paragraph"> <p>The <code>get</code> method reads a document from a collection.</p> </div> <div class="paragraph"> <p>As mentioned above, the Scala SDK will not throw exceptions. Instead, methods that can error — such as the <code>upsert</code> above — will return a Scala <code>Try</code> result, which can either be a <code>Success</code> containing the result, or a <code>Failure</code> containing a <em>Throwable</em> exception. The easiest way to handle a single operation is with pattern matching, as shown above.</p> </div> <div class="paragraph"> <p>Now let’s get the data back (this example will look a little messy due the nested handling of multiple <code>Try</code> results, but we’ll see how to clean it up shortly):</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L88-L102">// Get a document collection.get(docId) match { case Success(result) => // Convert the content to a JsonObjectSafe result.contentAs[JsonObjectSafe] match { case Success(json) => // Pull out the JSON's status field, if it exists json.str("status") match { case Success(hello) => println(s"Couchbase is $hello") case _ => println("Field 'status' did not exist") } case Failure(err) => println("Error decoding result: " + err) } case Failure(err) => println("Error getting document: " + err) }</code></pre> </div> </div> <div class="paragraph"> <p>Here we’re fetching the value for the key <code>docId</code>, converting that value to a <code>JsonObjectSafe</code> (a simple wrapper around <code>JsonObject</code> that returns <code>Try</code> results — see <a href="../howtos/json.html#error-handling-and-jsonobjectsafe" class="xref page">JsonObjectSafe</a> for details), and then accessing the value of the <strong>status</strong> key as a String.</p> </div> <div class="sect3"> <h4 id="better-error-handling"><a class="anchor" href="#better-error-handling"></a>Better Error Handling</h4> <div class="paragraph"> <p>All three of these operations could fail, so there’s quite a lot of error handling code here to do something quite simple. One way to improve on this is by using <code>flatMap</code>, like this:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L122-L130">val result: Try[String] = collection .get(docId) .flatMap(_.contentAs[JsonObjectSafe]) .flatMap(_.str("status")) result match { case Success(status) => println(s"Couchbase is $status") case Failure(err) => println("Error: " + err) }</code></pre> </div> </div> <div class="paragraph"> <p>Alternatively, you can use a for-comprehension, like so:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L107-L116">val result: Try[String] = for { result <- collection.get(docId) json <- result.contentAs[JsonObjectSafe] status <- json.str("status") } yield status result match { case Success(status) => println(s"Couchbase is $status") case Failure(err) => println("Error: " + err) }</code></pre> </div> </div> <div class="paragraph"> <p>Either of these methods will stop on the first failed operation. So the final returned <code>Try</code> contains either a) <code>Success</code> and the result of the final operation, indicating that everything was successful, or b) <code>Failure</code> with the error returned by the first failing operation.</p> </div> </div> </div> <div class="sect2"> <h3 id="replace-update-and-overloads"><a class="anchor" href="#replace-update-and-overloads"></a>Replace (Update) and Overloads</h3> <div class="paragraph"> <p>You’ll notice that most operations in the Scala SDK have two overloads. One will take an Options builder, which provides all possible options that operation takes. For instance:</p> </div> <div class="listingblock"> <div class="title">The replace method updates the value of an existing document</div> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L136-L145">collection.replace( docId, json, ReplaceOptions() .expiry(10.seconds) .durability(Durability.Majority) ) match { case Success(status) => case Failure(err) => println("Error: " + err) }</code></pre> </div> </div> <div class="paragraph"> <p>These options blocks are implemented as Scala case classes: they are immutable data objects that return a copy of themselves on each change.</p> </div> <div class="paragraph"> <p>The other overload is provided purely for convenience. It takes named arguments instead of an Options object, and provides only the most commonly used options:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/Cloud.scala#L151-L154">collection.replace(docId, json, durability = Durability.Majority) match { case Success(status) => case Failure(err) => println("Error: " + err) }</code></pre> </div> </div> <div class="admonitionblock caution"> <table> <tr> <td class="icon"> <i class="fa icon-caution" title="Caution"></i> </td> <td class="content"> When you replace a document, it’s usually good practice to use <a href="../howtos/kv-operations.html#optimistic-locking" class="xref page">optimistic locking</a>. Otherwise, changes might get lost if two people change the same document at the same time. </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="remove-delete"><a class="anchor" href="#remove-delete"></a>Remove (Delete)</h3> <div class="paragraph"> <p>The remove method deletes a document from a collection:</p> </div> <div class="listingblock"> <div class="content"> <pre class="highlightjs highlight"><code class="language-scala hljs" data-lang="scala" data-source-url="https://github.com/couchbase/docs-sdk-scala/blob/612e5330523273e0366fefbf2c4a510267c7c1db/modules/devguide/examples/scala/KvOperations.scala#L317-L322">collection.remove("document-key") match { case Success(result) => println("Document removed successfully") case Failure(err: DocumentNotFoundException) => println("The document does not exist") case Failure(err) => println("Error: " + err) }</code></pre> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="data-modeling"><a class="anchor" href="#data-modeling"></a>Data Modeling</h2> <div class="sectionbody"> <div class="paragraph"> <p>Documents are organized into collections — collections of documents that belong together. You get to decide what it means to "belong." Developers usually put documents of the same type in the same collection.</p> </div> <div class="paragraph"> <p>For example, imagine you have two types of documents: customers and invoices. You could put the customer documents in a collection called <code>customers</code>, and the invoice documents in a collection called <code>invoices</code>.</p> </div> <div class="paragraph"> <p>Each document belongs to exactly one collection. A document’s ID is unique <em>within</em> the collection.</p> </div> <div class="paragraph"> <p>Different scopes can hold collections with different names. There is no relationship between collections in different scopes. Each collection belongs to just one scope and a collection’s name is unique within the scope.</p> </div> <div class="paragraph"> <p>More details can be found on the <a href="../concept-docs/data-model.html" class="xref page">Data Model page</a>.</p> </div> </div> </div> <div class="sect1"> <h2 id="what-next"><a class="anchor" href="#what-next"></a>What Next?</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="help-and-troubleshooting"><a class="anchor" href="#help-and-troubleshooting"></a>Help and Troubleshooting</h3> <div class="ulist"> <ul> <li> <p><a href="../howtos/troubleshooting-cloud-connections.html" class="xref page">Troubleshooting common network problems</a>.</p> </li> <li> <p><a href="https://www.couchbase.com/forums/c/scala-sdk/37">Help forum</a>.</p> </li> <li> <p><a href="https://discord.com/channels/915294689681362954/1217642561645318194">Discord channel</a>.</p> </li> <li> <p>Read the <a href="../howtos/error-handling.html" class="xref page">error handling page</a>.</p> </li> <li> <p><a href="../../../cloud/get-started/capella-iq/get-started-with-iq.html#generate-sdk-code-preview" class="xref page">Get help from Couchbase iQ</a>.</p> </li> </ul> </div> </div> <div class="sect2"> <h3 id="next-steps"><a class="anchor" href="#next-steps"></a>Next Steps</h3> <div class="ulist"> <ul> <li> <p><a href="../concept-docs/data-durability-acid-transactions.html" class="xref page">Learn more about the Data Service</a>.</p> </li> <li> <p><a href="../concept-docs/querying-your-data.html" class="xref page">Discover SQL++</a> — our SQL-family querying language.</p> </li> <li> <p>Explore some of the <a href="../project-docs/third-party-integrations.html" class="xref page">third party integrations</a> with Couchbase and the Scala SDK, across the Scala ecosystem.</p> </li> </ul> </div> </div> </div> </div> </article> </main> </div> <footer class="footer"> <div class="container"> <div class="footer-links"> <div class="col"> <div class="footer-logo"> <a href="https://www.couchbase.com" class="icon"> <img src="../../../_/img/couchbase-logo.svg" alt="Couchbase"> </a> </div> </div> <div class="col"> <ul> <li><a href="https://docs.couchbase.com" target="_blank" rel="noopener">Documentation</a></li> <li><a href="https://forums.couchbase.com" target="_blank" rel="noopener">Forums</a></li> <li><a href="https://support.couchbase.com" target="_blank" rel="noopener">Support</a></li> </ul> </div> <div class="col"> <ul> <li><a href="https://developer.couchbase.com" target="_blank" rel="noopener">Developer Portal</a></li> <li><a href="https://blog.couchbase.com" target="_blank" rel="noopener">Blog</a></li> <li><a href="https://www.couchbase.com/resources">Resources</a></li> </ul> </div> <div class="col"> <ul> <li><a href="https://www.couchbase.com/get-started-developing-nosql">Get Started</a></li> <li><a href="https://www.couchbase.com/downloads">Downloads</a></li> <li><a href="https://learn.couchbase.com/store?utf8=%E2%9C%93&ss=1&ct=78327&commit=Filter" target="_blank" rel="noopener">Training</a></li> </ul> </div> <div class="col"> <ul class="social-icons"> <li> <svg width="14" height="14" viewBox="0 0 32.1 26.1"> <path id="twitter" class="cls-1" d="M32,7.1a11.836,11.836,0,0,1-3.8,1,6.462,6.462,0,0,0,2.9-3.6,12.606,12.606,0,0,1-4.2,1.6A6.492,6.492,0,0,0,22.1,4a6.594,6.594,0,0,0-6.6,6.6,7.719,7.719,0,0,0,.2,1.5A18.458,18.458,0,0,1,2.2,5.2a6.294,6.294,0,0,0-.9,3.3A6.765,6.765,0,0,0,4.2,14a6.109,6.109,0,0,1-3-.8v.1a6.543,6.543,0,0,0,5.3,6.4,4.678,4.678,0,0,1-1.7.2,4.869,4.869,0,0,1-1.2-.1,6.679,6.679,0,0,0,6.1,4.6,12.917,12.917,0,0,1-8.2,2.8,9.151,9.151,0,0,1-1.6-.1,18.438,18.438,0,0,0,10.1,3c12.1,0,18.7-10,18.7-18.7v-.8A13.336,13.336,0,0,0,32,7.2Z" transform="translate(0.1 -4)"/></svg> <a href="https://twitter.com/couchbase" class="icon"> Twitter </a> </li> <li> <svg width="14" height="14" viewBox="0 0 32 32"> <path id="linkedin" class="cls-1" d="M29,0H3A3.076,3.076,0,0,0,0,3V29a3.009,3.009,0,0,0,3,3H29a2.946,2.946,0,0,0,3-3V3A3.009,3.009,0,0,0,29,0ZM12,26H8V12h4ZM10,10a2,2,0,1,1,2-2A2.006,2.006,0,0,1,10,10ZM26,26H22V18a2,2,0,0,0-4,0v8H14V12h4v2.5c.8-1.1,2.1-2.5,3.5-2.5A4.736,4.736,0,0,1,26,17Z"/></svg> <a href="https://www.linkedin.com/company/couchbase" class="icon"> Linkedin </a> </li> <li> <svg width="14" height="14" viewBox="0 0 32 32"> <path id="facebook" class="cls-1" d="M29,0H3A2.652,2.652,0,0,0,0,3V29a2.652,2.652,0,0,0,3,3H16V18H12V14h4V12a6.452,6.452,0,0,1,6-6h4v4H22a2.151,2.151,0,0,0-2,2v2h6l-1,4H20V32h9a2.652,2.652,0,0,0,3-3V3A2.652,2.652,0,0,0,29,0Z"/></svg> <a href="https://www.facebook.com/Couchbase" class="icon"> Facebook </a> </li> </ul> </div> </div> <div class="footer-terms"> <div class="footer-terms-copyright"> <span>漏 2024 Couchbase and the Couchbase logo are registered trademarks of Couchbase, Inc. All third party trademarks (including logos and icons) referenced by Couchbase, Inc. remain the property of their respective owners. </span> </div> <div class="footer-terms-links"> <a href="https://www.couchbase.com/terms-of-use">Terms of Use</a> <a href="https://www.couchbase.com/privacy-policy">Privacy Policy</a> <a href="https://www.couchbase.com/cookie-policy">Cookie Policy</a> <a href="https://www.couchbase.com/support-policy">Support Policy</a> <a href="https://info.couchbase.com/unsubscribe-or-manage-preferences.html" target="_blank" rel="noopener">Marketing Preference Center</a> </div> </div> </div> </footer> <script src="../../../_/js/site-navigation-data.js"></script> <script id="page-navigation-group" type="application/json"> {"title":"Couchbase SDKs","components":["dotnet-sdk","c-sdk","cxx-sdk","go-sdk","java-sdk","kotlin-sdk","nodejs-sdk","php-sdk","python-sdk","ruby-sdk","scala-sdk","elasticsearch-connector","kafka-connector","spark-connector","tableau-connector","power-bi-connector","sdk-extensions"],"url":"/home/sdk.html","latestVersions":{"dotnet-sdk":"3.6","c-sdk":"3.3","cxx-sdk":"1.0","go-sdk":"2.9","java-sdk":"3.7","kotlin-sdk":"1.4","nodejs-sdk":"4.4","php-sdk":"4.2","python-sdk":"4.3","ruby-sdk":"3.5","scala-sdk":"1.7","elasticsearch-connector":"4.4","kafka-connector":"4.2","spark-connector":"3.5","tableau-connector":"1.1","power-bi-connector":"1.0","sdk-extensions":"master"}} </script> <template id="run-code-panel"> <div class="action-panel"> <form class="action-panel-control" method="POST" action="https://couchbase.live/run" target="run-code-output"> <input type="hidden" name="lang"> <input type="hidden" name="code"> <input type="hidden" name="from" value="docs"> <div class="controls"> <button class="control-button rerun" type="submit"><i class="fas fa-redo"></i></button> <span class="shell-name control-label">Output</span> <button class="control-button close"><i class="fas fa-times"></i> Close</button> </div> </form> <iframe class="run-code-output" name="run-code-output"></iframe> </div> </template> <script id="site-script" src="../../../_/js/vendor/chatbox-ui.js"></script> <script id="site-script" src="../../../_/js/site.js"></script> <script async src="../../../_/js/vendor/tabs.js" data-sync-storage-key="preferred-tab"></script> <script defer src="../../../_/js/vendor/fontawesome-icon-defs.js"></script> <script defer src="../../../_/js/vendor/fontawesome.js" data-search-pseudo-elements="true"></script> <script async src="../../../_/js/vendor/highlight.js"></script> <script async id="search-script" src="../../../_/js/vendor/docsearch.js" data-app-id="NI1G57N08Q" data-api-key="d3eff3e8bcc0860b8ceae87360a47d54" data-index-name="prod_docs_couchbase" data-stylesheet="../../../_/css/vendor/docsearch.css"></script> <script async id="feedback-script" src="../../../_/js/vendor/feedback.js?v=1" data-collector-id="709818cb"></script> </body> </html>