Advanced Bucket Accessors en Couchbase hace posible acceder a funcionalidades avanzadas de almacenes de valor-clave (KV) usando los siguientes operadores incorporados.
Utilizan los mismos bucket bindings definidos en el handler que los Basic Bucket Accessors, pero exponen un conjunto más rico de opciones y operadores que se pueden utilizar para:
- Fijar o recuperar vencimientos
- Resolver condiciones de carrera mediante CAS
- Manipular elementos KV calientes bajo alta contención
Tenga en cuenta que Accesorios básicos para cubos son mucho más fáciles de usar, tienen una API trivial, y también son un poco más rápidos que los correspondientes Advanced Bucket Accessors.
En Couchbase Server 6.6.1 se han añadido los siguientes Advanced Bucket Accessors:
Estos siete nuevos bucket accessors permiten utilizar y aprovechar CAS directamente para gestionar la contención y/o establecer la caducidad de un documento (o TTL) en el servicio de datos (o KV) a través de Eventos además de realizar operaciones de contador atómico distribuido.
Por ejemplo, en lugar de confiar ciegamente en los accesores de cubo básicos para una operación similar a upsert src_bkt[id_str] = some_docEn el caso de los accesos avanzados, los accesos avanzados le permiten resolver la contención (o posible contención) en claves que tienen mutaciones concurrentes de diferentes fuentes con lógica basada en JavaScript en su función de eventos.
-
- Si el documento no existe, puede utilizar
couchbase.insert(src_bkt, {"id: id_str}, some_doc)y comprobar si el valor devuelto es correcto - Si el documento existe, puede utilizar
couchbase.replace(src_bkt, {"id: id_str, "cas": current_cas}, some_doc)y comprueba si el valor de retorno es correcto o no.
- Si el documento no existe, puede utilizar
Para ver ejemplos completos que incluyan JavaScript, mutaciones de entrada, mutaciones de salida y/o mensajes de registro para cada accesorio de cubo avanzado, consulte Scriptlets: Manejadores de accesos avanzados en la sección de ejemplos de la documentación.
GET avanzado: resultado = couchbase.get(binding, meta)
Esta operación permite leer un documento junto con los metadatos del bucket y las operaciones posteriores para utilizar CAS o comprobar/modificar el fecha_de_vencimiento.
En contraste con el accesorio de cubo básico GET que simplemente expone un enlace o mapa JavaScript, var adoc = src_bkt[meta.id]cuyo valor de retorno es el documento sin metadatos.
A continuación se muestra un ejemplo de la opción Avanzada GET operación.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
function OnUpdate(doc, meta) { log('input doc ', doc); log('input meta', meta); // could be the same or different var new_meta = {"id":"test_adv_get::1"}; var result = couchbase.get(src_bkt,new_meta); if (result.success) { log('success adv. get: result',result); } else { log('failure adv. get: id',new_meta.id,'result',result); } } |
Algunos ejemplos de valores de retorno:
|
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 |
{ "doc": { "id": 1, "type": "test_adv_get" }, "meta": { "id": "test_adv_get::1", "cas": "1610034762747412480", "data_type": "json" }, "success": true } { "doc": { "a": 1, "random": 0.09799092443129842 }, "meta": { "id": "test_adv_insert:1", "cas": "1610140272584884224", "expiry_date": "2021-01-08T21:12:12.000Z", "data_type": "json" }, "success": true } { "error": { "code": 272, "name": "LCB_KEY_ENOENT", "desc": "The document key does not exist on the server", "key_not_found": true }, "success": false } |
INSERT avanzado: resultado = couchbase.insert(binding, meta, doc)
Esta operación permite crear un nuevo documento en el bucket. Esta operación fallará si el documento con la clave especificada ya existe. Permite especificar un tiempo de expiración (o TTL) para el documento.
No existe una operación de acceso a cubos básicos análoga a la operación de acceso a cubos avanzados. INSERTAR operación (como src_bkt[meta.id] = adoc es más bien un upsert).
A continuación se muestra un ejemplo de la opción Avanzada INSERTAR operación.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function OnUpdate(doc, meta) { log('input meta', meta); log('input doc ', doc); // could be the same or different var new_meta = {"id":"test_adv_insert:1"}; // optional set an expiry 60 seconds in the future // new_meta.expiry_date = new Date(Date.now() + 60 * 1000); var new_doc = doc; new_doc.random = Math.random(); var result = couchbase.insert(src_bkt,new_meta,new_doc); if (result.success) { log('success adv. insert: result',result); } else { log('failure adv. insert: id',new_meta.id,'result',result); } } |
Algunos ejemplos de valores de retorno:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "meta": { "id": "test_adv_insert:1", "cas": "1610041053310025728" }, "success": true } { "error": { "code": 272, "name": "LCB_KEY_EEXISTS", "desc": "The document key already exists in the server.", "key_already_exists": true }, "success": false } |
UPSERT avanzado: resultado = couchbase.upsert(binding, meta, doc)
Esta operación permite actualizar un documento existente en el bucket o, en su defecto, crear un documento nuevo con la clave especificada. La operación no permite especificar CAS (se ignorará silenciosamente). También permite especificar un tiempo de expiración (o TTL) que se establecerá en el documento.
En contraste con el accesorio de cubo básico SET que se limita a utilizar un mapa JavaScript expuesto definido mediante un alias de vinculación de bucket src_bkt[meta.id] = adoc. Para la base SET no hay valor de retorno (ni estado ni metadatos), por lo que no hay forma de comprobar el valor CAS.
A continuación se muestra un ejemplo de la opción Avanzada UPSERT operación.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function OnUpdate(doc, meta) { log('input meta', meta); log('input doc ', doc); // could be the same or different var new_meta = {"id":"test_adv_upsert:1"}; // CAS if supplied will be ignored // optional set an expiry 60 seconds in the future // new_meta.expiry_date = new Date(Date.now() + 60 * 1000); var new_doc = doc; new_doc.random = Math.random(); var result = couchbase.upsert(src_bkt,new_meta,new_doc); if (result.success) { log('success adv. upsert: result',result); } else { log('failure adv. upsert: id',new_meta.id,'result',result); } } |
Un ejemplo de valor de retorno:
|
1 2 3 4 5 6 7 |
{ "meta": { "id": "test_adv_upsert:1", "cas": "1610127444908376064" }, "success": true } |
Sustitución avanzada: resultado = couchbase.replace(binding, meta, doc)
Esta operación sustituye un documento existente en el bucket. Esta operación fallará si el documento con la clave especificada no existe. Esta operación permite especificar un valor CAS que debe coincidir como condición previa antes de proceder con la operación. También permite especificar un tiempo de expiración (o TTL) que debe establecerse en el documento.
No existe una operación de acceso a cubos básicos análoga a la operación de acceso a cubos avanzados. SUSTITUIR operación (como src_bkt[meta.id] = adoc es más bien un upsert).
A continuación se muestra un ejemplo de la opción Avanzada SUSTITUIR operació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 |
function OnUpdate(doc, meta) { log('input meta', meta); log('input doc ', doc); var mode = 3; // 1-> no CA, 2-> mismatch in CA, 3-> good CAS // Setup, make sure we have our doc to "replace", ignore any errors couchbase.insert(src_bkt,{"id":"test_adv_replace:10"},{"a:": 1}); var new_meta; if (mode === 1) { // If we pass no CAS it will succeed new_meta = {"id":"test_adv_replace:10"}; // optional set an expiry 60 seconds in the future // new_meta.expiry_date = new Date(Date.now() + 60 * 1000); } if (mode === 2) { // If we pass a non-matching CAS it will fail, so test this new_meta = {"id":"test_adv_replace:10", "cas":"1111111111111111111"}; } if (mode === 3) { // If we pass the matching or current CAS it will succeed var tmp_r = couchbase.get(src_bkt,{"id":"test_adv_replace:10"}); if (tmp_r.success) { // Here we use the current CAS just read via couchbase.get(...) new_meta = {"id":"test_adv_replace:10", "cas": tmp_r.meta.cas}; } else { log('Cannot replace non-existing key that create it and rerun',"test_adv_replace:10"); return; } } var new_doc = doc; new_doc.random = Math.random(); var result = couchbase.replace(src_bkt,new_meta,new_doc); if (result.success) { log('success adv. replace: result',result); } else { log('failure adv. replace: id',new_meta.id,'result',result); } } |
Algunos ejemplos de valores de retorno:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "meta": { "id": "test_adv_replace:10", "cas": "1610130177286144000" }, "success": true } { "error": { "code": 272, "name": "LCB_KEY_EEXISTS", "desc": "The document key exists with a CAS value different than specified", "cas_mismatch": true }, "success": false } |
Supresión avanzada: resultado = couchbase.delete(binding, meta)
Esta operación permite eliminar un documento del bucket especificado por key. Opcionalmente, se puede especificar un valor CAS que se cotejará como condición previa para proceder con la operación.
En contraste con el accesorio de cubo básico DEL que simplemente utiliza un enlace o mapa JavaScript expuesto, delete src_bkt[meta.id]donde no hay valor de retorno (ni estado ni metadatos).
A continuación se muestra un ejemplo de la opción Avanzada BORRAR operació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 |
function OnUpdate(doc, meta) { log('input meta', meta); log('input doc ', doc); var mode = 4; // 1-> no CA, 2-> mismatch in CA, 3-> good CAS, 4-> no such key // Setup, make sure we have our doc to "delete", ignore any errors couchbase.insert(src_bkt,{"id":"test_adv_delete:10"},{"a:": 1}); var new_meta; if (mode === 1) { // If we pass no CAS it will succeed new_meta = {"id":"test_adv_delete:10"}; // optional set an expiry 60 seconds in the future // new_meta.expiry_date = new Date(Date.now() + 60 * 1000); } if (mode === 2) { // If we pass a non-matching CAS it will fail, so test this new_meta = {"id":"test_adv_delete:10", "cas":"1111111111111111111"}; } if (mode === 3) { // If we pass the matching or current CAS it will succeed var tmp_r = couchbase.get(src_bkt,{"id":"test_adv_delete:10"}); if (tmp_r.success) { // Here we use the current CAS just read via couchbase.get(...) new_meta = {"id":"test_adv_delete:10", "cas": tmp_r.meta.cas}; } else { log('Cannot delete non-existing key that create it and rerun',"test_adv_delete:10"); return; } } if (mode === 4) { // Remove so that we have: no such key delete src_bkt["test_adv_delete:10"] new_meta = {"id":"test_adv_delete:10"}; } var result = couchbase.delete(src_bkt,new_meta); if (result.success) { log('success adv. delete: result',result); } else { log('failure adv. delete: id',new_meta.id,'result',result); } } |
Algunos ejemplos de valores de retorno:
|
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 |
{ "meta": { "id": "key::10", "cas": "1609374065129816064" }, "success": true } { "error": { "code": 272, "name": "LCB_KEY_EEXISTS", "desc": "The document key exists with a CAS value different than specified", "cas_mismatch": true }, "success": false } { "error": { "code": 272, "name": "LCB_KEY_ENOENT", "desc": "The document key does not exist on the server", "key_not_found": true }, "success": false } |
INCREMENTO Avanzado: resultado = couchbase.increment(binding, meta)
Esta operación incrementa atómicamente el campo cuente en el documento especificado. El documento debe tener la siguiente estructura:
|
1 |
{"count": 23} // 23 is the current counter value |
En incrementar devuelve el valor posterior al incremento.
Si el documento de contador especificado no existe, se crea uno con cuente como 0 y la estructura indicada anteriormente. Y así, el primer valor devuelto será 1.
Debido a las limitaciones de la API del motor KV, esta operación no puede manipular actualmente contadores de documentos completos.
No existe una operación de acceso a cubos básicos análoga a la operación de acceso a cubos avanzados. INCREMENTO operación.
A continuación se muestra un ejemplo de la opción Avanzada INCREMENTO operación.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function OnUpdate(doc, meta) { log('input meta', meta); log('input doc ', doc); // if doc.count doesn't exist it will be created var ctr_meta = {"id": "my_atomic_counter:1" }; var result = couchbase.increment(src_bkt,ctr_meta); if (result.success) { log('success adv. increment: result',result); } else { log('failure adv. increment: id',ctr_meta.id,'result',result); } } |
Un valor de retorno de ejemplo, suponga que crea esto KEY "my_atomic_counter:1" DOC {"count": 23} si se despliega la función Eventing anterior, el recuento se incrementará inmediatamente:
|
1 2 3 4 5 6 7 8 9 10 |
{ "doc": { "count": 24 }, "meta": { "id": "key::1", "cas": "1609374571840471040" }, "success": true } |
DECREMENTO Avanzado: resultado = couchbase.decrement(binding, meta)
Esta operación decrementa atómicamente el campo cuente en el documento especificado. El documento debe tener la siguiente estructura:
|
1 |
{"count": 23} // 23 is the current counter value |
En decremento devuelve el valor posterior a la reducción.
Si el documento de contador especificado no existe, se crea uno con la opción cuente como 0 y la estructura indicada anteriormente. Como resultado, el primer valor devuelto será -1.
Debido a las limitaciones de la API del motor KV, esta operación no puede manipular actualmente contadores de documentos completos.
No existe una operación de acceso a cubos básicos análoga a la operación de acceso a cubos avanzados. DESCREMENTO operación.
A continuación se muestra un ejemplo de la opción Avanzada DESCREMENTO operación.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function OnUpdate(doc, meta) { log('input meta', meta); log('input doc ', doc); // if doc.count doesn't exist it will be created var ctr_meta = {"id": "my_atomic_counter:1" }; var result = couchbase.decrement(src_bkt,ctr_meta); if (result.success) { log('success adv. decrement: result',result); } else { log('failure adv. decrement: id',ctr_meta.id,'result',result); } } |
Un valor de retorno de ejemplo, suponga que crea esto KEY "my_atomic_counter:1" DOC {"count": 23} si se despliega la función Eventing anterior, el recuento se decrementará inmediatamente:
|
1 2 3 4 5 6 7 8 9 10 |
{ "doc": { "count": 22 }, "meta": { "id": "key::1", "cas": "1609374770297176064" }, "success": true } |
Referencias