web-dev-qa-db-fra.com

DynamoDB à la fois

J'utilise DynamoDB et je dois mettre à jour un attribut spécifique sur plusieurs enregistrements. Écrire mon exigence en pseudo-langage Je voudrais faire une mise à jour disant "update table persons set relationshipStatus = 'marié' où personKey IN (key1, key2, key3, ...)" (en supposant que personKey est la clé dans ma table DynamoDB).

En d'autres termes, je souhaite effectuer une mise à jour avec une clause IN ou je suppose que l'on pourrait l'appeler une mise à jour par lot. J'ai trouvé this lien qui demande explicitement si une opération telle qu'une mise à jour par lots existe et la réponse à cela est que ce n'est pas le cas. Il ne mentionne cependant pas les clauses IN. La documentation montre que les clauses IN sont prises en charge dans ConditionalExpressions (100 valeurs peuvent être fournies à la fois). Cependant, je ne suis pas sûr qu'une telle clause IN convienne à ma situation car je dois toujours fournir un attribut KEY obligatoire (qui attend une valeur unique semble-t-il, je me trompe peut-être) et je crains qu'elle ne fasse analyse complète de la table pour chaque mise à jour.

Ma question est donc la suivante: comment réaliser une mise à jour simultanée sur plusieurs enregistrements DynamoDB? Pour le moment, il semble presque que j'aurai à appeler une déclaration de mise à jour pour chaque clé une par une, ce qui me semble tout simplement faux.

7
Stanley

Comme vous l'avez indiqué, DynamoDB ne prend pas en charge les opérations de mise à jour par lots. Vous devez interroger et obtenir les clés pour tous les enregistrements que vous souhaitez mettre à jour. Parcourez ensuite cette liste en mettant à jour chaque élément un par un.

16
Mark B

Je ne sais pas si cela a changé depuis que la réponse a été donnée mais c'est possible maintenant

Voir la documentation: https://docs.aws.Amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html

Je l'ai utilisé comme ceci en javascript (en mappant les nouveaux blocs sur un tableau d'objets avec la structure souhaitée:

let params = {}
let tableName = 'Blocks';

params.RequestItems[tableName] = _.map(newBlocks, block => {
    return {
        PutRequest: {
            Item: {
                'org_id': orgId,
                'block_id': block.block_id,
                'block_text': block.block_text
            },
            ConditionExpression: 'org_id <> :orgId AND block_id <> :block_id',
            ExpressionAttributeValues: {
                ':orgId': orgId,
                ':block_id': block.block_id
            }
        }
    }
})

docClient.batchWrite(params, function(err, data) {
   .... and do stuff with the result

Vous pouvez même mélanger puts et deletes

Et si vous utilisez des dynogels (vous ne pouvez pas les mélanger à cause de la prise en charge de dynogels, mais vous pouvez le faire pour les mettre à jour (utilisez create parce que dans les coulisses, il lance la fonction batchWrite en tant que put)

var item1 = {email: '[email protected]', name: 'Foo 1', age: 10};
var item2 = {email: '[email protected]', name: 'Foo 2', age: 20};
var item3 = {email: '[email protected]', name: 'Foo 3', age: 30};

Account.create([item1, item2, item3], function (err, acccounts) {
  console.log('created 3 accounts in DynamoDB', accounts);
});

Notez ceci à partir des limitations de DynamoDB ( des docs ):

L'opération BatchWriteItem ajoute ou supprime plusieurs éléments dans une ou plusieurs tables. Un seul appel à BatchWriteItem peut écrire jusqu'à 16 Mo de données, pouvant contenir jusqu'à 25 demandes de vente ou de suppression. Les éléments individuels à écrire peuvent atteindre 400 Ko.

Si je me souviens bien, je pense que dynogels divise les demandes en mandrins de 25 avant de les envoyer, puis de les rassembler dans une promesse et renvoie (bien que je ne sois pas sûr à 100% à ce sujet) - sinon une fonction d'emballage être assez simple à assembler 

2
Simon Pertersen