diff --git a/modules/howtos/examples/ProvisioningResourcesBuckets.csx b/modules/howtos/examples/ProvisioningResourcesBuckets.csx new file mode 100644 index 00000000..6b3c4a53 --- /dev/null +++ b/modules/howtos/examples/ProvisioningResourcesBuckets.csx @@ -0,0 +1,65 @@ +// Run this using dotnet-script: https://github.com/filipw/dotnet-script +// +// dotnet script ProvisioningResourcesBuckets.csx +// + +#r "nuget: CouchbaseNetClient, 3.3.0" + +using System; +using System.Threading.Tasks; +using Couchbase; +using Couchbase.Management.Buckets; + +await new ProvisioningResourcesBuckets().ExampleAsync(); + +public class ProvisioningResourcesBuckets +{ + public async Task ExampleAsync() + { + // tag::creatingBucketMgr[] + var cluster = await Cluster.ConnectAsync("couchbase://localhost", "Administrator", "password"); + var bucketMgr = cluster.Buckets; + // end::creatingBucketMgr[] + + { + Console.WriteLine("[createBucket]"); + // tag::createBucket[] + await bucketMgr.CreateBucketAsync( + new BucketSettings{ + Name = "hello", + FlushEnabled = false, + ReplicaIndexes = true, + RamQuotaMB = 150, + NumReplicas = 1, + BucketType = BucketType.Couchbase, + ConflictResolutionType = ConflictResolutionType.SequenceNumber + } + ); + // end::createBucket[] + } + + { + Console.WriteLine("[updateBucket]"); + // tag::updateBucket[] + var settings = await bucketMgr.GetBucketAsync("hello"); + settings.FlushEnabled = true; + + await bucketMgr.UpdateBucketAsync(settings); + // end::updateBucket[] + } + + { + Console.WriteLine("[flushBucket]"); + // tag::flushBucket[] + await bucketMgr.FlushBucketAsync("hello"); + // end::flushBucket[] + } + + { + Console.WriteLine("[removeBucket]"); + // tag::removeBucket[] + await bucketMgr.DropBucketAsync("hello"); + // end::removeBucket[] + } + } +} diff --git a/modules/howtos/examples/ProvisioningResourcesViews.csx b/modules/howtos/examples/ProvisioningResourcesViews.csx new file mode 100644 index 00000000..3ae08c8c --- /dev/null +++ b/modules/howtos/examples/ProvisioningResourcesViews.csx @@ -0,0 +1,69 @@ +// Run this using dotnet-script: https://github.com/filipw/dotnet-script +// +// dotnet script ProvisioningResourcesViews.csx +// + +#r "nuget: CouchbaseNetClient, 3.3.0" + +using System; +using System.Threading.Tasks; +using Couchbase; +using Couchbase.Views; +using Couchbase.Management.Views; + +await new ProvisioningResourcesViews().ExampleAsync(); + +public class ProvisioningResourcesViews +{ + public async Task ExampleAsync() + { + // tag::viewmgr[] + var cluster = await Cluster.ConnectAsync("couchbase://localhost", "Administrator", "password"); + var bucket = await cluster.BucketAsync("travel-sample"); + var viewMgr = bucket.ViewIndexes; + // end::viewmgr[] + + { + Console.WriteLine("[createView]"); + // tag::createView[] + var views = new Dictionary(); + views.Add( + "by_country", + new View{ Map = "function (doc, meta) { if (doc.type == 'landmark') { emit([doc.country, doc.city], null); } }" } + ); + views.Add( + "by_activity", + new View{ Map="function (doc, meta) { if (doc.type == 'landmark') { emit([doc.country, doc.city], null); } }", + Reduce="_count" } + ); + + var designDocument = new DesignDocument { Name = "landmarks", Views = views }; + await viewMgr.UpsertDesignDocumentAsync(designDocument, DesignDocumentNamespace.Development); + // end::createView[] + } + + { + Console.WriteLine("[getView]"); + // tag::getView[] + var designDocument = await viewMgr.GetDesignDocumentAsync("landmarks", DesignDocumentNamespace.Development); + Console.WriteLine($"Design Document: {designDocument.Name}"); + // end::getView[] + } + + + { + Console.WriteLine("[publishView]"); + // tag::publishView[] + await viewMgr.PublishDesignDocumentAsync("landmarks"); + // end::publishView[] + } + + { + Console.WriteLine("[removeView]"); + // tag::removeView[] + await viewMgr.DropDesignDocumentAsync("landmarks", DesignDocumentNamespace.Production); + // end::removeView[] + } + + } +} diff --git a/modules/howtos/examples/QueryIndexManagerExample.csx b/modules/howtos/examples/QueryIndexManagerExample.csx new file mode 100644 index 00000000..b0ebd708 --- /dev/null +++ b/modules/howtos/examples/QueryIndexManagerExample.csx @@ -0,0 +1,123 @@ +// Run this using dotnet-script: https://github.com/filipw/dotnet-script +// +// dotnet script QueryIndexManagerExample.csx +// + +#r "nuget: CouchbaseNetClient, 3.3.0" + +using System; +using System.Threading.Tasks; +using Couchbase; +using Couchbase.Management.Query; +using Couchbase.Core.Exceptions; + +await new QueryIndexManagerExample().ExampleAsync(); + +public class QueryIndexManagerExample +{ + public async Task ExampleAsync() + { + // tag::creating-index-mgr[] + var cluster = await Cluster.ConnectAsync("couchbase://localhost", "Administrator", "password"); + var queryIndexMgr = cluster.QueryIndexes; + // end::creating-index-mgr[] + + { + Console.WriteLine("[primary]"); + // tag::primary[] + await queryIndexMgr.CreatePrimaryIndexAsync( + "travel-sample", + new CreatePrimaryQueryIndexOptions() + .ScopeName("tenant_agent_01") + .CollectionName("users") + // Set this if you wish to use a custom name + // .IndexName("custom_name") + .IgnoreIfExists(true) + ); + // end::primary[] + } + + { + Console.WriteLine("[secondary]"); + // tag::secondary[] + try + { + await queryIndexMgr.CreateIndexAsync( + "travel-sample", + "tenant_agent_01_users_email", + new[] { "preferred_email" }, + new CreateQueryIndexOptions() + .ScopeName("tenant_agent_01") + .CollectionName("users") + ); + } + catch (IndexExistsException) + { + Console.WriteLine("Index already exists!"); + } + // end::secondary[] + } + + { + Console.WriteLine("[defer-indexes]"); + // tag::defer-indexes[] + try + { + // Create a deferred index + await queryIndexMgr.CreateIndexAsync( + "travel-sample", + "tenant_agent_01_users_phone", + new[] { "preferred_phone" }, + new CreateQueryIndexOptions() + .ScopeName("tenant_agent_01") + .CollectionName("users") + .Deferred(true) + ); + + // Build any deferred indexes within `travel-sample`.tenant_agent_01.users + await queryIndexMgr.BuildDeferredIndexesAsync( + "travel-sample", + new BuildDeferredQueryIndexOptions() + .ScopeName("tenant_agent_01") + .CollectionName("users") + ); + + // Wait for indexes to come online + await queryIndexMgr.WatchIndexesAsync( + "travel-sample", + new[] { "tenant_agent_01_users_phone" }, + new WatchQueryIndexOptions() + .ScopeName("users") + .CollectionName("tenant_agent_01") + ); + } + catch (IndexExistsException) + { + Console.WriteLine("Index already exists!"); + } + // end::defer-indexes[] + } + + { + Console.WriteLine("[drop-primary-or-secondary-index]"); + // tag::drop-primary-or-secondary-index[] + // Drop primary index + await queryIndexMgr.DropPrimaryIndexAsync( + "travel-sample", + new DropPrimaryQueryIndexOptions() + .ScopeName("tenant_agent_01") + .CollectionName("users") + ); + + // Drop secondary index + await queryIndexMgr.DropIndexAsync( + "travel-sample", + "tenant_agent_01_users_email", + new DropQueryIndexOptions() + .ScopeName("tenant_agent_01") + .CollectionName("users") + ); + // end::drop-primary-or-secondary-index[] + } + } +} diff --git a/modules/howtos/pages/provisioning-cluster-resources.adoc b/modules/howtos/pages/provisioning-cluster-resources.adoc index 06f00e71..cce10130 100644 --- a/modules/howtos/pages/provisioning-cluster-resources.adoc +++ b/modules/howtos/pages/provisioning-cluster-resources.adoc @@ -2,107 +2,113 @@ :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[IBucketManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.Cluster.html#Couchbase_Cluster_Buckets[`Cluster.Buckets`]] +:user-api-reference: pass:q[IUserManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.Cluster.html#Couchbase_Cluster_Users[`Cluster.Users`]] +:query-api-reference: pass:q[IQueryIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.Cluster.html#Couchbase_Cluster_QueryIndexes[`Cluster.QueryIndexes`]] +:analytics-api-reference: pass:q[IAnalyticsIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.Cluster.html#Couchbase_Cluster_AnalyticsIndexes[`Cluster.AnalyticsIndexes`]] +:search-api-reference: pass:q[ISearchIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.Cluster.html#Couchbase_Cluster_SearchIndexes[`Cluster.SearchIndexes`]] +:collection-api-reference: pass:q[ICouchbaseCollectionManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.IBucket.html#Couchbase_IBucket_Collections[`Bucket.Collections`]] +:view-api-reference: pass:q[IViewIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.IBucket.html#Couchbase_IBucket_ViewIndexes[`Bucket.ViewIndexes`]] + +// one-view-update-warning common partial +:upsertDesignDocument: pass:q[`UpsertDesignDocumentAsync` method] +:getDesignDocument: pass:q[`GetDesignDocumentAsync`] include::project-docs:partial$attributes.adoc[] [abstract] {description} -Common use cases are outlined here, less common use cases are covered in the https://pkg.go.dev/github.com/couchbase/gocb/v2?tab=doc[API docs]. +Common use cases are outlined here, less common use cases are covered in the https://docs.couchbase.com/sdk-api/couchbase-net-client/api/index.html[API docs]. include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=management-intro] The .NET SDK also comes with some convenience functionality for common Couchbase management requests. -//// + Management operations in the SDK may be performed through several interfaces depending on the object: -* BucketManager -- ` IBucketManager` -* UserManager -- `IUserManager` -* QueryIndexManager -- `IQueryIndexManager` -* AnalyticsIndexManager -- `IAnalyticsIndexManager` -* SearchIndexManager -- `ISearchIndexManager` -* CollectionManager -- `ICouchbaseCollectionManager` -* ViewIndexManager -- `IViewIndexManager`. -//// -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. +* {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. -== Creating and Removing Buckets -The `ClusterManager` interface may be used to create and delete buckets from the Couchbase cluster. -It is instantiated through the `Cluster.Buckets()` method. -Refer to the https://docs.couchbase.com/sdk-api/couchbase-net-client/html/M_Couchbase_Cluster_BucketAsync.htm[API documentation] for details. +== Bucket Management -//// -[source,golang,indent=0] +The `IBucketManager` interface may be used to create and delete buckets from the Couchbase cluster. +It is referenced via the `Cluster.Buckets` property. + +[source,golang] ---- -include::devguide:example$go/provisioning-resources-buckets.go[tag=creatingbucketmgr] +include::example$/ProvisioningResourcesBuckets.csx[tag=creatingBucketMgr,indent=0] ---- -//// -The `CreateBucketSettings` and `BucketSettings` structs are used for creating and updating buckets, `BucketSettings` is also used for exposing information about existing buckets. +The `BucketSettings` object is used for creating or updating buckets, and for exposing information about existing buckets. include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=update-bucket-warning] -//// Here is the list of parameters available: |==== | Name | Description | Can be updated | `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 -| `ReplicaIndexDisabled boolean` | Whether or not to replicate indexes. | false -| `RAMQuotaMB uint64` | How much memory should each node use for the bucket, required for creation. | true -| `NumReplicas uint32` | The number of replicas to use for the bucket. | 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 Int64` | How much memory should each node use for the bucket, required for creation. | true +| `NumReplicas Int32` | The number of replicas to use for the bucket. | true | `BucketType BucketType` | The type of the bucket, required for creation. | false -| `EvictionPolicy EvictionPolicyType` | The type of the eviction to use for the bucket, defaults to `valueOnly`. | true (note: changing will cause the bucket to restart causing temporary inaccessibility) -| `MaxTTL time.Duration` | The default maximum time-to-live to apply to documents in the bucket. (note: This option is only available for Couchbase and Ephemeral buckets in Couchbase Enterprise Edition.) | true +| `EvictionPolicy EvictionPolicyType` | The type of the eviction to use for the bucket, defaults to `ValueOnly`. | true (note: changing will cause the bucket to restart causing temporary inaccessibility) +| `MaxTTL Int32` | The default maximum time-to-live to apply to documents in the bucket. (note: This option is only available for Couchbase and Ephemeral buckets in Couchbase Enterprise Edition.) | true | `CompressionMode CompressionMode` | The compression mode to apply to documents in the bucket. (note: This option is only available for Couchbase and Ephemeral buckets in Couchbase Enterprise Edition.) | true -| `ConflictResolutionType ConflictResolutionType` | The conflict resolution type to apply to conflicts on the bucket, defaults to `seqno` | false +| `ConflictResolutionType ConflictResolutionType` | The conflict resolution type to apply to conflicts on the bucket, defaults to `SequenceNumber` | false |==== The following example creates a "hello" bucket: -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-buckets.go[tag=createBucket] +include::example$ProvisioningResourcesBuckets.csx[tag=createBucket,indent=0] ---- We can now get this bucket and update it to enable Flush: -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-buckets.go[tag=updateBucket] +include::example$ProvisioningResourcesBuckets.csx[tag=updateBucket,indent=0] ---- Once you no longer need to use the bucket, you can remove it: -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-buckets.go[tag=removeBucket] +include::example$ProvisioningResourcesBuckets.csx[tag=removeBucket,indent=0] ---- -//// -[#go-flushing] -== Flushing Buckets +=== Flushing Buckets include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=flush-intro] You can flush a bucket in the SDK by using `FlushBucketAsync()`. -//// -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-buckets.go[tag=flushBucket] +include::example$ProvisioningResourcesBuckets.csx[tag=flushBucket,indent=0] ---- -The `Flush` operation may fail if the bucket does not have flush enabled, in that case it will return an `ErrBucketNotFlushable`. -//// +The `Flush` operation may fail if the bucket does not have flush enabled, in that case it will return a `BucketIsNotFlushableException`. == Collection Management The CollectionManager interface may be used to create and delete scopes and collections from the Couchbase cluster. -It is instantiated through the `Bucket.collections()` method. -Refer to the https://docs.couchbase.com/sdk-api/couchbase-net-client/html/N_Couchbase_Management_Collections.htm[`CollectionManager` API documentation] +It can be referenced via the `Bucket.Collections` property. +Refer to the https://docs.couchbase.com/sdk-api/couchbase-net-client/api/Couchbase.Management.Collections.ICouchbaseCollectionManager.html[`CollectionManager` API documentation] for further details. [source,csharp] @@ -131,6 +137,7 @@ Finally, you can drop unneeded collections and scopes: include::example$Couchbase.Examples/CollectionManager.cs[tag=drop-collection,indent=0] include::example$Couchbase.Examples/CollectionManager.cs[tag=drop-scope,indent=0] + ---- Note that the most minimal permissions to create and drop a Scope or Collection is @@ -144,8 +151,6 @@ You can create users with the appropriate RBAC programmatically: include::example$Couchbase.Examples/CollectionManager.cs[tag=scopeAdmin, indent=0] ---- -=== Listing the Scopes and Collections available - You can enumerate Scopes and Collections using the `CollectionManager` and the properties of the `ScopeSpec` and `CollectionSpec` objects retrieved. @@ -155,19 +160,70 @@ the `CollectionManager` and the properties of the include::example$Couchbase.Examples/CollectionManager.cs[tag=listing-scope-collection,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 `IQueryIndexManager` interface contains the means for managing indexes used for queries. +It can be referenced through the `Cluster.QueryIndexes` property. + +[source,csharp] +---- +include::example$QueryIndexManagerExample.csx[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 `CreatePrimaryIndexAsync()` method. +Note that you cannot provide a named scope or collection separately, both must be set for the `IQueryIndexManager` to create an index on the relevant keyspace path. + +.Creating a primary index + +[source,csharp] +---- +include::example$QueryIndexManagerExample.csx[tag=primary,indent=0] +---- + +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 set an `IndexName` property in the `CreatePrimaryQueryIndexOptions` class. -* QueryIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/html/N_Couchbase_Management_Query.htm[`IQueryIndexManager`]; -* AnalyticsIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/html/N_Couchbase_Management_Analytics.htm[`IAnalyticsIndexManager`]; -* SearchIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/html/N_Couchbase_Management_Search.htm[`ISearchIndexManager`]; -* ViewIndexManager -- https://docs.couchbase.com/sdk-api/couchbase-net-client/html/N_Couchbase_Management_Views.htm[`IViewIndexManager`]. -//// +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. -// * Query +Creating a _secondary_ index follows a similar approach, with some minor differences: + +.Creating a secondary index + +[source,csharp] +---- +include::example$QueryIndexManagerExample.csx[tag=secondary,indent=0] +---- + +The `CreateIndexAsync()` 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 by passing some options. + +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,csharp] +---- +include::example$QueryIndexManagerExample.csx[tag=defer-indexes,indent=0] +---- + +To delete a query index you can use the `DropIndexAsync()` or `DropPrimaryIndexAsync()` methods. +Which one you use depends on the type of query index you wish to drop from the database. + +.Deleting an index + +[source,csharp] +---- +include::example$QueryIndexManagerExample.csx[tag=drop-primary-or-secondary-index,indent=0] +---- // * Search - note & link to FTS page & API? @@ -175,45 +231,43 @@ For those occasions when you do, please see the relevant API docs: include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=view-management] -In the SDK, design documents are represented by the `DesignDocument` and `View` structs. +In the SDK, design documents are represented by the `DesignDocument` and `View` classes. All operations on design documents are performed on the `ViewIndexManager` instance: -//// -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-views.go[tag=viewmgr] +include::example$ProvisioningResourcesViews.csx[tag=viewmgr,indent=0] ---- The following example upserts a design document with two views: -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-views.go[tag=createView] +include::example$ProvisioningResourcesViews.csx[tag=createView,indent=0] ---- include::{version-server}@sdk:shared:partial$flush-info-pars.adoc[tag=one-view-update-warning] -Note the use of `DesignDocumentNamespaceDevelopment`, the other option is `DesignDocumentNamespaceProduction`. +Note the use of `DesignDocumentNamespace.Development`, the other option is `DesignDocumentNamespace.Production`. This parameter specifies whether the design document should be created as development, or as production -- with the former running over only a small fraction of the documents. Now that we've created a design document we can fetch it: -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-views.go[tag=getView] +include::example$ProvisioningResourcesViews.csx[tag=getView,indent=0] ---- -We've created the design document using `DesignDocumentNamespaceDevelopment` and now want to push it to production, we can do this with: +We've created the design document using `DesignDocumentNamespace.Development` and now want to push it to production, we can do this with: -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-views.go[tag=publishView] +include::example$ProvisioningResourcesViews.csx[tag=publishView,indent=0] ---- To remove this design document: -[source,golang,indent=0] +[source,csharp] ---- -include::devguide:example$go/provisioning-resources-views.go[tag=removeView] +include::example$ProvisioningResourcesViews.csx[tag=removeView,indent=0] ---- -//// diff --git a/modules/project-docs/partials/attributes.adoc b/modules/project-docs/partials/attributes.adoc index acccd66c..3d50dda5 100644 --- a/modules/project-docs/partials/attributes.adoc +++ b/modules/project-docs/partials/attributes.adoc @@ -1,4 +1,4 @@ -:dotnet-api-link: http://docs.couchbase.com/sdk-api/couchbase-dotnet-client-3.2.4 -:dotnet-current-version: 3.2.4 -:version-server: 7.0 +:dotnet-api-link: http://docs.couchbase.com/sdk-api/couchbase-dotnet-client-3.3.0 +:dotnet-current-version: 3.3.0 +:version-server: 7.1 :name-sdk: .NET SDK