From af61c82ff4bbed1a305225bfadc3cc01828a7560 Mon Sep 17 00:00:00 2001 From: Maria Shodunke Date: Thu, 28 Apr 2022 15:59:13 +0100 Subject: [PATCH 1/2] DOC-9567 - Add scoped index management examples - Use changes made in this sdk-common PR: couchbase/docs-sdk-common#47 - Add Index management examples with scopes and collections (new in 1.3) --- .../examples/QueryIndexManagerExample.scala | 129 ++++++++++++++++++ .../pages/provisioning-cluster-resources.adoc | 98 +++++++++++-- 2 files changed, 212 insertions(+), 15 deletions(-) create mode 100644 modules/howtos/examples/QueryIndexManagerExample.scala diff --git a/modules/howtos/examples/QueryIndexManagerExample.scala b/modules/howtos/examples/QueryIndexManagerExample.scala new file mode 100644 index 00000000..a7c4aef9 --- /dev/null +++ b/modules/howtos/examples/QueryIndexManagerExample.scala @@ -0,0 +1,129 @@ +import com.couchbase.client.core.error._ +import com.couchbase.client.scala.Cluster +import com.couchbase.client.scala.manager.query.QueryIndexManager + +import scala.util.{Failure, Success, Try} +import scala.concurrent.duration.Duration + +object QueryIndexManagerExample { + // tag::creating-index-mgr[] + val cluster = Cluster.connect("localhost", "Administrator", "password").get + val queryIndexMgr = cluster.queryIndexes + // end::creating-index-mgr[] + + def createPrimaryIndex(): Unit = { + println("[primary]") + // tag::primary[] + val result: Try[Unit] = queryIndexMgr.createPrimaryIndex( + "travel-sample", + // Set this if you wish to use a custom name + // indexName = Option("custom_name"), + scopeName = Option("tenant_agent_01"), + collectionName = Option("users"), + ignoreIfExists = true + ) + result match { + case Success(_) => + case Failure(err) => throw err + } + // end::primary[] + } + + def createIndex(): Unit = { + println("[secondary]") + // tag::secondary[] + val result: Try[Unit] = queryIndexMgr.createIndex( + "travel-sample", + "tenant_agent_01_users_email", + Array("preferred_email"), + scopeName = Option("tenant_agent_01"), + collectionName = Option("users") + ) + result match { + case Success(_) => + case Failure(err: IndexExistsException) => println("Index already exists!") + case Failure(err) => throw err + } + // end::secondary[] + } + + def deferAndWatchIndex(): Unit = { + println("[defer-indexes]") + // tag::defer-indexes[] + // Create a deferred index + var result: Try[Unit] = queryIndexMgr.createIndex( + "travel-sample", + "tenant_agent_01_users_phone", + Array("preferred_phone"), + scopeName = Option("tenant_agent_01"), + collectionName = Option("users"), + deferred = Option(true) + ) + result match { + case Success(_) => + case Failure(err: IndexExistsException) => println("Index already exists!") + case Failure(err) => throw err + } + + // Build any deferred indexes within `travel-sample`.tenant_agent_01.users + result = queryIndexMgr.buildDeferredIndexes( + "travel-sample", + scopeName = Option("tenant_agent_01"), + collectionName = Option("users") + ) + result match { + case Success(_) => + case Failure(err) => throw err + } + + // Wait for indexes to come online + result = queryIndexMgr.watchIndexes( + "travel-sample", + Array("tenant_agent_01_users_phone"), + Duration("30 seconds"), + scopeName = Option("tenant_agent_01"), + collectionName = Option("users") + ) + result match { + case Success(_) => + case Failure(err: IndexExistsException) => println("Index already exists!") + case Failure(err) => throw err + } + // end::defer-indexes[] + } + + def dropPrimaryAndSecondaryIndex(): Unit = { + println("[drop-primary-or-secondary-index]") + // tag::drop-primary-or-secondary-index[] + // Drop a primary index + var result: Try[Unit] = queryIndexMgr.dropPrimaryIndex( + "travel-sample", + scopeName = Option("tenant_agent_01"), + collectionName = Option("users") + ) + result match { + case Success(_) => + case Failure(err) => throw err + } + + // Drop a secondary index + result = queryIndexMgr.dropIndex( + "travel-sample", + "tenant_agent_01_users_email", + scopeName = Option("tenant_agent_01"), + collectionName = Option("users") + ) + result match { + case Success(_) => + case Failure(err) => throw err + } + // end::drop-primary-or-secondary-index[] + } + + def main(args: Array[String]): Unit = { + createPrimaryIndex() + createIndex() + deferAndWatchIndex() + dropPrimaryAndSecondaryIndex() + } +} diff --git a/modules/howtos/pages/provisioning-cluster-resources.adoc b/modules/howtos/pages/provisioning-cluster-resources.adoc index 14e4098c..4b5cb068 100644 --- a/modules/howtos/pages/provisioning-cluster-resources.adoc +++ b/modules/howtos/pages/provisioning-cluster-resources.adoc @@ -2,12 +2,26 @@ :description: Provisioning cluster resources is managed at the collection or bucket level, depending upon the service affected. :navtitle: Provisioning Cluster Resources :page-aliases: ROOT:managing-clusters +:page-toclevels: 2 + +// API refs +:bucket-api-reference: pass:q[BucketManager -- https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/Cluster.html#buckets:com.couchbase.client.scala.manager.bucket.BucketManager[`Cluster.buckets`]] +:user-api-reference: pass:q[UserManager -- https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/Cluster.html#users:com.couchbase.client.scala.manager.user.UserManager[`Cluster.users`]] +:query-api-reference: pass:q[QueryIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/Cluster.html#queryIndexes:com.couchbase.client.scala.manager.query.QueryIndexManager[`Cluster.queryIndexes`]] +:analytics-api-reference: pass:q[AnalyticsIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/Cluster.html#analyticsIndexes:com.couchbase.client.scala.manager.analytics.AnalyticsIndexManager[`Cluster.analyticsIndexes`]] +:search-api-reference: pass:q[SearchIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/Cluster.html#searchIndexes:com.couchbase.client.scala.manager.search.SearchIndexManager[`Cluster.searchIndexes`]] +:collection-api-reference: pass:q[CollectionManager -- https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/Bucket.html#collections:com.couchbase.client.scala.manager.collection.CollectionManager[`Bucket.collections`]] +:view-api-reference: pass:q[ ViewIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/Bucket.html#viewIndexes:com.couchbase.client.scala.manager.view.ViewIndexManager[`Bucket.viewIndexes`]] + +// one-view-update-warning common partial +:upsertDesignDocument: pass:q[`upsertDesignDocument` method] +:getDesignDocument: pass:q[`getDesignDocument`] include::project-docs:partial$attributes.adoc[] [abstract] {description} -Common use cases are outlined here, less common use cases are covered in the https://docs.couchbase.com/sdk-api/couchbase-scala-client-1.0.4/com/couchbase/client/scala/index.html[API docs]. +Common use cases are outlined here, less common use cases are covered in the https://docs.couchbase.com/sdk-api/couchbase-scala-client/com/couchbase/client/scala/index.html[API docs]. include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=management-intro] @@ -15,15 +29,17 @@ The Scala SDK also comes with some convenience functionality for common Couchbas Management operations in the SDK may be performed through several interfaces depending on the object: -[source,scala] ----- -include::example$ClusterResources.scala[tag=managers,indent=0] ----- +* {bucket-api-reference} +* {user-api-reference} +* {query-api-reference} +* {analytics-api-reference} +* {search-api-reference} +* {collection-api-reference} +* {view-api-reference} -NOTE: When using a Couchbase version earlier than 6.5, you must create a valid Bucket connection using `cluster.bucket(name)` before you can use cluster-level managers. +NOTE: When using a Couchbase version earlier than 6.5, you must create a valid Bucket connection using `Cluster.bucket(name)` before you can use cluster-level managers. - -== Creating and Removing Buckets +== Bucket Management The `BucketManager` interface may be used to create and delete buckets from the Couchbase cluster. @@ -40,7 +56,7 @@ The "Updatable" column indicates whether the parameter may only be specified whe | Name | Type | Description | Updatable | `name` | `String` | The name of the bucket, required for creation. | false -| `flushEnabled` | `boolean` | Enables flushing to be performed on this bucket (see the <> section below). | true +| `flushEnabled` | `boolean` | Enables flushing to be performed on this bucket (see the <> section below). | true | `replicaIndexes` | `boolean` | Whether or not to replicate indexes. | false | `ramQuotaMB` | `int` | How much memory should each node use for the bucket, required for creation. | true | `numReplicas` | `int` | The number of replicas to use for the bucket. | true @@ -72,8 +88,7 @@ Once you no longer need to use the bucket, you can remove it: include::example$ClusterResources.scala[tag=drop,indent=0] ---- -[#flushing] -== Flushing Buckets +=== Flushing Buckets include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=flush-intro] @@ -132,15 +147,68 @@ include::example$CollectionManagerExample.scala[tag=scopeAdmin, indent=0] == Index Management -In general,you will rarely need to work with Index Managers from the SDK. -For those occasions when you do, please see the relevant API docs: +include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=index-management-intro] + +=== QueryIndexManager + +The `QueryIndexManager` interface contains the means for managing indexes used for queries. + +It can be accessed via `Cluster.queryIndexes`. + +[source,scala] +---- +include::example$QueryIndexManagerExample.scala[tag=creating-index-mgr,indent=0] +---- + +include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=query-index-manager-intro] + +The example below shows how to create a simple primary index, restricted to a named scope and collection, by calling the `createPrimaryIndex()` method. +Note that you cannot provide a named scope or collection separately, both must be set for the `QueryIndexManager` to create an index on the relevant keyspace path. + +.Creating a primary index [source,scala] ---- -include::example$ClusterResources.scala[tag=index-managers,indent=0] +include::example$QueryIndexManagerExample.scala[tag=primary,indent=0] ---- -// * Query +When a primary index name is not specified, the SDK will create the index as `#primary` by default. +However, if you wish to provide a custom name, you can simply pass an `indexName` argument to `createPrimaryIndex()`. + +You may have noticed that the example also sets the `ignoreIfExists` boolean flag. +When set to `true`, this optional argument ensures that an error is not thrown if an index under the same name already exists. + +Creating a _secondary_ index follows a similar approach, with some minor differences: + +.Creating a secondary index + +[source,scala] +---- +include::example$QueryIndexManagerExample.scala[tag=secondary,indent=0] +---- + +The `createIndex()` method requires an index name to be provided, along with the fields to create the index on. +Like the _primary_ index, you can restrict a _secondary_ index to a named scope and collection. + +Indexes can easily take a long time to build if they contain a lot of documents. +In these situations, it is more ideal to build indexes in the background. +To achieve this we can use the `deferred` boolean option, and set it to `true`. + +.Deferring index creation + +[source,scala] +---- +include::example$QueryIndexManagerExample.scala[tag=defer-indexes,indent=0] +---- + +To delete a query index you can use the `dropIndex()` or `dropPrimaryIndex()` methods. +Which one you use depends on the type of query index you wish to drop from the database. + +.Deleting an index + +[source,scala] +---- +include::example$QueryIndexManagerExample.scala[tag=drop-primary-or-secondary-index,indent=0] +---- // * Search - note & link to FTS page & API? From 664ca7d63c0543c6f972da31748077f662e7ec80 Mon Sep 17 00:00:00 2001 From: Maria Shodunke Date: Thu, 28 Apr 2022 17:09:39 +0100 Subject: [PATCH 2/2] Fix indentation --- modules/howtos/examples/QueryIndexManagerExample.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/howtos/examples/QueryIndexManagerExample.scala b/modules/howtos/examples/QueryIndexManagerExample.scala index a7c4aef9..d957571a 100644 --- a/modules/howtos/examples/QueryIndexManagerExample.scala +++ b/modules/howtos/examples/QueryIndexManagerExample.scala @@ -109,7 +109,7 @@ object QueryIndexManagerExample { // Drop a secondary index result = queryIndexMgr.dropIndex( "travel-sample", - "tenant_agent_01_users_email", + "tenant_agent_01_users_email", scopeName = Option("tenant_agent_01"), collectionName = Option("users") )