amazon dynamodb - pricing - DynamoDB-Poner elemento si el hash(o combinación de hash y rango) no existe
dynamodb tutorial (4)
Cuidado con las palabras clave reservadas .
attribute_not_exists
no funcionará como se esperaba si el attributeName proporcionado coincide con una palabra de la lista reservada. hash
como el range
están reservados y, por lo tanto, requieren la necesidad de solucionar ese problema usando ExpressionAttributeNames
.
El siguiente ejemplo permite la duplicación de claves de partición y solo falla si ya hay un elemento en la tabla con la partición Y la clave de clasificación provistas.
$client->putItem(array(
''TableName'' => ''test'',
''Item'' => array(
''hash'' => array(''S'' => ''abcdefg''),
''range'' => array(''S'' => ''some other value''),
''whatever'' => array(''N'' => 233)
),
''ConditionExpression'' => ''attribute_not_exists(#h) AND attribute_not_exists(#r)'',
''ExpressionAttributeNames'' => array(''#h'' => ''hash'', ''#r'' => ''range'')
));
Y este se aseguraría de que la clave de partición llamada hash
sea única.
$client->putItem(
''TableName'' => ''test'',
''Item'' => array(
''hash'' => array(''S'' => ''abcdefg''),
''range'' => array(''S'' => ''some other value''),
''whatever'' => array(''N'' => 233)
),
''ConditionExpression'' => ''attribute_not_exists(#h)'',
''ExpressionAttributeNames'' => array(''#h'' => ''hash'')
));
Aquí están mis casos de uso: Tengo una tabla de Dynamo con un hash + clave de rango. Cuando coloco nuevos elementos en la tabla, quiero hacer una verificación de singularidad. A veces quiero garantizar que el hash sea único (ignorando el rango). Otras veces quiero permitir hashes duplicados, pero garantizar que la combinación de hash y rango sea única. ¿Cómo puedo lograr esto?
Experimenté con attribute_not_exists. Parece manejar el segundo caso, donde verifica la combinación de teclas hash +. Aquí hay una muestra de PHP:
$client->putItem(array(
''TableName'' => ''test'',
''Item'' => array(
''hash'' => array(''S'' => ''abcdefg''),
''range'' => array(''S'' => ''some other value''),
''whatever'' => array(''N'' => 233)
),
''ConditionExpression'' => ''attribute_not_exists(hash)''
));
Curiosamente, no parece importar si uso attribute_not_exists(hash)
o attribute_not_exists(range)
. Ambos parecen hacer exactamente lo mismo. ¿Es así como se supone que funciona?
¿Alguna idea de cómo manejar el caso en el que solo quiero comprobar el hash
para ver si es único?
Esta versión de explicación tomada del foro de Amazon Aws dice que una búsqueda se verá como un elemento que coincida con una clave hash proporcionada y luego solo verifica si el atributo existe en ese registro. Debería funcionar igual si tienes un hash y un rango de teclas, supongo.
Si una solicitud intenta encontrar un elemento existente con la clave hash "b825501b-60d3-4e53-b737-02645d27c2ae". Si es la primera vez que se utiliza este ID, no habrá ningún elemento y "attribute_not_exists (correo electrónico)" se evaluará como verdadero, la solicitud de Put pasará.
Si esta identificación ya está en uso, habrá un elemento existente. Luego, la expresión de condición buscará un atributo de correo electrónico existente en el elemento existente, si hay un atributo de correo electrónico, la solicitud de colocación fallará, si no hay un atributo de correo electrónico por el que pasará la solicitud de venta.
De cualquier manera, no se compara el valor del atributo "correo electrónico" y no se comprueba si otros elementos de la tabla utilizan el mismo valor de "correo electrónico".
Si el correo electrónico era la clave hash, la solicitud intentará encontrar un elemento existente con la clave hash "[email protected]".
Si hay otro elemento con el mismo valor de correo electrónico, se encontrará un elemento existente. Dado que el correo electrónico es la clave hash, tiene que estar presente en el elemento existente y "attribute_not_exists (correo electrónico)" se evaluará como falso y la solicitud de colocación fallará.
Si no se usa el valor de "correo electrónico" antes de que no se encuentre el elemento existente y "attribute_not_exists (correo electrónico)" se evaluará como verdadero, por lo tanto, la solicitud de transferencia pasará.
Puedes usar la operación AND si tu tabla tiene hash y rango
''ConditionExpression'' => ''attribute_not_exists (hash) AND attribute_not_exists (range)''
Usted no puede Todos los elementos en DynamoDB están indexados por su hash
o hash
+ range
(dependiendo de su tabla).
Una especie de resumen de lo que está pasando hasta ahora:
- Una sola clave hash puede tener múltiples claves de rango.
- Cada elemento tiene un
hash
y una clave derange
- Está realizando una solicitud de
PutItem
y debe proporcionar tanto elhash
como elrange
- Está proporcionando una
ConditionExpression
conattribute_not_exists
en elhash
o en el nombre del atributo derange
- La condición
attribute_not_exists
es simplemente verificar si existe un atributo con ese nombre, no le importa el valor
Veamos un ejemplo. Comencemos con una tabla de claves hash
+ range
con estos datos:
-
hash=A,range=1
-
hash=A,range=2
Hay cuatro casos posibles:
Si intenta poner un elemento con
hash=A,range=3
yattribute_not_exists(hash)
,PutItem
tendrá éxito porqueattribute_not_exists(hash)
evalúa comotrue
. No existe ningún elemento con la clavehash=A,range=3
que cumple la condición deattribute_not_exists(hash)
.Si intentas poner un elemento con
hash=A,range=3
yattribute_not_exists(range)
,PutItem
se realizará correctamente porqueattribute_not_exists(range)
evalúa comotrue
. No existe ningún elemento con la clavehash=A,range=3
que cumple la condición deattribute_not_exists(range)
.Si intenta colocar un elemento con
hash=A,range=1
yattribute_not_exists(hash)
,PutItem
fallará porqueattribute_not_exists(hash)
evalúa comofalse
. Existe un elemento con clavehash=A,range=1
que no cumple la condición deattribute_not_exists(hash)
.Si intentas poner un elemento con
hash=A,range=1
yattribute_not_exists(range)
,PutItem
fallará porqueattribute_not_exists(range)
evalúa comofalse
. Existe un elemento con clavehash=A,range=1
que no cumple la condición deattribute_not_exists(range)
.
Esto significa que una de dos cosas sucederá:
- El par
hash
+range
existe en la base de datos.-
attribute_not_exists(hash)
debe sertrue
-
attribute_not_exists(range)
debe sertrue
-
- El par
hash
+range
no existe en la base de datos.-
attribute_not_exists(hash)
debe serfalse
-
attribute_not_exists(range)
debe serfalse
-
En ambos casos, obtienes el mismo resultado independientemente de si lo pones en el hash o en la clave de rango. La tecla hash
+ range
identifica un solo elemento en toda la tabla, y su condición se está evaluando en ese elemento.
Efectivamente, está ejecutando un "poner este elemento si un elemento con esta clave hash
+ range
aún no existe" .