Couchbase Server 5.0 y 5.5 han sido dos grandes lanzamientos. Veamos algunas de las nuevas características que los desarrolladores no pueden perderse:
1) Subdocumentos
Esta característica ha estado aquí por un tiempo, pero todavía vale la pena mencionarla. Algunos almacenes Clave-Valor sólo permiten traer el documento completo, lo cual es una característica razonable. Después de todo, es un Key-Value Store. Sin embargo, si estás usando Couchbase como KV, aún puedes manipular partes del documento especificando la ruta a él. Ej:
Dado el siguiente documento:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{ "nombre": "Douglas Reynholm", "email": "douglas@reynholmindustries.com", "direcciones": { "facturación": { "línea1": "Calle Cualquiera 123", "línea2": "Cualquier ciudad", "país": "Reino Unido" }, "entrega": { "línea1": "Calle Cualquiera 123", "línea2": "Cualquier ciudad", "país": "Reino Unido" } }, "compras": { "completo": [ 339, 976, 442, 666 ], "abandonado": [ 157, 42, 999 ] } } |
Puede manipular partes del documento simplemente especificando la ruta a él, como GET('direcciones.facturación') o ARRAY_APPEND('compras.abandonadas', 42)
Si quiere saber más, consulte este artículo entrada del blog o nuestro documentación oficial.
2)Concurso completo
Evento es claramente una de las características más interesantes en Couchbase 5.5 y ya tenemos un montón de entradas de blog que cubren, como aquí o aquí. Para los que aún no lo conozcan, el Servicio Eventing permite escribir funciones del servidor que se activan automáticamente cada vez que se inserta/actualiza/elimina un documento. Estas funciones pueden escribirse fácilmente utilizando una sintaxis similar a la de JavaScript:

Además, también puede llamar a puntos finales en su aplicación a través de curl:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
función OnUpdate(doc, meta) { si (doc.resourceType != Observación) devolver; deje referencia = doc.tema.referencia; deje url = "https://localhost:8080/events/" + referencia.substr(9); deje datos = JSON.stringify({ "referencia": doc.tema.referencia, "código": doc.código.codificación[0].código, "recordedAt": doc.publicado, "valor": doc.valorCantidad.valor }); deje rizo = SELECCIONE CURL($url, { "solicitud": "POST", "cabecera": [ "Content-Type: application/json", "accept: application/json" ], "datos": $datos }); rizo.execQuery(); } función OnDelete(meta) {} |
3)Uniones ANSI
Couchbase le permite utilizar se une a en tus consultas desde hace bastante tiempo, pero hasta ahora sólo se podía conseguir utilizando nuestra propia sintaxis. Desde Couchbase 5.5 también puedes usar la sintaxis ANSI JOIN:
|
1 2 3 4 5 6 7 |
SELECCIONE DISTINTO ruta.destinoaeropuerto DESDE `viaje-muestra` aeropuerto ÚNASE A `viaje-muestra` ruta EN aeropuerto.faa = ruta.fuenteaeropuerto Y ruta.tipo = "ruta" DONDE aeropuerto.tipo = "aeropuerto" Y aeropuerto.ciudad = "San Francisco" Y aeropuerto.país = "Estados Unidos"; |
Más información aquí.
4)Búsqueda de texto completo
La mayoría de las aplicaciones orientadas al usuario necesitan implementar algún tipo de búsqueda avanzada. Este tipo de función suele requerir que se envíen datos a una herramienta de terceros como Solr o Elastic Search. Sin embargo, añadir este tipo de herramientas aumenta el coste y la complejidad de la infraestructura de forma significativa, por no mencionar todo el código necesario para enviar cambios de objetos/documentos a estas herramientas.
A partir de Couchbase 5.0, puedes simplemente crear un índice de búsqueda de texto completo en la consola web y empezar a hacer búsquedas de texto completo directamente desde la base de datos:

Resaltar resultados de búsqueda:

