¿Cómo hacer un UUID en DynamoDB?

En mi esquema de db, necesito una clave principal de autoincremento. ¿Cómo puedo realizar esta característica?

PS Para acceder a DynamoDB, uso dynode , módulo para Node.js.

Descargo de responsabilidad: soy el mantenedor del proyecto Dynamodb-mapper

Flujo de trabajo intuitivo de una clave de incremento automático:

  1. obtener la última posición de contador
  2. añadir 1
  3. Usa el nuevo número como el índice del objeto.
  4. guarda el nuevo valor del contador
  5. guardar el objeto

Esto es solo para explicar la idea subyacente. Nunca lo hagas de esta manera porque no es atómico. Bajo cierta carga de trabajo, puede asignar la misma ID a más de 2 objetos diferentes porque no es atómico. Esto daría lugar a una pérdida de datos.

La solución es usar la operación ADD atómica junto con ALL_NEW de UpdateItem :

  1. generar atómicamente una identificación
  2. Usa el nuevo número como el índice del objeto.
  3. guardar el objeto

En el peor de los casos, la aplicación se bloquea antes de que se guarde el objeto, pero nunca corre el riesgo de asignar la misma ID dos veces.

Hay un problema restante: ¿dónde almacenar el último valor de ID? Nosotros elegimos:

