No hace mucho escribí sobre cómo trabajar con partes, o fragmentos, de documentos en Couchbase
utilizando el SDK de Node.js. Ser capaz de trabajar con
partes de los documentos es posible utilizando
Servidor Couchbase 4.5 y superiores y el subdocumento API.
Esto es enorme porque cuando se trabaja con documentos NoSQL puede encontrarse con documentos muy grandes debido a todos los datos JSON incrustados. Como probablemente
sabe, hacer peticiones en documentos grandes es lento, y en la era moderna de la web, todo tiene que ser rápido. En su lugar, es más eficiente sólo
trabaja con lo que necesitas y no con todo a la vez.
En esta ocasión vamos a ver cómo hacer las mismas manipulaciones de documentos NoSQL que vimos en Node.js, pero esta vez con el lenguaje de programación Go. Vamos a
elabore una historia de datos para este ejemplo. Será la misma historia de datos que en el ejemplo anterior, pero supongamos que tenemos el siguiente documento JSON:
1 2 3 4 5 6 7 8 9 |
{ firstName: "Nic", apellido: "Raboy", redes sociales: { twitter: "nraboy" } } |
Los datos anteriores serán una base almacén de perfiles de usuario con la información de las redes sociales. Todas nuestras manipulaciones serán en torno a la información de los medios sociales, no
los datos padre que lo rodean.
Para mantener las cosas simples en esta guía, vamos a trabajar con un proyecto nuevo. En este punto asumiremos que tienes Couchbase Server 4.5+ y
GoLang instalado y configurado en tu máquina. Si aún no has descargado el SDK de GoLang para Couchbase, ejecuta lo siguiente desde tu Comando
Prompt o Terminal:
1 2 3 |
ir consiga github.com/couchbase/gocb |
Todo nuestro proyecto para este ejemplo residirá en un único archivo. Nos referiremos a este archivo como main.go y puede residir en cualquier
Directorio de proyectos Go que desee siempre que cumpla los requisitos del lenguaje de programación Go.
Para empezar, vamos a crear un archivo principal
dentro de nuestro proyecto:
1 2 3 4 5 6 7 8 9 |
func principal() { fmt.Imprimir("Iniciando la aplicación...") grupo, _ := gocb.Conectar("couchbase://localhost") cubo, _ = grupo.OpenBucket("por defecto", "") persona := Persona{Nombre: "Nic", Apellido: "Raboy", Redes sociales: &Redes sociales{Twitter: "nraboy"}} crearDocumento("nraboy", &persona) } |
Hay algunas cosas a tener en cuenta en lo anterior. En primer lugar, estamos estableciendo una conexión con un clúster de Couchbase que se ejecuta localmente. Cuando la conexión tiene
establecido abrimos el por defecto
cubo. Observe que sólo estamos asignando un valor a la variable cubo
y no definirlo. Este
es porque vamos a utilizar esta variable de forma global y debemos definirla fuera del archivo principal
función. Con el cubo abierto, vamos a
crear nuestra estructura de datos inicial. Esta estructura de datos Persona
se define a continuación:
1 2 3 4 5 6 7 8 9 10 11 12 |
tipo Persona struct { Nombre cadena `json:"firstname,omitempty"` Apellido cadena `json:"apellido,omitempty"` Redes sociales *Redes sociales `json:"socialNetworking,omitempty"` } tipo Redes sociales struct { Twitter cadena `json:"twitter,omitempty"` Página web cadena `json:"sitio web,omitempty"` } |
En Persona
tendrá la información básica del usuario y hará referencia a otra estructura llamada Redes sociales
. Ambos
se etiquetan con nombres de propiedades JSON que deben excluirse de la impresión si están en blanco.
Volviendo a la principal
función. Observa que a nuestro nuevo objeto persona le falta la página web. Lo añadiremos más adelante. El primer objeto
que llamamos desde la función principal
se llama a la función crearDocumento
y añadirá nuestro objeto a la base de datos. Esta función
se define del siguiente modo:
1 2 3 4 5 6 7 8 9 10 11 12 |
func crearDocumento(documentId cadena, persona *Persona) { fmt.Imprimir("Insertando un documento completo...") _, error := cubo.Upsert(documentId, persona, 0) si error != nil { fmt.Imprimir(error.Error()) devolver } getDocument(documentId) getSubDocument(documentId) } |
En la función anterior aún no estamos trabajando con fragmentos de un documento. Necesitamos empezar el ejemplo con datos frescos primero. Vamos a insertar
el documento inicial y siempre que no haya errores vamos a llamar a getDocument
para validar su creación y, a continuación
getSubDocument
para obtener una parte determinada del documento. El sitio getDocument
se utilizará dos veces en esta aplicación y
parece lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
func getDocument(documentId cadena) { fmt.Imprimir("Obtener el documento completo por id...") var persona Persona _, error := cubo.Visite(documentId, &persona) si error != nil { fmt.Imprimir(error.Error()) devolver } jsonPerson, _ := json.Mariscal(&persona) fmt.Imprimir(cadena(jsonPerson)) } |
En el getDocument
estamos obteniendo el documento completo basado en id, marshalling en JSON, y luego imprimirlo. Este
nos lleva a la getSubDocument
como se ve a continuación:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
func getSubDocument(documentId cadena) { fmt.Imprimir("Obtener parte de un documento por id...") fragmento, error := cubo.BúsquedaEn(documentId).Visite("redes sociales).Ejecute() si error != nil { fmt.Imprimir(error.Error()) devolver } var redes sociales Redes sociales fragmento.Contenido("redes sociales, &redes sociales) jsonSocialNetworking, _ := json.Mariscal(&redes sociales) fmt.Imprimir(cadena(jsonSocialNetworking)) upsertSubDocument(documentId, "thepolyglotdeveloper.com") } |
En el getSubDocument
estamos haciendo una búsqueda dentro de un documento para una propiedad específica. Aquí es donde empezamos a trabajar con
la API de subdocumentos. La búsqueda que estamos realizando es una búsqueda del subdocumento redes sociales
propiedad. Tenga en cuenta que me estoy refiriendo a la JSON, no
el struct
nombre. Cuando tengamos el fragmento podemos marshalizarlo en JSON y luego imprimirlo. El resultado debería tener este aspecto:
1 2 3 4 5 |
{ "twitter": "nraboy" } |
Al final del getSubDocument
hacemos una llamada a una función que pronto se creará upsertSubDocument
función. Aquí es donde
vamos a modificar parte de un documento sin obtener antes el documento completo. Esta función se puede ver de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 11 |
func upsertSubDocument(documentId cadena, sitio web cadena) { fmt.Imprimir("Insertando parte de un documento...") _, error := cubo.MutateIn(documentId, 0, 0).Upsert("socialNetworking.website", sitio web, verdadero).Ejecute() si error != nil { fmt.Imprimir(error.Error()) devolver } getDocument(documentId) } |
En la función anterior primero especificamos qué documento queremos manipular basándonos en el id del documento. A continuación, decimos que queremos realizar un upsert en un
cierta ruta o propiedad del documento. En este ejemplo estamos diciendo que queremos upsert un sitio web
que se encuentra en la propiedad
redes sociales
padre. Tenga en cuenta que todo este proceso se realiza sin obtener realmente el documento.
Cuando hayamos terminado, volvemos a buscar el documento completo para ver qué aspecto tiene en su conjunto. En caso de que necesites que esto se ponga en perspectiva un
poco mejor, el código completo de este proyecto se puede ver a continuación:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
paquete principal importar ( "encoding/json" "fmt" "github.com/couchbase/gocb" ) var cubo *gocb.Cubo tipo Persona struct { Nombre cadena `json:"firstname,omitempty"` Apellido cadena `json:"apellido,omitempty"` Redes sociales *Redes sociales `json:"socialNetworking,omitempty"` } tipo Redes sociales struct { Twitter cadena `json:"twitter,omitempty"` Página web cadena `json:"sitio web,omitempty"` } func getDocument(documentId cadena) { fmt.Imprimir("Obtener el documento completo por id...") var persona Persona _, error := cubo.Visite(documentId, &persona) si error != nil { fmt.Imprimir(error.Error()) devolver } jsonPerson, _ := json.Mariscal(&persona) fmt.Imprimir(cadena(jsonPerson)) } func crearDocumento(documentId cadena, persona *Persona) { fmt.Imprimir("Insertando un documento completo...") _, error := cubo.Upsert(documentId, persona, 0) si error != nil { fmt.Imprimir(error.Error()) devolver } getDocument(documentId) getSubDocument(documentId) } func getSubDocument(documentId cadena) { fmt.Imprimir("Obtener parte de un documento por id...") fragmento, error := cubo.BúsquedaEn(documentId).Visite("redes sociales).Ejecute() si error != nil { fmt.Imprimir(error.Error()) devolver } var redes sociales Redes sociales fragmento.Contenido("redes sociales, &redes sociales) jsonSocialNetworking, _ := json.Mariscal(&redes sociales) fmt.Imprimir(cadena(jsonSocialNetworking)) upsertSubDocument(documentId, "thepolyglotdeveloper.com") } func upsertSubDocument(documentId cadena, sitio web cadena) { fmt.Imprimir("Insertando parte de un documento...") _, error := cubo.MutateIn(documentId, 0, 0).Upsert("socialNetworking.website", sitio web, verdadero).Ejecute() si error != nil { fmt.Imprimir(error.Error()) devolver } getDocument(documentId) } func principal() { fmt.Imprimir("Iniciando la aplicación...") grupo, _ := gocb.Conectar("couchbase://localhost") cubo, _ = grupo.OpenBucket("por defecto", "") persona := Persona{Nombre: "Nic", Apellido: "Raboy", Redes sociales: &Redes sociales{Twitter: "nraboy"}} crearDocumento("nraboy", &persona) } |
Pruebe este proyecto para ver lo maravillosa que es la API de subdocumentos.
Conclusión
Acabas de ver cómo usar la API de sub-documentos del servidor Couchbase en una aplicación GoLang usando el SDK Go de Couchbase. Ya no tendrás que preocuparte por
pasando alrededor de tus potencialmente enormes documentos NoSQL, arruinando los tiempos de respuesta de tu aplicación. Si sabes que tus documentos son grandes o sólo necesitas
puede hacer uso de esta API.
Para obtener más información, visite el sitio web de Couchbase Portal para desarrolladores.