web-dev-qa-db-fra.com

Mettre à jour la carte dynamique imbriquée

J'ai une table dynamodb avec un attribut contenant une carte imbriquée et je voudrais mettre à jour un élément d'inventaire spécifique qui est filtré via une expression de filtre qui aboutit à un seul élément de cette carte.

Comment écrire une expression de mise à jour pour mettre à jour l'emplacement à "en place trois" de l'élément avec name = opel, les balises incluent "x1" (et éventuellement aussi f3)? Cela devrait simplement mettre à jour le premier attribut d'emplacement des éléments de la liste.

(
  "inventory": [
    {
      "location": "in place one",      # I want to update this
      "name": "opel",
      "tags": [
        "x1",
        "f3"
      ]
    },
    {
      "location": "in place two",
      "name": "abc",
      "tags": [
        "a3",
        "f5"
      ]
    }],
"User" :"test" 
 } 
10
Nico Müller

Réponse mise à jour - basée sur l'énoncé de question mis à jour

Vous pouvez mettre à jour les attributs dans une carte imbriquée en utilisant expressions de mise à jour de sorte que seule une partie de l'élément soit mise à jour (c.-à-d. DynamoDB appliquerait l'équivalent d'un patch à votre élément) mais, parce que DynamoDB est un base de données de documents, toutes les opérations (Put, Get, Update, Delete etc.) fonctionnent sur l'élément dans son ensemble.

Donc, dans votre exemple, en supposant que User est la clé de partition et qu'il n'y a pas de clé de tri (je n'ai vu aucun attribut qui pourrait être une clé de tri dans cet exemple), une demande de mise à jour pourrait ressembler à ceci :

table.update_item(
  Key={
    'User': 'test'
  },
  UpdateExpression="SET #inv[0].#loc = :locVal",
  ExpressionAttributeNames={
    '#inv': 'inventory',
    '#loc': 'location'
  },
  ExpressionAttributeValues={
    ':locVal': 'in place three',
  },
)

Cela dit, vous devez savoir à quoi ressemble le schéma de l'élément et quels attributs de l'élément doivent être mis à jour exactement.

DynamoDB n'a PAS de moyen de fonctionner sur les sous-éléments. Cela signifie qu'il n'y a aucun moyen de dire à Dynamo d'exécuter une opération telle que "Mettre à jour l'élément, définir la propriété 'location' des éléments du tableau 'inventaire' qui ont une propriété de 'nom' égale à 'opel'"

Ce n'est probablement pas la réponse que vous espériez, mais c'est ce qui est disponible aujourd'hui. Vous pourrez peut-être vous rapprocher de ce que vous voulez en modifiant un peu le schéma.

Si vous devez référencer les sous-éléments par leur nom, peut-être stocker quelque chose comme:

{
  "inventory": {
    "opel": {
       "location": "in place one",      # I want to update this
       "tags": [ "x1", "f3" ]
    },
    "abc": {
       "location": "in place two",
       "tags": [ "a3", "f5" ]
    }
  },
  "User" :"test" 
} 

Votre requête serait alors:

table.update_item(
  Key={
    'User': 'test'
  },
  UpdateExpression="SET #inv.#brand.#loc = :locVal",
  ExpressionAttributeNames={
    '#inv': 'inventory',
    '#loc': 'location',
    '#brand': 'opel'
  },
  ExpressionAttributeValues={
    ':locVal': 'in place three',
  },
)

Mais YMMV car même cela a des limites parce que vous êtes limité à identifier les articles d'inventaire par leur nom (c'est-à-dire que vous ne pouvez toujours pas dire "mettre à jour l'inventaire avec la balise 'x1'"

En fin de compte, vous devez soigneusement réfléchir à la raison pour laquelle vous avez besoin de Dynamo pour effectuer ces opérations complexes à votre place, au lieu d'être précis sur ce que vous souhaitez mettre à jour.

18
Mike Dinescu