{ "hash_key"=-1, #0 was judged too risky as it is the default value for integers. "__max_hash_key__y"=N } 

Por supuesto, para funcionar de manera confiable, todas las aplicaciones que insertan datos DEBEN conocer este sistema, de lo contrario, podría (nuevamente) sobrescribir los datos.

El último paso es automatizar el proceso. Por ejemplo:

 When hash_key is 0: atomically_allocate_ID() actual_save() 

Para los detalles de la implementación (Python, lo siento), consulte https://bitbucket.org/Ludia/dynamodb-mapper/src/8173d0e8b55d/dynamodb_mapper/model.py#cl-67

Para decirle la verdad, mi empresa no la usa en producción porque, la mayoría de las veces, es mejor encontrar otra clave como, para el usuario, una ID, para una transacción, una fecha y hora, …

Escribí algunos ejemplos en la documentación de dynamodb-mapper y se puede extrapolar fácilmente a Node.JS

Si usted tiene alguna pregunta no dude en preguntar.

Si está de acuerdo con los huecos en su identificación incremental, y está de acuerdo con que solo se corresponda aproximadamente con el orden en que se agregaron las filas, puede hacer su propio rollo: cree una tabla separada llamada NextIdTable, con una clave principal ( numérico), llámalo contador.

Cada vez que desee generar un nuevo ID, debería hacer lo siguiente:

  • Haga un GetItem en NextIdTable para leer el valor actual de Counter -> curValue
  • Haga un PutItem en NextIdTable para establecer el valor de Counter en curValue + 1. Haga que este sea un PutItem condicional para que falle si el valor de Counter ha cambiado.
  • Si ese PutItem condicional falló, significa que alguien más estaba haciendo esto al mismo tiempo que tú. Comenzar de nuevo.
  • Si tuvo éxito, entonces curValue es su nueva ID única.

Por supuesto, si su proceso falla antes de aplicar realmente esa identificación en cualquier lugar, lo “filtrará” y tendrá un hueco en su secuencia de identificaciones. Y si está haciendo esto simultáneamente con algún otro proceso, uno de ustedes obtendrá el valor 39 y uno de ustedes obtendrá el valor 40, y no hay garantías sobre qué orden se aplicarán realmente en su tabla de datos; el tipo que obtuvo 40 podría escribirlo antes que el que obtuvo 39. Pero le da un orden aproximado.

Los parámetros para un PutItem condicional en node.js se detallan aquí. http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/frames.html#!AWS/DynamoDB.html . Si anteriormente había leído un valor de 38 en Counter, su solicitud de PutItem condicional podría tener este aspecto.

 var conditionalPutParams = { TableName: 'NextIdTable', Item: { Counter: { N: '39' } }, Expected: { Counter: { AttributeValueList: [ { N: '38' } ], ComparisonOperator: 'EQ' } } }; 

No creo que sea posible hacer un incremento automático de estilo SQL porque las tablas se dividen en varias máquinas. Genero mi propio UUID en PHP que hace el trabajo, estoy seguro de que podrías encontrar algo similar a esto en javascript.

Otro enfoque es utilizar un generador UUID para las claves primarias, ya que es muy poco probable que se produzcan conflictos.

En mi opinión, es más probable que experimente errores al consolidar los contadores de claves primarias en las tablas de DynamoDB alta disponibilidad que a partir de los choques en los UUID generados.

Por ejemplo, en Nodo:

npm install uuid

 var uuid = require('uuid'); // Generate a v1 (time-based) id uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' // Generate a v4 (random) id uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

Tomado de SO respuesta .

He tenido el mismo problema y he creado un pequeño servicio web solo para este propósito. Vea esta publicación del blog, que explica cómo estoy usando stateful.co con DynamoDB para simular la funcionalidad de incremento automático: http://www.yegor256.com/2014/05/18/cloud-autoincrement-counters.html

Básicamente, registra un contador atómico en stateful.co y lo incrementa cada vez que necesita un nuevo valor, a través de la API RESTful. El servicio es gratuito.

Adición a la respuesta de @yadutaf.

AWS soporta contadores atómicos .

Cree una tabla separada ( order_id ) con una fila que contenga el último número de orden:

 +----+--------------+ | id | order_number | +----+--------------+ | 0 | 5000 | +----+--------------+ 

Esto permitirá boost el número de orden en 1 y obtener el resultado incrementado en una callback de AWS DynamoDB:

 config={ region: 'us-east-1', endpoint: "http://localhost:8000" }; const docClient = new AWS.DynamoDB.DocumentClient(config); let param = { TableName: 'order_id', Key: { "id": 0 }, UpdateExpression: "set order_number = order_number + :val", ExpressionAttributeValues:{ ":val": 1 }, ReturnValues: "UPDATED_NEW" }; docClient.update(params, function(err, data) { if (err) { console.log("Unable to update the table. Error JSON:", JSON.stringify(err, null, 2)); } else { console.log(data); console.log(data.Attributes.order_number); // <= here is our incremented result } }); 

🛈 Tenga en cuenta que, en algunos casos excepcionales , pueden ser problemas con la conexión entre el punto de la persona que llama y la API de AWS. El resultado será un incremento en la fila de dynamodb, mientras que obtendrá un error de conexión. Por lo tanto, pueden aparecer algunos valores incrementados no utilizados.

Puede usar data.Attributes.order_number incrementado en su tabla, por ejemplo, para insertar {id: data.Attributes.order_number, otherfields:{}} en la tabla de order .

Para aquellos que codifican en Java, DynamoDBMapper ahora puede generar UUID únicos en su nombre.

DynamoDBAutoGeneratedKey

Marca una clave de partición o una propiedad de clave de clasificación como generada automáticamente. DynamoDBMapper generará un UUID aleatorio al guardar estos atributos. Sólo las propiedades de cadena se pueden marcar como claves generadas automáticamente.

Utilice la anotación DynamoDBAutoGeneratedKey de esta manera

 @DynamoDBTable(tableName="AutoGeneratedKeysExample") public class AutoGeneratedKeys { private String id; @DynamoDBHashKey(attributeName = "Id") @DynamoDBAutoGeneratedKey public String getId() { return id; } public void setId(String id) { this.id = id; } 

Como puede ver en el ejemplo anterior, puede aplicar la anotación DynamoDBAutoGeneratedKey y DynamoDBHashKey al mismo atributo para generar una clave hash única.

Crea el nuevo file.js y pon este código:

 exports.guid = function () { function _p8(s) { var p = (Math.random().toString(16)+"000000000").substr(2,8); return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ; } return (_p8() + _p8(true) + _p8(true)+new Date().toISOString().slice(0,10)).replace(/-/g,""); } 

Luego, puede aplicar esta función a la clave principal id. Se generará el UUID.