{"id":2327,"date":"2016-07-12T13:18:54","date_gmt":"2016-07-12T13:18:53","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2327"},"modified":"2025-10-09T07:25:56","modified_gmt":"2025-10-09T14:25:56","slug":"sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/","title":{"rendered":"API de subdocumento no Couchbase Server 4.5 com o SDK do .NET (revisitado)"},"content":{"rendered":"<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><em>Esta postagem do blog \u00e9 baseada em um <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/developer-preview-of-new-sub-document-api-included-w-2.2.6-release-of-couchbase-.net-sdk\/\">post anterior do blog de Jeff Morris<\/a> que cobriu a API de subdocumentos enquanto ela ainda estava na vers\u00e3o pr\u00e9via para desenvolvedores. Houve algumas altera\u00e7\u00f5es na API desde esse lan\u00e7amento.<\/em><\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Com <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/introduction\/intro.html?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">Servidor Couchbase 4.5<\/a> e o <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/4.5\/sdk\/dotnet\/start-using-sdk.html?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">.NET SDK 2.3.x<\/a>Agora voc\u00ea pode usar o <em>Subdocumento<\/em> em seu aplicativo .NET.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Nas vers\u00f5es anteriores do Couchbase, todas as muta\u00e7\u00f5es de documentos eram at\u00f4micas e envolviam o documento inteiro. Se voc\u00ea quiser alterar apenas um \u00fanico campo e depois fazer uma atualiza\u00e7\u00e3o, todo o documento no servidor Couchbase ser\u00e1 copiado pela nova revis\u00e3o. O problema \u00e9 que, se o documento for grande ou a rede for lenta (ou ambos), muitos recursos ser\u00e3o desperdi\u00e7ados com o envio de dados que n\u00e3o foram modificados. Uma solu\u00e7\u00e3o melhor e de melhor desempenho seria enviar apenas a parte do documento ou o valor que sofreu muta\u00e7\u00e3o. Essencialmente, \u00e9 isso que voc\u00ea obt\u00e9m com a API de subdocumento; quando voc\u00ea atualiza um elemento ou exclui um elemento de um documento, somente o caminho do fragmento a ser alterado \u00e9 enviado pela rede e somente essa parte do documento \u00e9 modificada.<\/p>\n<\/div>\n<div class=\"imageblock\">\n<div class=\"content\"><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2016\/july\/sub-document-api-in-couchbase-server-4.5-with-the-.net-sdk-revisted\/subdocument_001.jpg\" alt=\"Subdocument\" \/><\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>H\u00e1 v\u00e1rias opera\u00e7\u00f5es diferentes que s\u00e3o suportadas pela API, desde muta\u00e7\u00f5es em elementos individuais aninhados (tamb\u00e9m conhecidos como <em>sub<\/em>documentos) para modifica\u00e7\u00f5es em matrizes e dicion\u00e1rios. As opera\u00e7\u00f5es de contador tamb\u00e9m s\u00e3o suportadas, assim como as opera\u00e7\u00f5es de recupera\u00e7\u00e3o de fragmentos JSON incorporados.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>A API \u00e9 exposta por meio de um <em>fluente<\/em> que permite anexar v\u00e1rias opera\u00e7\u00f5es e execut\u00e1-las atomicamente no documento. H\u00e1 dois \"construtores\" diferentes: um construtor para opera\u00e7\u00f5es de muta\u00e7\u00e3o e um construtor para leituras ou \"pesquisas\" (que tamb\u00e9m pode verificar se um elemento existe em um determinado caminho).<\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"trueprerequisite-couchbase-server-4-5\">Pr\u00e9-requisito: Couchbase Server 4.5<\/h3>\n<div class=\"paragraph\">\n<p>Para seguir os exemplos abaixo, voc\u00ea precisar\u00e1 fazer o download e instalar <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/get-started-developing-nosql\/#Download_Couchbase_Server?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">Servidor Couchbase 4.5<\/a>. Se voc\u00ea nunca instalou o Couchbase Server antes, assista ao meu v\u00eddeo sobre <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/how-to-install-couchbase-server-on-windows-video\/\">Como instalar o Couchbase Server no Windows<\/a>. \u00c9 muito f\u00e1cil, independentemente do sistema operacional que estiver usando.<\/p>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"truesub-document-api-overview\">Vis\u00e3o geral da API do subdocumento<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Os exemplos a seguir usar\u00e3o um documento com um ID de \"puppy\" e come\u00e7ar\u00e3o com a seguinte apar\u00eancia:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">  {\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}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Todos os <a href=\"https:\/\/github.com\/couchbaselabs\/blog-source-code\/tree\/master\/Groves\/011SubDocumentInDotNet\/src\">Os exemplos est\u00e3o dispon\u00edveis no Github<\/a> para que voc\u00ea possa clonar o projeto e brincar com a API.<\/p>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truemutateinbuilder-and-lookupinbuilder\">MutateInBuilder e LookupInBuilder<\/h3>\n<div class=\"paragraph\">\n<p>A API de subdocumentos oferece dois novos tipos que utilizam um padr\u00e3o de construtor por meio de uma interface fluente para encadear v\u00e1rias opera\u00e7\u00f5es em um documento. Ambos os objetos s\u00e3o criados chamando <code>Muta\u00e7\u00e3o<\/code> ou <code>Pesquisa<\/code> em um <code>CouchbaseBucket<\/code> e passando a chave do documento com o qual voc\u00ea est\u00e1 trabalhando:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">\/\/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();<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Depois de ter o objeto construtor, voc\u00ea pode encadear v\u00e1rias opera\u00e7\u00f5es para executar no documento, por exemplo:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">var builder = bucket.LookupIn(id).\r\n    Get(\"type\").\r\n    Get(\"name\").\r\n    Get(\"owner\").\r\n    Exists(\"notfound\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Em seguida, voc\u00ea pode enviar todas as opera\u00e7\u00f5es para o servidor em um \u00fanico lote:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">var fragment = builder.Execute();<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Voc\u00ea pode verificar o resultado de uma opera\u00e7\u00e3o usando OpStatus e um caminho. Neste exemplo, estou usando o caminho <code>\"tipo\"<\/code>:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">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}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Estes s\u00e3o alguns dos m\u00e9todos e campos que voc\u00ea encontrar\u00e1 no <code>IDoc DocumentFragment<\/code> interface.<\/p>\n<\/div>\n<table class=\"tableblock frame-all grid-all spread\">\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Nome<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Descri\u00e7\u00e3o<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Conte\u00fado(...)<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Obt\u00e9m o conte\u00fado de um determinado caminho ou \u00edndice.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Existe(...)<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Retorna true se houver um resultado para um determinado caminho ou \u00edndice.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Count()<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">O n\u00famero de opera\u00e7\u00f5es atuais mantidas pelo construtor.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">OpStatus(...)<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">O <code>Status da resposta<\/code> de uma opera\u00e7\u00e3o em um determinado \u00edndice ou caminho.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Status<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">O <code>Status da resposta<\/code> para toda a opera\u00e7\u00e3o m\u00faltipla.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Sucesso<\/p>\n<\/td>\n<td class=\"tableblock halign-left valign-top\">\n<p class=\"tableblock\">Verdadeiro se toda a opera\u00e7\u00e3o m\u00faltipla for bem-sucedida.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"paragraph\">\n<p>Al\u00e9m dessas propriedades ou m\u00e9todos, h\u00e1 todas as outras propriedades herdadas de <code>Resultado da opera\u00e7\u00e3o<\/code> (que \u00e9 a resposta padr\u00e3o de uma opera\u00e7\u00e3o de chave\/valor): Upsert, Remove, Replace e assim por diante.<\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"trueerror-handling\">Tratamento de erros<\/h3>\n<div class=\"paragraph\">\n<p>Ao enviar v\u00e1rios <em>muta\u00e7\u00f5es<\/em>Se um deles falhar, toda a solicita\u00e7\u00e3o de v\u00e1rias opera\u00e7\u00f5es falhar\u00e1. Isso permite uma sem\u00e2ntica transacional do tipo \"tudo ou nada\" ao realizar muta\u00e7\u00f5es em um \u00fanico documento.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Ao enviar v\u00e1rios <em>pesquisas<\/em>Se o servidor tentar retornar tantos itens quantos forem solicitados, algumas opera\u00e7\u00f5es poder\u00e3o ser bem-sucedidas e outras poder\u00e3o falhar.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>If the operation(s) failed, then the`Status` property will contain a top-level error response such as <code>SubDocMultiPathFailure<\/code>. Essa \u00e9 uma indica\u00e7\u00e3o de que voc\u00ea deve se aprofundar nos resultados da opera\u00e7\u00e3o para obter o erro espec\u00edfico. Voc\u00ea pode fazer isso por meio de itera\u00e7\u00e3o: chamando a fun\u00e7\u00e3o <code>Status da opera\u00e7\u00e3o<\/code> e passando o \u00edndice ou o caminho:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">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\"));<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Nesse caso, como o caminho \"somepaththatdoesntexist\" n\u00e3o existia no documento, o erro espec\u00edfico retornado foi <code>SubDocPathNotFound<\/code>. H\u00e1 muitas combina\u00e7\u00f5es diferentes de erros, dependendo do tipo de construtor e da condi\u00e7\u00e3o do erro.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"truelookupinbuilder-examples\">Exemplos de LookupInBuilder<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>O <code>LookUpInBuilder<\/code> suporta duas opera\u00e7\u00f5es: buscar um valor por caminho e verificar a exist\u00eancia de um valor em um determinado caminho.<\/p>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"trueget\">Obter:<\/h3>\n<div class=\"paragraph\">\n<p>Vamos procurar o <code>propriet\u00e1rio<\/code> fragmento. Se eu passar \"owner\" como par\u00e2metro de caminho para esse m\u00e9todo...<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void GetExample(IBucket bucket, string path, string id)\r\n{\r\n    var builder = bucket.LookupIn(id).\r\n        Get(path).\r\n        Execute();\r\n\r\n    var fragment = builder.Content(path);\r\n    Console.WriteLine(fragment);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>...a sa\u00edda para o console seria:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">{\r\n    \"type\": \"servant\",\r\n    \"name\": \"Don Knotts\",\r\n    \"age\": 63\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"trueexist\">Existir:<\/h3>\n<div class=\"paragraph\">\n<p>Tamb\u00e9m podemos verificar se um caminho existe. Se eu passar \"owner\" como o caminho para esse m\u00e9todo...<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void ExistsExample(IBucket bucket, string path, string id)\r\n{\r\n    var builder = bucket.LookupIn(id).\r\n        Exists(path).\r\n        Execute();\r\n\r\n    var found = builder.Content(path);\r\n    Console.WriteLine(found);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>...o resultado \u00e9 <code>verdadeiro<\/code>porque o caminho <code>propriet\u00e1rio<\/code> existe de fato no documento.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"truemutateinbuilder\">MutateInBuilder<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>O MutateInBuilder oferece v\u00e1rios m\u00e9todos de suporte a muta\u00e7\u00f5es em valores escalares, dicion\u00e1rios e matrizes, al\u00e9m de suporte a opera\u00e7\u00f5es de contador at\u00f4mico.<\/p>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"trueinsert\">Inserir:<\/h3>\n<div class=\"paragraph\">\n<p>Insert adiciona um valor a um dicion\u00e1rio e, opcionalmente, permite que o elemento que o cont\u00e9m (o pr\u00f3prio dicion\u00e1rio) seja adicionado.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void InsertExample(IBucket bucket, string id, string path, string value)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        Insert(path, value, true).  \/\/ false is the default\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Se eu chamasse o m\u00e9todo acima dessa forma:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">InsertExample(bucket, id,\"attributes.hairLength\", \"short\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Ent\u00e3o, o dicion\u00e1rio de atributos do documento ter\u00e1 a seguinte apar\u00eancia:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">...\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...<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Observe que o <code>Inserir<\/code> tem um par\u00e2metro booleano opcional chamado <code>createParents<\/code>. \u00c9 falso por padr\u00e3o. Se for verdadeiro, a API do subdocumento criar\u00e1 o caminho necess\u00e1rio para que o campo exista. Se for falso, a API do subdocumento s\u00f3 criar\u00e1 o campo se os pais do campo j\u00e1 existirem. No exemplo acima, o campo <code>atributos<\/code> j\u00e1 existia.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>No pr\u00f3ximo exemplo, usarei um caminho com um campo pai (<code>um novo atributo<\/code>) que ainda n\u00e3o exista.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">InsertExample(bucket, id, \"anewattribute.withakey\", \"somevalue\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Isso criar\u00e1 o novo atributo chamado <code>um novo atributo<\/code> no documento e adicione uma \u00fanica chave chamada <code>withakey<\/code> com um valor de <code>algum valor<\/code>.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">...\r\n\"anewattribute\":\r\n{\r\n    \"withakey\": \"somevalue\"\r\n}\r\n...<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Agora, se passarmos <code>falso<\/code> para <code>createParents<\/code> e o atributo pai n\u00e3o existisse, a muta\u00e7\u00e3o m\u00faltipla falharia com um status de resposta de n\u00edvel superior de <code>SubDocMultiPathFailure<\/code> e o erro espec\u00edfico seria <code>SubDocPathNotFound<\/code>.<\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"trueupsert\">Upsert<\/h3>\n<div class=\"paragraph\">\n<p>Upsert adiciona ou substitui uma entrada existente no dicion\u00e1rio. O uso \u00e9 exatamente o mesmo que <code>Inserir<\/code> com exce\u00e7\u00e3o do nome do m\u00e9todo que \u00e9 <code>Upsert<\/code>.<\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"trueremove\">Remover<\/h3>\n<div class=\"paragraph\">\n<p><code>Remover<\/code> remover\u00e1 um elemento em um determinado caminho.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void RemoveExample(IBucket bucket, string id, string path)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        Remove(path).\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Quando chamo esse m\u00e9todo:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">RemoveExample(bucket, id, \"owner.name\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Veja como o documento ficar\u00e1 depois:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">...\r\n\"owner\":\r\n{\r\n    \"type\": \"servant\",\r\n    \"age\": 63\r\n},\r\n...<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truereplace\">Substituir<\/h3>\n<div class=\"paragraph\">\n<p>Replace trocar\u00e1 o valor do elemento em um determinado caminho, falhando se o caminho n\u00e3o existir:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void ReplaceExample(IBucket bucket, string id, string path, object value)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        Replace(path, value).\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Depois que eu chamar esse m\u00e9todo:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">ReplaceExample(bucket, id, \"owner\", new { CatLover=true, CatName=\"celia\"});<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>O documento agora ter\u00e1 um valor diferente para \"propriet\u00e1rio\":<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">...\r\n\"owner\":\r\n{\r\n    \"catLover\": true,\r\n    \"catName\": \"celia\"\r\n},\r\n...<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truearrayappend\">ArrayAppend<\/h3>\n<div class=\"paragraph\">\n<p>O ArrayAppend adiciona um valor ao final de uma matriz, adicionando opcionalmente o elemento pai (o pr\u00f3prio elemento da matriz) se ele n\u00e3o existir.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void ArrayAppendExample(IBucket bucket, string id, string path, object value)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        ArrayAppend(path, value, false).\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Depois desse m\u00e9todo com o caminho \"toys\"...<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">ArrayAppendExample(bucket, id, \"toys\", \"slipper\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>...o <code>brinquedos<\/code> no documento ter\u00e1 o valor \"slipper\" no \u00faltimo ordinal:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">...\r\n\"toys\":\r\n[\r\n    \"squeaker\",\r\n    \"ball\",\r\n    \"shoe\",\r\n    \"slipper\"\r\n],\r\n...<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truearrayprepend\">ArrayPrepender<\/h3>\n<div class=\"paragraph\">\n<p>O ArrayPrepend funciona da mesma forma que o ArrayAppend, exceto pelo fato de que ele adiciona um valor \u00e0 vari\u00e1vel <em>frente<\/em> de uma matriz.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void ArrayAppendExample(IBucket bucket, string id, string path, object value)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        ArrayAppend(path, value, false).\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Chamando esse m\u00e9todo com o caminho \"toys\"...<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">ArrayAppendExample(bucket, id, \"toys\", \"slipper\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>O <code>brinquedos<\/code> agora tem o valor \"slipper\" em sua matriz <em>primeiro<\/em> ordinal:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">...\r\n\"toys\":\r\n[\r\n    \"slipper\",\r\n    \"squeaker\",\r\n    \"ball\",\r\n    \"shoe\"\r\n],\r\n...<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truearrayinsert\">ArrayInsert<\/h3>\n<div class=\"paragraph\">\n<p>O ArrayPrepend coloca um valor no in\u00edcio, o ArrayAppend o coloca no final. Para completar, voc\u00ea pode usar o ArrayInsert para colocar um valor em algum ponto intermedi\u00e1rio (em um determinado \u00edndice).<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void ArrayInsertExample(IBucket bucket, string id, string path, object value)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        ArrayInsert(path, value).\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>E, em seguida, chamar esse m\u00e9todo com \"toys[2]\"...<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">ArrayInsertExample(bucket, id, \"toys[2]\", \"slipper\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>O <code>brinquedos<\/code> A matriz agora tem o valor \"slipper\" em seu terceiro ordinal (\u00edndice 2):<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">\"toys\":\r\n[\r\n    \"squeaker\",\r\n    \"ball\",\r\n    \"slipper\",\r\n    \"shoe\"\r\n ],<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truearrayaddunique\">ArrayAddUnique<\/h3>\n<div class=\"paragraph\">\n<p>O ArrayAddUnique insere um valor em uma matriz, mas falhar\u00e1 se esse valor j\u00e1 existir (ou seja, o valor deve ser exclusivo dentro da matriz).<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void ArrayAddUniqueExample(IBucket bucket, string id, string path, object value)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        ArrayAddUnique(path, value).\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Quando eu chamo isso de \"sapato\"...<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">ArrayAddUniqueExample(bucket, id, \"toys\", \"shoe\");<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>...uma vez que o valor \"shoe\" j\u00e1 existe no documento original <code>brinquedos<\/code> isso falhar\u00e1 com o status <code>SubDocPathExists<\/code>.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><em>Observe que esse m\u00e9todo s\u00f3 permite a inser\u00e7\u00e3o de primitivos JSON: cadeias de caracteres, n\u00fameros e valores especiais para verdadeiro, falso ou nulo. N\u00e3o h\u00e1 como comparar a exclusividade sem descer em cada objeto JSON e comparar os elementos item por item.<\/em><\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truecounter\">Balc\u00e3o<\/h3>\n<div class=\"paragraph\">\n<p>Adiciona o delta especificado (altera\u00e7\u00e3o) a um valor existente, criando o elemento se ele n\u00e3o existir. O valor e o delta ser\u00e3o padronizados como 0. Se o delta for negativo, o valor do elemento ser\u00e1 diminu\u00eddo pelo delta fornecido.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Criarei um m\u00e9todo que usa <code>Balc\u00e3o<\/code>:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">public static void CounterExample(IBucket bucket, string id, string path, long delta)\r\n{\r\n    var fragment = bucket.MutateIn(id).\r\n        Counter(path, delta).\r\n        Execute();\r\n\r\n    var status = fragment.OpStatus(path);\r\n    Console.WriteLine(status);\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Em seguida, chamarei o m\u00e9todo duas vezes usando um 1 positivo e um 1 negativo como \"deltas\":<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-C#\">CounterExample(bucket, id, \"likes\", 1);\r\nCounterExample(bucket, id, \"likes\", -1);<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Ap\u00f3s a primeira chamada, como o elemento n\u00e3o existe, ele ser\u00e1 criado e, em seguida, definido como um (1). O documento agora ter\u00e1 a seguinte apar\u00eancia:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">...\r\n    ],\r\n    \"likes\": 1\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>A segunda chamada passa um n\u00famero negativo (-1), portanto, o contador para <code>gostos<\/code> ser\u00e1 decrementado para zero (0). O documento JSON agora ter\u00e1 a seguinte apar\u00eancia:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlightjs highlight\"><code class=\"language-javascript\">...\r\n    ],\r\n    \"likes\": 0\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"trueconclusion\">Conclus\u00e3o<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Desde a publica\u00e7\u00e3o no blog da visualiza\u00e7\u00e3o do desenvolvedor, o SDK do Couchbase .NET foi atualizado para a vers\u00e3o 2.3.2 (at\u00e9 o momento desta publica\u00e7\u00e3o no blog). Voc\u00ea pode conferir o trabalho que foi feito na se\u00e7\u00e3o <a href=\"https:\/\/issues.couchbase.com\/projects\/NCBC\/versions\/13438?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">Notas de vers\u00e3o da vers\u00e3o 2.3.2<\/a>.<\/p>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truehow-to-get-v2-3-x\">Como obter a vers\u00e3o 2.3.x<\/h3>\n<div class=\"ulist\">\n<ul>\n<li>Fa\u00e7a o download dos bin\u00e1rios <a href=\"https:\/\/s3.amazonaws.com\/packages.couchbase.com\/clients\/net\/2.3\/Couchbase-Net-Client-2.3.3.zip\">para o .NET SDK 2.3.x do nosso reposit\u00f3rio (2.3.3 \u00e9 a vers\u00e3o mais recente).<\/a><\/li>\n<li>Voc\u00ea pode encontrar o <a href=\"https:\/\/www.nuget.org\/packages\/CouchbaseNetClient\/\">SDKs mais recentes no NuGet<\/a>.<\/li>\n<li>O <a href=\"https:\/\/github.com\/couchbase\/couchbase-net-client\">O c\u00f3digo-fonte est\u00e1 dispon\u00edvel no Github<\/a><\/li>\n<\/ul>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"truefinal-notes\">Notas finais<\/h3>\n<div class=\"paragraph\">\n<p>A API de subdocumentos permite que voc\u00ea seja mais granular em suas intera\u00e7\u00f5es com os documentos. Voc\u00ea pode modificar e recuperar apenas as partes de que precisa.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Deixe um coment\u00e1rio abaixo, <a href=\"https:\/\/twitter.com\/mgroves\">fale comigo no Twitter<\/a>ou envie um e-mail para mim (matthew.groves AT couchbase DOT com) se tiver alguma d\u00favida ou coment\u00e1rio.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>This blog post is based on an earlier blog post by Jeff Morris that covered the sub-document API while it was still in developer preview. There have been some changes to the API since that release. With Couchbase Server 4.5 [&hellip;]<\/p>","protected":false},"author":71,"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,1816],"tags":[1586],"ppma_author":[8937],"class_list":["post-2327","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-couchbase-server","tag-subdocument"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Sub-document API in Couchbase Server 4.5 with the .NET SDK<\/title>\n<meta name=\"description\" content=\"This blog focuses on the Sub-document feature in .Net application. It gives you the ability to be more granular in your interactions with documents.\" \/>\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\/pt\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Sub-document API in Couchbase Server 4.5 with the .NET SDK (revisited)\" \/>\n<meta property=\"og:description\" content=\"This blog focuses on the Sub-document feature in .Net application. It gives you the ability to be more granular in your interactions with documents.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-07-12T13:18:53+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-10-09T14:25:56+00:00\" \/>\n<meta name=\"author\" content=\"Matthew Groves\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mgroves\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matthew Groves\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/\"},\"author\":{\"name\":\"Matthew Groves\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58\"},\"headline\":\"Sub-document API in Couchbase Server 4.5 with the .NET SDK (revisited)\",\"datePublished\":\"2016-07-12T13:18:53+00:00\",\"dateModified\":\"2025-10-09T14:25:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/\"},\"wordCount\":1568,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"subdocument\"],\"articleSection\":[\".NET\",\"Couchbase Server\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/\",\"name\":\"Sub-document API in Couchbase Server 4.5 with the .NET SDK\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2016-07-12T13:18:53+00:00\",\"dateModified\":\"2025-10-09T14:25:56+00:00\",\"description\":\"This blog focuses on the Sub-document feature in .Net application. It gives you the ability to be more granular in your interactions with documents.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#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\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Sub-document API in Couchbase Server 4.5 with the .NET SDK (revisited)\"}]},{\"@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\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@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\/3929663e372020321b0152dc4fa65a58\",\"name\":\"Matthew Groves\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ba51e6aacc53995c323a634e4502ef54\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"caption\":\"Matthew Groves\"},\"description\":\"Matthew D. Groves is a guy who loves to code. It doesn't matter if it's C#, jQuery, or PHP: he'll submit pull requests for anything. He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s. He currently works as a Senior Product Marketing Manager for Couchbase. His free time is spent with his family, watching the Reds, and getting involved in the developer community. He is the author of AOP in .NET, Pro Microservices in .NET, a Pluralsight author, and a Microsoft MVP.\",\"sameAs\":[\"https:\/\/crosscuttingconcerns.com\",\"https:\/\/x.com\/mgroves\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/matthew-groves\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Sub-document API in Couchbase Server 4.5 with the .NET SDK","description":"Este blog se concentra no recurso Sub-documento no aplicativo .Net. Ele permite que voc\u00ea seja mais granular em suas intera\u00e7\u00f5es com os documentos.","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\/pt\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/","og_locale":"pt_BR","og_type":"article","og_title":"Sub-document API in Couchbase Server 4.5 with the .NET SDK (revisited)","og_description":"This blog focuses on the Sub-document feature in .Net application. It gives you the ability to be more granular in your interactions with documents.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/","og_site_name":"The Couchbase Blog","article_published_time":"2016-07-12T13:18:53+00:00","article_modified_time":"2025-10-09T14:25:56+00:00","author":"Matthew Groves","twitter_card":"summary_large_image","twitter_creator":"@mgroves","twitter_misc":{"Written by":"Matthew Groves","Est. reading time":"7 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/"},"author":{"name":"Matthew Groves","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58"},"headline":"Sub-document API in Couchbase Server 4.5 with the .NET SDK (revisited)","datePublished":"2016-07-12T13:18:53+00:00","dateModified":"2025-10-09T14:25:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/"},"wordCount":1568,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["subdocument"],"articleSection":[".NET","Couchbase Server"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/","url":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/","name":"Sub-document API in Couchbase Server 4.5 with the .NET SDK","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2016-07-12T13:18:53+00:00","dateModified":"2025-10-09T14:25:56+00:00","description":"Este blog se concentra no recurso Sub-documento no aplicativo .Net. Ele permite que voc\u00ea seja mais granular em suas intera\u00e7\u00f5es com os documentos.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#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\/sub-document-api-in-couchbase-server-4-5-with-the-net-sdk-revisted\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Sub-document API in Couchbase Server 4.5 with the .NET SDK (revisited)"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","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":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@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\/3929663e372020321b0152dc4fa65a58","name":"Matthew Groves","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ba51e6aacc53995c323a634e4502ef54","url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","caption":"Matthew Groves"},"description":"Matthew D. Groves \u00e9 um cara que adora programar. N\u00e3o importa se \u00e9 C#, jQuery ou PHP: ele enviar\u00e1 solicita\u00e7\u00f5es de pull para qualquer coisa. Ele tem programado profissionalmente desde que escreveu um aplicativo de ponto de venda QuickBASIC para a pizzaria de seus pais nos anos 90. Atualmente, ele trabalha como gerente s\u00eanior de marketing de produtos da Couchbase. Seu tempo livre \u00e9 passado com a fam\u00edlia, assistindo aos Reds e participando da comunidade de desenvolvedores. Ele \u00e9 autor de AOP in .NET, Pro Microservices in .NET, autor da Pluralsight e Microsoft MVP.","sameAs":["https:\/\/crosscuttingconcerns.com","https:\/\/x.com\/mgroves"],"url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/matthew-groves\/"}]}},"authors":[{"term_id":8937,"user_id":71,"is_guest":0,"slug":"matthew-groves","display_name":"Matthew Groves","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","author_category":"","last_name":"Groves","first_name":"Matthew","job_title":"","user_url":"https:\/\/crosscuttingconcerns.com","description":"Matthew D. Groves \u00e9 um cara que adora programar.  N\u00e3o importa se \u00e9 C#, jQuery ou PHP: ele enviar\u00e1 solicita\u00e7\u00f5es de pull para qualquer coisa.  Ele tem programado profissionalmente desde que escreveu um aplicativo de ponto de venda QuickBASIC para a pizzaria de seus pais nos anos 90.  Atualmente, ele trabalha como gerente s\u00eanior de marketing de produtos da Couchbase. Seu tempo livre \u00e9 passado com a fam\u00edlia, assistindo aos Reds e participando da comunidade de desenvolvedores.  Ele \u00e9 autor de AOP in .NET, Pro Microservices in .NET, autor da Pluralsight e Microsoft MVP."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2327","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/71"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=2327"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2327\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=2327"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=2327"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=2327"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=2327"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}