Caliente para hacer una búsqueda simple a través de SDK:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Override público Lista<SearchQueryRow> searchQuery(Cadena palabra) { Cadena indexName = "movies_index"; QueryStringQuery consulta = BúsquedaQuery.queryString(palabra); SearchQueryResult resultado = movieRepository.getCouchbaseOperations().getCouchbaseBucket().consulta( nuevo BúsquedaQuery(indexName, consulta).destacar().límite(20)); Lista<SearchQueryRow> hits = nuevo ArrayList<>(); si (resultado != null && resultado.errores().isEmpty()) { Iterador<SearchQueryRow> resultIterator = resultado.iterador(); mientras que (resultIterator.hasNext()) { hits.añada(resultIterator.siguiente()); } } devolver hits; } |
Puede consultar la documentación oficial aquí.
5) Consultas más rápidas, agrupaciones por y agregación pushdown
Independientemente de la base de datos, las operaciones de agregación (min, max, avg, etc) y GROUP BYs siempre han sido problemáticas en términos de rendimiento. Para hacer frente a este problema, con Couchbase 5.5, puedes aprovechar tus índices para acelerar este tipo de consultas:
|
1 2 3 4 5 |
SELECCIONE país, estado, ciudad, CONTAR(1) AS total DESDE `viaje-muestra` DONDE tipo = hotel y país es no null GRUPO POR país, estado, ciudad PEDIR POR CONTAR(1) DESC; |
~90ms - Plan de consulta de la consulta anterior

~7ms - La misma consulta anterior pero utilizando un índice adecuado

Puede leer el artículo completo aquí.
6)Control de acceso basado en funciones y certificado X509
Las bases de datos son el premio gordo para cualquier intruso malintencionado, por eso nunca está de más añadir una capa extra de seguridad. Con Couchbase, puede autenticar clientes mediante certificados X.509 y limitar su acceso mediante el control de acceso basado en funciones (RBAC):

