{"id":2192,"date":"2016-03-10T21:51:31","date_gmt":"2016-03-10T21:51:30","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2192"},"modified":"2025-10-09T07:10:18","modified_gmt":"2025-10-09T14:10:18","slug":"developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/","title":{"rendered":"Developer Preview of new Sub-document API included w\/2.2.6 release of Couchbase .NET SDK"},"content":{"rendered":"<p><strong>Note: all examples can be found <a href=\"https:\/\/github.com\/couchbaselabs\/couchbase-net-examples\/tree\/master\/Src\/Couchbase.Examples.SubDocumentAPI\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/strong><\/p>\n<p>Today we are releasing a very special Developer Preview (DP) of a new feature in the upcoming release of Couchbase Server called <em>Sub-document<\/em>, along with our normal Couchbase Server .NET SDK 2.2.6! The Sub-document API is a new feature of Couchbase Server that is available in the Developer Preview of Couchbase Server 4.5.<\/p>\n<p>If you recall, in Couchbase all document mutations are atomic and involve the entire document. If you only want to change a single field and then do an update, the entire document in Couchbase server is copied over by the new revision. The problem with is that if the document is large or the network slow (or both), then a lot of resources are wasted sending data that hasn&#8217;t been modified. A better, more performant solution would be to just send the portion of the document or the value which has been mutated. Essentially, that is what you get with sub-document API; when you update an element or delete an element of a document, only the <i>path<\/i>\u00a0of the fragment to be mutated\u00a0is sent over the wire and only that part of the document is modified.<\/p>\n<p>There are several different operations that are supported by the API, from mutations on individual nested elements or <em>sub-<\/em>documents\u00a0to array and dictionary modifications. Counter operations are also supported, as are retrieval operations for embedded JSON fragments.<\/p>\n<p>The API Is exposed via a fluent interface which allows you append multiple operations and then executing them against the document atomically. There there are two different &#8220;builders&#8221;: a builder for mutation operations and a builder for reads or &#8220;lookups&#8221; and to check if an element exists at a given path.<\/p>\n<h2 id=\"important-use-sub-document-api-dp-at-you-own-risk-\">IMPORTANT: Sub-document API is a Developer Preview!!!<\/h2>\n<p>Please note that this is an early DP of the Sub-document API and has not gone through the usual checks and balances that are normal API&#8217;s go through before a release. Additionally, based on user feedback, the public interfaces may change in subsequent releases, therefore it is not suggested you use the Sub-document API in production&#8230;just yet. <strong><em>The rest of 2.2.6 has been tested, however, and is ready for production usage.<\/em><\/strong><\/p>\n<h3 id=\"prerequisite-couchbase-server-4-5-0-developer-preview\">Prerequisite: Couchbase Server 4.5.0 Developer Preview<\/h3>\n<p>In order to follow the examples below, you&#8217;ll need to download and install <a href=\"https:\/\/www.couchbase.com\/\">Couchbase Server 4.5 developer preview<\/a>. Go, do this now!<\/p>\n<h2 id=\"sub-document-api-dp-overview\">Sub-Document API DP Overview<\/h2>\n<p>The following examples will use a document with an id of &#8220;puppy&#8221; and will look like this:<\/p>\n<pre><code>  {\r\n  \"type\": \"dog\",\r\n  \"breed\": \"Pitbull\/Chihuahua\",\r\n  \"name\": \"Puppy\",\r\n  \"toys\": [\r\n    \"squeaker\",\r\n    \"ball\",\r\n    \"shoe\"\r\n  ],\r\n  \"owner\": {\r\n    \"type\": \"servant\",\r\n    \"name\": \"Don Knotts\",\r\n    \"age\": 63\r\n  },\r\n  \"attributes\": {\r\n    \"fleas\": true,\r\n    \"color\": \"white\",\r\n    \"eyeColor\": \"brown\",\r\n    \"age\": 5,\r\n    \"dirty\": true,\r\n    \"sex\": \"female\"\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>All of the examples are available on <a href=\"https:\/\/github.com\/couchbaselabs\/couchbase-net-examples\">Github <\/a>so you can clone the project and play around with the API.<\/p>\n<h3 id=\"mutateinbuilder-and-lookupinbuilder\">MutateInBuilder and LookupInBuilder<\/h3>\n<p>As mentioned previously, the Sub-document API offers two new Types that utilize a builder pattern via a fluent-interface for chaining together multiple operations on a document. Both objects are created by calling <code>MutateIn<\/code> or <code>LookupIn<\/code> on a <code>CouchbaseBucket<\/code> object and passing in the key or id of the document you are working against:<\/p>\n<pre><code>\/\/Initialize the cluster helper with the default settings - i.e. localhost\r\nClusterHelper.Initialize();\r\nvar bucket = ClusterHelper.GetBucket(\"default\");\r\n\r\n\/\/create a mutation builder for the document \"thekey\"\r\nvar mutate = bucket.MutateIn(\"thekey\");\r\n\r\n\/\/create a lookup builder for the document \"thekey2\"\r\nvar lookup = bucket.LookupIn(\"thekey2\");\r\n\r\nClusterHelper.Close();\r\n<\/code><\/pre>\n<p>Once you have the builder object, you can chain together a number of operations to execute against the document, for example:<\/p>\n<pre><code>var builder = bucket.LookupIn(id).\r\n            Get(\"type\").\r\n            Get(\"name\").\r\n            Get(\"owner\").\r\n            Exists(\"notfound\");\r\n<\/code><\/pre>\n<p>Then you can send all of the operations to the server in a single batch:<\/p>\n<pre><code>var fragment = builder.Execute();\r\n<\/code><\/pre>\n<p>And then check the result of one operation operation for the path <code>type<\/code>:<\/p>\n<pre><code>if (fragment.OpStatus(\"type\") == ResponseStatus.Success)\r\n{\r\n    string format = \"Path='{0}' Value='{1}'\";\r\n    Console.WriteLine(format, \"type\", fragment.Content(\"type\"));\r\n}\r\n<\/code><\/pre>\n<p>The IDocumentFragment<\/p>\n<table>\n<thead>\n<tr>\n<th>Name<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Content(&#8230;)<\/td>\n<td>Gets the content for a given path or index.<\/td>\n<\/tr>\n<tr>\n<td>Exists(&#8230;)<\/td>\n<td>Returns true if there is a result for a given path or index.<\/td>\n<\/tr>\n<tr>\n<td>Count()<\/td>\n<td>The count of current operations maintained by the builder.<\/td>\n<\/tr>\n<tr>\n<td>OpStatus(&#8230;)<\/td>\n<td>The <code>ResponseStatus<\/code> of an operation at a given index or path.<\/td>\n<\/tr>\n<tr>\n<td>Status<\/td>\n<td>The <code>ResponseStatus<\/code> for the entire multi-operation.<\/td>\n<\/tr>\n<tr>\n<td>Success<\/td>\n<td>True if the entire multi-operation succeeds.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Besides these properties or methods, there are all of the other properties inherited from <code>OperationResult<\/code> which is the standard response from a K\/V operation: Upsert, Remove, Replace, etc.<\/p>\n<h3 id=\"error-handling\">Error Handling<\/h3>\n<p>When sending multiple mutations,\u00a0if\u00a0one of them\u00a0fails, the entire multi-operation request fails, allowing transactional all-or-nothing semantics when performing mutations within a single document. When sending multiple lookups, some operations may succeed and some may fail, with the server attempting to return as many items as requested.\u00a0If the operations failed then\u00a0Status property will contain a top-level error response such as <code>SubDocMultiPathFailure,<\/code>\u00a0which\u00a0is an indication to dig deeper into the operation&#8217;s results to get the specific error. You can do this by iterating by calling the OpStatus method and passing either the index or the path:<\/p>\n<pre><code>var builder = bucket.LookupIn(id).\r\n            Get(\"type\").\r\n            Get(\"somepaththatdoesntexist\").\r\n            Get(\"owner\");\r\n\r\nvar fragment = builder.Execute();\r\nConsole.WriteLine(\"Generic error: {0}{1}Specific Error: {2}\", \r\n    fragment.Status, Environment.NewLine, fragment.OpStatus(1));\r\n\r\nConsole.WriteLine(\"Generic error: {0}{1}Specific Error: {2}\",\r\n    fragment.Status, Environment.NewLine, fragment.OpStatus(\"somepaththatdoesntexist\"));\r\n<\/code><\/pre>\n<p>In this case since the path didn&#8217;t exist within the document, the specific error returned was <code>SubDocPathNotFound<\/code>. There are many different combinations of errors depending upon the builder type and the condition for the error &#8211; this is a brief introduction and should be suitable for starting out with the API.<\/p>\n<h2 id=\"lookupinbuilder-examples\">LookupInBuilder Examples<\/h2>\n<p>The LookUpInBuilder supports two operations: fetching a value by path and checking for the existence of a value at a given path.<\/p>\n<h3 id=\"get-\">Get:<\/h3>\n<p>Let&#8217;s lookup the <code>owner<\/code> fragment by <code>path<\/code>:<\/p>\n<pre><code>var builder = bucket.LookupIn(id).\r\n            Get(\"owner\").\r\n            Execute();\r\n\r\nvar owner = builder.Content(\"owner\");\r\n<\/code><\/pre>\n<p>The output is:<\/p>\n<pre><code>{\r\n    \"type\": \"servant\",\r\n    \"name\": \"Don Knotts\",\r\n    \"age\": 63\r\n}\r\n<\/code><\/pre>\n<h3 id=\"exist-\">Exist:<\/h3>\n<p>Let&#8217;s check if the <code>owner<\/code> path exists:<\/p>\n<pre><code>var builder = bucket.LookupIn(id).\r\n            Exists(\"owner\").\r\n            Execute();\r\n\r\nvar found = builder.Content(\"owner\");\r\n<\/code><\/pre>\n<p>The output is <code>true<\/code>, the path <code>owner<\/code> does indeed exist within the document.<\/p>\n<h2 id=\"mutateinbuilder\">MutateInBuilder<\/h2>\n<p>The MutateInBuilder offers a number of methods supporting mutations on scalar values, dictionaries and arrays, along with support for atomic counter operations.<\/p>\n<h3 id=\"insert-\">Insert:<\/h3>\n<p>Insert adds a value to a dictionary optionally allowing for the containing element (the dictionary itself) to be added:<\/p>\n<pre><code>var builder = bucket.MutateIn(id).\r\n            Insert(\"attributes.hairLength\", \"short\").\r\n            Execute();\r\n<\/code><\/pre>\n<p>The document&#8217;s attributes dictionary will now look like this:<\/p>\n<pre><code>...\r\n\"attributes\": \r\n{\r\n    \"fleas\": true,\r\n    \"color\": \"white\",\r\n    \"eyeColor\": \"brown\",\r\n    \"age\": 5,\r\n    \"dirty\": true,\r\n    \"sex\": \"female\",\r\n    \"hairLength\": \"short\"\r\n}\r\n...\r\n<\/code><\/pre>\n<p>Now if the parent element doesn&#8217;t exist, the <code>createParents<\/code> parameter can be used to create the parent element. This is true by default, so you do not have to do anything &#8211; pass false if you want to fail if the parent element doesn&#8217;t exist:<\/p>\n<pre><code>var builder = bucket.MutateIn(id).\r\n            Insert(\"anewattribute.withakey\", \"somevalue\").\r\n            Execute();\r\n<\/code><\/pre>\n<p>This will create the new attribute called <code>anewattribute<\/code> in the document and add a single key called <code>withakey<\/code> with a value of <code>somevalue<\/code>.<\/p>\n<pre><code>...\r\n\"anewattribute\": \r\n{\r\n    \"withakey\": \"somevalue\"\r\n}\r\n...\r\n<\/code><\/pre>\n<p>Now, if we passed on <code>false<\/code> for <code>createParents<\/code> and the parent attribute did not exist, then the multi-mutation would fail with a top-level response status of <code>SubDocMultiPathFailure<\/code> and the specific error would be <code>SubDocPathNotFound<\/code>.<\/p>\n<h3 id=\"upsert\">Upsert<\/h3>\n<p>Upsert will add or replace an existing dictionary entry. The usage is exactly the same as <code>Insert<\/code> with the exception of the method name being <code>Upsert<\/code>.<\/p>\n<h3 id=\"remove\">Remove<\/h3>\n<p><code>Remove<\/code> will remove an element at a given path. As an example, we will remove the owner&#8217;s name from the document above:<\/p>\n<pre><code> var fragment = bucket.MutateIn(id).\r\n            Remove(\"owner.name\").\r\n            Execute();\r\n<\/code><\/pre>\n<p>And the document after called <code>Remove<\/code>:<\/p>\n<pre><code>...\r\n\"owner\": \r\n{\r\n    \"type\": \"servant\",\r\n    \"age\": 63\r\n},\r\n...\r\n<\/code><\/pre>\n<h3 id=\"replace\">Replace<\/h3>\n<p>Replace will swap the value of element at a given path, failing if the path does not exist:<\/p>\n<pre><code>var fragment = bucket.MutateIn(id).\r\n            Replace(\"owner\", new { CatLover=true, CatName=\"celia\"}).\r\n            Execute();\r\n<\/code><\/pre>\n<p>The document will now have a different value for &#8220;owner&#8221;:<\/p>\n<pre><code>...\r\n\"owner\": \r\n{\r\n    \"catLover\": true,\r\n    \"catName\": \"celia\"\r\n},\r\n...\r\n<\/code><\/pre>\n<h3 id=\"pushback\">PushBack<\/h3>\n<p>Adds a value to the back of an array optionally adding the parent element (the array element itself) if it doesn&#8217;t exist.<\/p>\n<pre><code>var fragment = bucket.MutateIn(id).\r\n            PushBack(path, value, false).\r\n            Execute();\r\n<\/code><\/pre>\n<p>The <code>toys<\/code> array in the document now has the value &#8220;slipper&#8221; in the last ordinal:<\/p>\n<pre><code>...\r\n\"toys\": \r\n[ \r\n    \"squeaker\", \r\n    \"ball\", \r\n    \"shoe\", \r\n    \"slipper\"\r\n],\r\n...\r\n<\/code><\/pre>\n<h3 id=\"pushfront\">PushFront<\/h3>\n<p>Adds a value to the front of an array optionally adding the parent element (the array itself) if it doesn&#8217;t exist:<\/p>\n<pre><code>var fragment = bucket.MutateIn(id).\r\n            PushFront(path, value, false).\r\n            Execute();\r\n<\/code><\/pre>\n<p>The <code>toys<\/code> array now has the value &#8220;slipper&#8221; in it&#8217;s first ordinal:<\/p>\n<pre><code>...\r\n\"toys\": \r\n[\r\n    \"slipper\",\r\n    \"squeaker\",\r\n    \"ball\",\r\n    \"shoe\"\r\n],\r\n...\r\n<\/code><\/pre>\n<h3 id=\"arrayinsert\">ArrayInsert<\/h3>\n<p>Inserts a value into an array at a given index:<\/p>\n<pre><code> var fragment = bucket.MutateIn(id).\r\n            ArrayInsert(\"toys[2]\", \"slipper\").\r\n            Execute();\r\n<\/code><\/pre>\n<p>The <code>toys<\/code> array now has the value &#8220;slipper&#8221; at it&#8217;s 3rd ordinal (index 2):<\/p>\n<pre><code>\"toys\": \r\n[\r\n    \"squeaker\",\r\n    \"ball\",\r\n    \"slipper\",\r\n    \"shoe\"\r\n ],\r\n<\/code><\/pre>\n<h3 id=\"addunique\">AddUnique<\/h3>\n<p>Inserts a value into an array, failing if it exists (the value must be unique within the array):<\/p>\n<pre><code> var fragment = bucket.MutateIn(id).\r\n            AddUnique(\"toys\", \"shoe\").\r\n            Execute();\r\n<\/code><\/pre>\n<p>Since the value &#8220;shoe&#8221; already exists in the original document&#8217;s <code>toys<\/code> array, this will fail withe following status:<\/p>\n<pre><code>SubDocPathExists\r\n<\/code><\/pre>\n<p>Note that this method only allows for JSON primitives to be inserted: strings, numbers, and special values for true, false or null. The reason is that there is no way to compare for uniqueness without descending into each JSON object and comparing elements item by item.<\/p>\n<h3 id=\"counter\">Counter<\/h3>\n<p>Adds a the specified delta to an existing value, creating the element if it doesn&#8217;t exist and defaulting the value and delta to 0. If the delta is negative, the value of the element will be decremented by the given delta.<\/p>\n<pre><code>var fragment = bucket.MutateIn(id).\r\n            Counter(\"likes\", 1).\r\n            Execute();\r\n<\/code><\/pre>\n<p>Since the element doesn&#8217;t exist it will be created and then set to one (1). The document will now look like this:<\/p>\n<pre><code>...\r\n    ],\r\n    \"likes\": 1\r\n}\r\n<\/code><\/pre>\n<p>If we pass a negative one (-1), then the counter for <code>likes<\/code> will be decremented back to zero (0):<\/p>\n<pre><code>var fragment = bucket.MutateIn(id).\r\n            Counter(\"likes\", -1).\r\n            Execute();\r\n<\/code><\/pre>\n<p>And the JSON document will now look like this:<\/p>\n<pre><code>...\r\n    ],\r\n    \"likes\": 0\r\n}\r\n<\/code><\/pre>\n<h2 id=\"release-notes-for-v2-2-6\">Release Notes for v2.2.6<\/h2>\n<h3>Bug<\/h3>\n<ul>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-981\">NCBC-981<\/a>] &#8211; When FQDN is defined for Couchbase instance SSL fails<\/li>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1074\">NCBC-1074<\/a>] &#8211; View request blocks indefinitely if waited on synchronously<\/li>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1083\">NCBC-1083<\/a>] &#8211; PoolConfiguration still uses default settings when overridden<\/li>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1084\">NCBC-1084<\/a>] &#8211; ConfigurationSection ignores UseSsl<\/li>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1086\">NCBC-1086<\/a>] &#8211; GetAndLock not returning Locked status but timed out when doc is locked<\/li>\n<\/ul>\n<h3>Improvement<\/h3>\n<ul>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1070\">NCBC-1070<\/a>] &#8211; Make QueryRequest not depend upon JSON.NET<\/li>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1082\">NCBC-1082<\/a>] &#8211; Add support for sortCount in QueryResult.Metrics<\/li>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1085\">NCBC-1085<\/a>] &#8211; Await callback so that the executing thread is not blocked<\/li>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-1090\">NCBC-1090<\/a>] &#8211; Fix &#8221; Cannot await in the body of a catch clause&#8221; in SSL IO<\/li>\n<\/ul>\n<h3>New Feature<\/h3>\n<ul>\n<li>[<a href=\"https:\/\/issues.couchbase.com\/browse\/NCBC-998\">NCBC-998<\/a>] &#8211; Include support for Subdocument API &#8211; Part 1 Multi-commands DP<\/li>\n<\/ul>\n<h2 id=\"how-to-get-v2-2-6\">How to get v2.2.6<\/h2>\n<ul>\n<li>Download the binaries <a href=\"https:\/\/s3.amazonaws.com\/packages.couchbase.com\/clients\/net\/2.2\/Couchbase-Net-Client-2.2.6.zip\" target=\"_blank\" rel=\"noopener noreferrer\">here.<\/a><\/li>\n<li>The NuGet package can be found <a href=\"https:\/\/www.nuget.org\/packages\/CouchbaseNetClient\/2.2.6\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/li>\n<li>The Github repo is <a href=\"https:\/\/github.com\/couchbase\/couchbase-net-client\/tree\/2.2.6\">here<\/a>.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Note: all examples can be found here. Today we are releasing a very special Developer Preview (DP) of a new feature in the upcoming release of Couchbase Server called Sub-document, along with our normal Couchbase Server .NET SDK 2.2.6! The [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1811,2201],"tags":[1606,1586],"ppma_author":[8970],"class_list":["post-2192","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-tools-sdks","tag-sub-document","tag-subdocument"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Sub-document API included Couchbase .NET SDK<\/title>\n<meta name=\"description\" content=\"Check out the Sub-document API is a new feature of Couchbase Server that is available in the Developer Preview of Couchbase Server 4.5.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Developer Preview of new Sub-document API included w\/2.2.6 release of Couchbase .NET SDK\" \/>\n<meta property=\"og:description\" content=\"Check out the Sub-document API is a new feature of Couchbase Server that is available in the Developer Preview of Couchbase Server 4.5.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-03-10T21:51:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-10-09T14:10:18+00:00\" \/>\n<meta name=\"author\" content=\"Jeff Morris, Senior Software Engineer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@jeffrysmorris\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeff Morris, Senior Software Engineer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/\"},\"author\":{\"name\":\"Jeff Morris, Senior Software Engineer, Couchbase\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/b678bdd9f7b21a33d43ea965865a3341\"},\"headline\":\"Developer Preview of new Sub-document API included w\\\/2.2.6 release of Couchbase .NET SDK\",\"datePublished\":\"2016-03-10T21:51:30+00:00\",\"dateModified\":\"2025-10-09T14:10:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/\"},\"wordCount\":1474,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"keywords\":[\"sub-document\",\"subdocument\"],\"articleSection\":[\".NET\",\"Tools &amp; SDKs\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/\",\"name\":\"Sub-document API included Couchbase .NET SDK\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2016-03-10T21:51:30+00:00\",\"dateModified\":\"2025-10-09T14:10:18+00:00\",\"description\":\"Check out the Sub-document API is a new feature of Couchbase Server that is available in the Developer Preview of Couchbase Server 4.5.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Developer Preview of new Sub-document API included w\\\/2.2.6 release of Couchbase .NET SDK\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/b678bdd9f7b21a33d43ea965865a3341\",\"name\":\"Jeff Morris, Senior Software Engineer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5f910befdbd58de8bac85293df7f544680843061ecc921ba7d293d6d52076ab3?s=96&d=mm&r=g73188ee2831025d81740e12e1ed80812\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5f910befdbd58de8bac85293df7f544680843061ecc921ba7d293d6d52076ab3?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5f910befdbd58de8bac85293df7f544680843061ecc921ba7d293d6d52076ab3?s=96&d=mm&r=g\",\"caption\":\"Jeff Morris, Senior Software Engineer, Couchbase\"},\"description\":\"Jeff Morris is a Senior Software Engineer at Couchbase. Prior to joining Couchbase, Jeff spent six years at Source Interlink as an Enterprise Web Architect. Jeff is responsible for the development of Couchbase SDKs and how to integrate with N1QL (query language).\",\"sameAs\":[\"https:\\\/\\\/x.com\\\/jeffrysmorris\"],\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/author\\\/jeff-morris\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Sub-document API included Couchbase .NET SDK","description":"Check out the Sub-document API is a new feature of Couchbase Server that is available in the Developer Preview of Couchbase Server 4.5.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/","og_locale":"en_US","og_type":"article","og_title":"Developer Preview of new Sub-document API included w\/2.2.6 release of Couchbase .NET SDK","og_description":"Check out the Sub-document API is a new feature of Couchbase Server that is available in the Developer Preview of Couchbase Server 4.5.","og_url":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/","og_site_name":"The Couchbase Blog","article_published_time":"2016-03-10T21:51:30+00:00","article_modified_time":"2025-10-09T14:10:18+00:00","author":"Jeff Morris, Senior Software Engineer, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@jeffrysmorris","twitter_misc":{"Written by":"Jeff Morris, Senior Software Engineer, Couchbase","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/"},"author":{"name":"Jeff Morris, Senior Software Engineer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/b678bdd9f7b21a33d43ea965865a3341"},"headline":"Developer Preview of new Sub-document API included w\/2.2.6 release of Couchbase .NET SDK","datePublished":"2016-03-10T21:51:30+00:00","dateModified":"2025-10-09T14:10:18+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/"},"wordCount":1474,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["sub-document","subdocument"],"articleSection":[".NET","Tools &amp; SDKs"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/","url":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/","name":"Sub-document API included Couchbase .NET SDK","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2016-03-10T21:51:30+00:00","dateModified":"2025-10-09T14:10:18+00:00","description":"Check out the Sub-document API is a new feature of Couchbase Server that is available in the Developer Preview of Couchbase Server 4.5.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/developer-preview-of-new-sub-document-api-included-w-2-2-6-release-of-couchbase-net-sdk\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Developer Preview of new Sub-document API included w\/2.2.6 release of Couchbase .NET SDK"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/b678bdd9f7b21a33d43ea965865a3341","name":"Jeff Morris, Senior Software Engineer, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/5f910befdbd58de8bac85293df7f544680843061ecc921ba7d293d6d52076ab3?s=96&d=mm&r=g73188ee2831025d81740e12e1ed80812","url":"https:\/\/secure.gravatar.com\/avatar\/5f910befdbd58de8bac85293df7f544680843061ecc921ba7d293d6d52076ab3?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5f910befdbd58de8bac85293df7f544680843061ecc921ba7d293d6d52076ab3?s=96&d=mm&r=g","caption":"Jeff Morris, Senior Software Engineer, Couchbase"},"description":"Jeff Morris is a Senior Software Engineer at Couchbase. Prior to joining Couchbase, Jeff spent six years at Source Interlink as an Enterprise Web Architect. Jeff is responsible for the development of Couchbase SDKs and how to integrate with N1QL (query language).","sameAs":["https:\/\/x.com\/jeffrysmorris"],"url":"https:\/\/www.couchbase.com\/blog\/author\/jeff-morris\/"}]}},"acf":[],"authors":[{"term_id":8970,"user_id":21,"is_guest":0,"slug":"jeff-morris","display_name":"Jeff Morris, Senior Software Engineer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/5f910befdbd58de8bac85293df7f544680843061ecc921ba7d293d6d52076ab3?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2192","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=2192"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2192\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=2192"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=2192"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=2192"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=2192"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}