Voici mes cas d'utilisation: J'ai une table Dynamo avec une clé de hachage + plage. Lorsque je mets de nouveaux éléments dans la table, je souhaite effectuer une vérification de l'unicité. Parfois, je veux garantir que le hachage est unique (en ignorant la plage). D'autres fois, je souhaite autoriser les doublons, mais je garantis que la combinaison de hachage et de plage est unique. Comment puis-je accomplir cela?
J'ai expérimenté attribut_not_exists. Il semble traiter le deuxième cas, où il vérifie la combinaison hash + key. Voici un exemple 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)'
));
Bizarrement, peu importe si j'utilise attribute_not_exists(hash)
ou attribute_not_exists(range)
. Ils semblent tous deux faire exactement la même chose. Est-ce ainsi que c'est censé fonctionner?
Une idée de comment gérer le cas où je veux seulement vérifier hash
pour l'unicité?
Tu ne peux pas. Tous les éléments de DynamoDB sont indexés selon leur hash
ou hash
+ range
(en fonction de votre table).
Une sorte de résumé de ce qui se passe jusqu'à présent:
hash
et une clé range
PutItem
et devez fournissez à la fois hash
et range
ConditionExpression
avec attribute_not_exists
sur le nom de l'attribut hash
ou range
attribute_not_exists
vérifie simplement si un attribut portant ce nom existe, peu importe la valeurPassons en exemple. Commençons par une table de clés hash
+ range
avec ces données:
hash=A,range=1
hash=A,range=2
Il y a quatre cas possibles:
Si vous essayez de placer un élément avec hash=A,range=3
et attribute_not_exists(hash)
, la PutItem
réussira car attribute_not_exists(hash)
est évalué à true
. Aucun élément n'existe avec la clé hash=A,range=3
qui remplit la condition de attribute_not_exists(hash)
.
Si vous essayez de placer un élément avec hash=A,range=3
et attribute_not_exists(range)
, la PutItem
réussira car attribute_not_exists(range)
est évalué à true
. Aucun élément n'existe avec la clé hash=A,range=3
qui remplit la condition de attribute_not_exists(range)
.
Si vous essayez de placer un élément avec hash=A,range=1
et attribute_not_exists(hash)
, la variable PutItem
échouera car attribute_not_exists(hash)
est évalué à false
. Un élément existe avec la clé hash=A,range=1
qui ne répond pas à la condition de attribute_not_exists(hash)
.
Si vous essayez de placer un élément avec hash=A,range=1
et attribute_not_exists(range)
, la variable PutItem
échouera car attribute_not_exists(range)
est évalué à false
. Un élément existe avec la clé hash=A,range=1
qui ne répond pas à la condition de attribute_not_exists(range)
.
Cela signifie que l'une des deux choses va se passer:
hash
+ range
existe dans la base de données. attribute_not_exists(hash)
doit être true
attribute_not_exists(range)
doit être true
hash
+ range
n'existe pas dans la base de données. attribute_not_exists(hash)
doit être false
attribute_not_exists(range)
doit être false
Dans les deux cas, vous obtenez le même résultat, que vous le placiez sur la touche Dièse ou Plage. La clé hash
+ range
identifie un seul élément de la table entière et votre condition est en cours d'évaluation sur cet élément.
Vous effectuez effectivement un "mettez cet élément si un élément avec cette clé hash
+ range
n’existe pas déjà".
Cette version de l'explication provient de Amazon aws forum indique qu'une recherche recherchera un élément qui correspond à une clé de hachage fournie, puis vérifie uniquement si l'attribut existe dans cet enregistrement. Cela devrait fonctionner de la même manière si vous avez un hash et une clé de plage, je suppose.
Si une requête tente de trouver un élément existant avec une clé de hachage "b825501b-60d3-4e53-b737-02645d27c2ae". Si c'est la première fois, cet identifiant est utilisé, il n'y aura pas d'article existant et "attribut_not_existe (email)" sera évalué à vrai, la demande de vente sera traverser.
Si cet identifiant est déjà utilisé, il y aura un élément existant. Ensuite expression de condition recherchera un attribut de courrier électronique existant dans le fichier élément existant, s'il existe un attribut de courrier électronique, la demande de mise en place sera échec, s’il n’ya pas d’attribut email dans lequel la demande de vente sera traitée.
Quoi qu'il en soit, il ne s'agit pas de comparer la valeur de l'attribut "email" et il s'agit de ne pas vérifier si d'autres éléments de la table utilisaient la même valeur "email".
Si l'email était la clé de hachage, alors request essaiera de trouver un fichier .__ existant. élément avec la clé de hachage "[email protected]".
S'il existe un autre élément avec la même valeur de courrier électronique, un élément existant sera être trouvé. Puisque le courrier électronique est la clé de hachage, il doit être présent dans le fichier L'élément existant et "attribut_not_existe (email)" sera évalué à false et mettre la demande échouera.
Si "email", la valeur n'est pas utilisée avant que l'élément existant ne soit pas trouvé. et "attribut_not_exists (email)" sera évalué à true d'où Put demande va passer.
Vous pouvez utiliser l'opération AND si votre table a hash et range
'ConditionExpression' => 'attribut_not_exists (dièse) ET attribut_not_exists (plage)'
Attention avec mots-clés réservés .attribute_not_exists
ne fonctionnera pas comme prévu si le nom d'attribut fourni correspond à un mot de la liste réservée. hash
et range
sont tous deux réservés et nécessitent donc de contourner ce problème en utilisant ExpressionAttributeNames
.
L'exemple suivant autorise les clés de partition en double et n'échoue que s'il existe déjà un élément dans la table avec la clé de partition ET de partition fournie.
$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')
));
Et celui-ci s’assurerait que la clé de partition nommée hash
est unique.
$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')
));