También puede conceder permisos a través de N1QL. Veamos cómo conceder un permiso SELECT para el usuario denis en el cubo algún_cubo se vería así:
|
1 |
SUBVENCIÓN PAPEL query_select(algún_cubo) A denis; |
7)Cifrado de campos
La encriptación en reposo es una de las formas más básicas de seguridad, y puedes encriptar/desencriptar campos fácilmente utilizando la función Cifrado Java de Couchbase:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
público estático clase Persona { @Id público Cadena id; @CampoEncriptado(proveedor = "AES") público Cadena contraseña; //El resto se transportará y almacenará sin cifrar. público Cadena firstName; público Cadena apellido; público Cadena nombredeusuario; público int edad; } |
8) SDK reactivo
También ofrecemos un SDK reactivo, que no es algo fácil de encontrar en buena parte de los proveedores de bases de datos. Esto se debe principalmente al hecho de que nuestro propio SDK se implementa de forma reactiva.
La programación reactiva es realmente importante para el rendimiento y la optimización de recursos. Si aún no estás familiarizado con este concepto, te recomiendo encarecidamente este artículoque ofrece una rápida visión general de por qué debería considerar el uso de la programación reactiva en su capa de persistencia.
Disponemos de un amplio material sobre este tema. Si desea saber más, puede empezar por aquí o aquí.
9) "Ajuste fino de la velocidad" mediante SDK
En Couchbase, intentamos que los desarrolladores puedan ajustar su rendimiento incluso a nivel de documento, para que puedan decidir, caso por caso, cuál es la mejor compensación para cada escenario.
Echemos un vistazo, por ejemplo, a cómo Couchbase almacena los datos. Por defecto, tan pronto como el servidor reconoce que un nuevo documento debe ser almacenado, ya envía la respuesta de vuelta al cliente diciendo que su "petición ha sido recibida con éxito" y de forma asíncrona, almacenamos y replicamos el documento.
Este enfoque es muy bueno para la velocidad, pero hay una pequeña posibilidad de perder datos si el servidor se bloquea cuando el documento está todavía en la memoria del servidor. Si quiere evitarlo, puede especificar mediante SDK que desea recibir la confirmación sólo después de que el documento se haya replicado o almacenado en el disco:
|
1 2 3 4 5 |
movieRepository.getCouchbaseOperations().guardar(película, PersistTo.UNA, ReplicateTo.NONE); /o movieRepository.getCouchbaseOperations().guardar(película, PersistTo.UNA, ReplicateTo.DOS); ... movieRepository.getCouchbaseOperations().guardar(película, PersistTo.NONE, ReplicateTo.UNA); |
¿Por qué permitir algo así? Pues porque si puede permitirse la pequeña posibilidad de perder estos datos si el servidor se bloquea, puede mejorar su rendimiento de forma significativa. No se trata de una decisión de todo o nada, ya que puedes decidir qué partes del sistema merecen ese riesgo.
También puede hacer algo similar con sus consultas. En este caso, si desea esperar a que los índices/vistas se actualicen en función de los últimos cambios o si le parece bien la pequeña posibilidad de no devolver la versión más reciente de sus documentos:
|
1 2 3 4 |
//Puede utilizar ScanConsistency.REQUEST_PLUS, ScanConsistency.NOT_BOUNDED o ScanConsistency.STATEMENT_PLUS N1qlParámetros parámetros = N1qlParámetros.construya().coherencia(Consistencia de escaneado.SOLICITUD_PLUS).adhoc(verdadero); ParameterizedN1qlQuery consulta = N1qlQuery.parametrizado(queryString, JsonObject.crear(), parámetros); repositorio de recursos.getCouchbaseOperations().getCouchbaseBucket().consulta(consulta); |
Hay algunas otras características en nuestro SDK que también se pueden optimizar, y todas estas pequeñas decisiones pueden mejorar significativamente su rendimiento a escala.
10) Observabilidad del tiempo de respuesta
Ya he mencionado este punto en mi entrada anteriorpero creo que merece la pena mencionarlo de nuevo. Desde la versión 5.5, hemos introducido una nueva capacidad llamada Observabilidad del Tiempo de Respuesta, que proporcionará a los desarrolladores de sistemas una forma muy sencilla de observar los tiempos de respuesta en relación con un umbral (ajustable).
Esta función, que utiliza el formato OpenTracing, registra las peticiones lentas seguidas de un montón de detalles al respecto después de cada intervalo de tiempo, para que pueda identificar fácilmente las operaciones con bajo rendimiento.
|
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 |
Abr 04, 2018 9:42:57 AM com.couchbase.cliente.núcleo.rastreo.ThresholdLogReporter logOverThreshold ADVERTENCIA: Operaciones en umbral: [ { "top" : [ { "servidor_us" : 8, "local_id" : "41837B87B9B1C5D1/000000004746B9AA", "dirección_local" : "127.0.0.1:55011", "operation_id" : "get:0x6", "dispatch_us" : 315, "dirección_remota" : "127.0.0.1:11210", "total_us" : 576 }, { "servidor_us" : 8, "local_id" : "41837B87B9B1C5D1/000000004746B9AA", "dirección_local" : "127.0.0.1:55011", "operation_id" : "get:0x5", "dispatch_us" : 319, "dirección_remota" : "127.0.0.1:11210", "total_us" : 599 }, { "servidor_us" : 8, "local_id" : "41837B87B9B1C5D1/000000004746B9AA", "dirección_local" : "127.0.0.1:55011", "operation_id" : "get:0x4", "dispatch_us" : 332, "dirección_remota" : "127.0.0.1:11210", "total_us" : 632 }, { "servidor_us" : 11, "local_id" : "41837B87B9B1C5D1/000000004746B9AA", "dirección_local" : "127.0.0.1:55011", "operation_id" : "get:0x3", "dispatch_us" : 392, "dirección_remota" : "127.0.0.1:11210", "total_us" : 762 }, { "servidor_us" : 23, "local_id" : "41837B87B9B1C5D1/000000004746B9AA", "dirección_local" : "127.0.0.1:55011", "operation_id" : "get:0x1", "decode_us" : 9579, "dispatch_us" : 947, "dirección_remota" : "127.0.0.1:11210", "total_us" : 16533 }, { "servidor_us" : 56, "encode_us" : 12296, "local_id" : "41837B87B9B1C5D1/000000004746B9AA", "dirección_local" : "127.0.0.1:55011", "operation_id" : "upsert:0x2", "dispatch_us" : 1280, "dirección_remota" : "127.0.0.1:11210", "total_us" : 20935 } ], "servicio" : "kv", "contar" : 6 } ] |
La Observabilidad del Tiempo de Respuesta está activada por defecto, y ya hemos definido un conjunto de umbrales para evitar el registro de peticiones sanas. Si desea ampliar los límites de su clúster, puede incluso establecer umbrales más pequeños manualmente. Puedes leer más al respecto aquí.