Ahora bien, esto no es el fin. Ni siquiera es el principio del fin. Pero es, quizás, el final del principio. - Winston Churchill
La actualización de datos no suele ser el final, sino el progreso de un flujo de trabajo. El envío sigue al pedido; la actualización del inventario sigue al envío; el ajuste del crédito sigue a la devolución; es necesario actuar en el siguiente paso del proceso para que el flujo de trabajo siga avanzando. Los flujos de trabajo pueden ser sencillos, con pocos pasos, o complejos, con cientos de pasos. Gestión de procesos empresariales (BPM) es una industria en sí misma.
Presentación de Couchbase 5.5 Servicio nocturno. Los desarrolladores pueden escribir una función Javascript que se ejecute cuando se produzca un cambio en los datos. Nos referimos a las inserciones, actualizaciones, fusiones y eliminaciones como mutaciones. Múltiples casos de uso específicos se han documentado para desarrollar estos concurso funciones.
JSON modelo de datos de Couchbase procede de JavaScript. N1QL es SQL para JSON. Las funciones eventing están escritas en Javascript y tiene integrado N1QL. El uso de las funciones Eventing, escribir lógica de negocio de procedimiento con acceso instantáneo a los datos fácil.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// Simple counting function // After every update to travel sample, keep track of the total number of documents of each type. function OnUpdate(doc, meta) { try { // Issue SELECT statement to get the counts. var ginfo = SELECT type, COUNT(type) typecount FROM `travel-sample` WHERE `type` IS NOT MISSING GROUP BY type; // loop through the resultset for (var val of ginfo) { var ckey = "trcount" + val.type; // Create the document key-string. var vtype = val.type; var vtc = val.typecount; // get the type, count // do the update. UPDATE T1 USE KEYS[$ckey] SET type = $vtype, typecount =$vtc; } } catch(e) { log(e); } } |
Este es el ciclo de vida de las funciones desde la perspectiva del desarrollador. Para cada mutación, se puede definir cualquier número de estas funciones a ejecutar. Es responsabilidad del desarrollador dimensionar los tiempos de ejecución de las funciones, en función del número de mutaciones.
Este es el ciclo de vida de las funciones de Eventing:
Para cada inserción, actualización o supresión (directa o por expiración), puede ejecutar una o varias funciones javascript. Estas funciones pueden leer los nuevos datos y el tipo de acción y luego ejecutar la acción subsiguiente. Esta funcionalidad está bien descrita en los blogs y artículos de Couchbase.
| Tipo de declaración | Función de eventos invocada |
| SELECCIONE | Ninguno |
| INSERTAR | OnUpdate(). La función se invoca una vez por documento insertado. La inserción simple inserta un único documento. Las inserciones pueden tener varios documentos utilizando varios documentos en la cláusula VALUES o pueden insertar varios documentos mediante la sentencia INSERT INTO...SELECT. |
| ACTUALIZACIÓN | Se invoca OnUpdate() una vez por documento actualizado, excepto cuando varias actualizaciones de un mismo documento se deduzcan en una sola actualización. La sentencia Update puede actualizar varios documentos. |
| UPSERT | OnUpdate(). El comportamiento es similar a INSERT. |
| BORRAR | OnDelete(). Se invoca una vez por cada documento eliminado. |
| FUSIONAR | OnUpdate() y/o OnDelete() en función de las acciones de inserción, actualización y eliminación. |
| CREAR ÍNDICE, ELIMINAR ÍNDICE, EXPLICAR, PREPARAR, CONCEDER, REVOCAR | No se invoca ninguna función de eventos. |
| EJECUTAR | Depende del tipo de sentencia ejecutada. |
Estas funciones también pueden ejecutar sentencias N1QL. Resto del artículo se ve en todos los aspectos de N1QL ejecutado en Funciones Eventing.
Declaraciones N1QL en funciones Eventing.
| Declaración | Casos de uso de las sentencias N1QL en las funciones de eventos |
| CREAR ÍNDICE | Dado que el esquema es flexible, podría inspeccionar los datos a menudo/periódicamente para detectar nuevos campos y luego crear índices sobre ellos. |
| BORRAR | Borrado en cascada. |
| DROP INDEX | Corolario del caso de uso CREAR ÍNDICE. |
| INFER | Introspección periódica del cubo para la estructura. A continuación, tomar medidas (validar, crear índice, actualizar el modelo de datos) si es necesario. |
| INSERTAR | Mantener datos referenciales (eventualmente).
Actualizar otros documentos con referencias a estos datos. Por ejemplo, datos de un nuevo código postal, estado, etc. Copia de datos (total o parcialmente) en documentos secundarios/terciarios. Similar a la acción posterior a la activación. |
| FUSIONAR | Mantén sincronizados los datos secundarios. |
| SELECCIONE | Obtener datos, ejecutar informes periódicamente, etc.
Compruebe diversos aspectos, como la calidad y la validez de los datos, Si conoce la clave del documento de destino, utilice las referencias directas incorporadas. Vea ejemplos en: https://docs.couchbase.com/server/5.5/eventing/eventing-examples.html |
| UPSERT | Mantener sincronizados los datos secundarios y terciarios.
Similar a la acción posterior al disparo. |
| ACTUALIZACIÓN | Mantener sincronizados los datos secundarios y terciarios.
Similar a la acción posterior al disparo. |
Ejemplos: Probemos algunas funciones eventing con N1QL.
|
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 |
select meta().id, * from execute S1; [ { "S1": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" }, { "S1": { "name": "John Smith", "zip": "94040" }, "id": "John::94040" } ] select meta().id, * from S2; [ { "S2": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" }, { "S2": { "name": "John Smith", "zip": "94040" }, "id": "John::94040" } ] select meta().id, * from T1; <No data> |
- N1QL simple en Funciones para registro y borrado en cascada.
Guarda cada documento eliminado en un cubo aparte.
|
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 |
function OnUpdate(doc, meta) { } function OnDelete(meta) { try { var myid = meta.id; //Insert into the bucket of INSERT INTO T1 VALUES(UUID(), {"type" : "deleted", "docid":$myid}); //Cascade delete DELETE FROM S2 USE KEYS [$myid]; } catch(e) { log(e); } } After creating the function above, the application Runs the following: DELETE FROM S1 WHERE zip = "94040"; // One document was deleted. SELECT meta().id, * from S1; // one document just got deleted. There should be only one document remaining. [ { "S1": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" } ] SELECT meta().id, * from T1; // We should see a log of the deleted [ { "T1": { "docid": "John::94040", "type": "deleted" }, "id": "2dc9b33d-3cd4-422e-af9c-b0c664c4660f" } ] SELECT meta().id, * FROM S2; // We should only see one document due to the effect of cascade delete from the the function [ { "S2": { "name": "Joe Smith", "zip": "94501" }, "id": "Joe::94040" } ] |
- OnUpdate() para mantener la información agregada lista periódicamente.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
function OnUpdate(doc, meta) { try { var stattime = SELECT lastupdate FROM T1 USE KEYS ["trstattime"]; for (var t of stattime) { var lt = t.lastupdate; var d = new Date(); var n = d.getTime(); // Every 10 minutes or more if ((n - lt) > (1000 * 60 * 10)) { UPDATE T1 USE KEYS["trstattime"] SET lastupdate = NOW_MILLIS() ; var ginfo = SELECT type, count(type) typecount FROM `travel-sample` WHERE `type` IS NOT MISSING GROUP BY type; for (var val of ginfo) { var ckey = "trcount::" + val.type; var vtype = val.type; var vtc = val.typecount; UPDATE T1 USE KEYS[$ckey] SET type = $vtype, typecount = $vtc; } } } } catch(e) { log(e); } } |
Referencias:
- Documentación de Couchbase: https://docs.couchbase.com/server/5.5/eventing/eventing-overview.html
- Blogs de Couchbase sobre eventing: https://www.couchbase.com/blog/tag/eventing/
