J'essaie de créer un tableau pour stocker les éléments de ligne de facture dans DynamoDB. Supposons que l'élément soit défini par CompanyCode
, InvoiceNumber
et LineItemId
, le montant et les autres détails de l'élément de campagne.
Un élément unique est défini par la combinaison des 3 premiers attributs. 2 de ces attributs peuvent être identiques pour les différents éléments. Que dois-je sélectionner comme attribut de hachage et attribut de plage?
Je crois que la première option offerte par @ georgeaf99 ne fonctionnera pas, car si vous le faites de cette façon, alors CompanyCode
doit être unique dans le tableau. Par conséquent, un seul article serait autorisé par entreprise. Je pense que la deuxième solution est la seule vraie façon de le faire.
Vous pouvez utiliser CompanyCode
comme clé de hachage, puis tous les autres champs qui se combinent pour rendre l'élément unique (dans ce cas InvoiceNumber
et LineItemId
) doivent être en quelque sorte combiné en une valeur (telle que la concaténation avec un délimiteur de champ), qui serait votre clé de plage. Malheureusement, c'est un peu moche, mais c'est la nature d'une base de données NoSQL comme DynamoDB. Cependant, il vous permettra de stocker avec succès les enregistrements avec l'unicité correcte. Lors de la lecture des enregistrements, si vous ne souhaitez pas analyser le champ combiné dans ses parties individuelles, vous devrez ajouter des champs séparés supplémentaires pour InvoiceNumber
et LineItemID
.
Si vous n'avez pas un grand nombre de factures par entreprise, vous pouvez interroger uniquement avec la clé de hachage et effectuer le filtrage côté client. Si vous avez un grand nombre de factures par entreprise et devez pouvoir interroger uniquement les articles pour une seule facture, je créerais un index secondaire sur CompanyCode et InvoiceNumber.
Pour plus d'efficacité, je proposerais une conception totalement différente. Avec les bases de données NoSQL (et DynamoDB n'est pas différent), nous devons toujours considérer les modèles d'accès en premier. De plus, si possible, nous devons nous efforcer d'adapter toutes nos données dans la même table et plusieurs index. D'après ce que nous avons d'OP et ses commentaires, voici les deux modèles d'accès:
Nous nous demandons maintenant ce qu'est une bonne clé primaire? Traduit pour se demander ce qu'est une bonne clé de partition (PK) et qu'est-ce qu'une bonne clé de tri (SK) et quels index secondaires devons-nous créer et de quel type (local ou global)? Quelques rappels:
KeyConditionExpression
qui vous fournit ensemble d'opérateurs pour le tri et tout le reste (l'un d'eux étant la fonction begins_with (a, substr)
)FilterExpression
si vous avez besoin d'affiner davantage les résultats de la requête (filtre sur les attributs projetés)Il est évident que nous avons affaire à plusieurs entités qui doivent être modélisées et s'inscrire dans la même table. Pour satisfaire à la condition que la clé de partition soit unique sur la table, CompanyCode
est une clé de partition naturelle - je m'assurerais donc que c'est unique. Sinon, vous devez vous demander comment modéliser le deuxième modèle d'accès?
En supposant que nous avons établi l'unicité sur le CompanyCode
simplifions et disons qu'il se présente sous la forme d'un e-mail (ou pourrait être un domaine ou juste un code, mais j'utiliserai l'email pour la démonstration).
Je propose le design comme dans l'image ci-dessous:
CompanyCode
et SK étant InvoiceNumber
peut stocker tous les attributs de cette facture pour cette entreprise.Customer
ce qui me permet de stocker tous les attributs de l'entreprise.InvoiceNumber
) et mon GSI1SK est mes tables PK (CompanyCode
).LineItemId
et SK étant CompanyCode
(toujours unique)InvoiceNumber
et mon GSI1SK est LineItemId
, ce qui correspond aux tables PK.Maintenant, les modèles d'accès pris en charge avec ceci:
CompanyCode=X
Et utilisez KeyConditionExpression
avec l'opérateur =
Sur la clé de tri InvoiceNumber
. Si je veux obtenir tous les articles liés à cette facture, je projetterai l'attribut Items
à l'aide de ProjectionExpression
.BatchGetItem
appel API (en utilisant ma clé composite unique LineItemId+CompanyCode
) Sur la table pour obtenir tous les articles appartenant à ce particulier facture de ce client particulier. (cela vient avec quelques contraintes de BatchGetItem API )CompanyCode=X
Sur PK et utiliser KeyConditionExpression
sur la SK avec begins_with (a, substr)
fonction/opérateur pour obtenir uniquement les factures de la société X et pas les métadonnées sur cette entreprise. Cela me donnera toutes les factures pour une entreprise/un client donné.InvoiceNumber
je peux facilement sélectionner tous les éléments de ligne qui appartiennent à cette facture particulière. N'OUBLIEZ PAS: Les valeurs clés d'un index secondaire global n'ont pas besoin d'être uniques - donc dans mon GSI1 j'aurais pu avoir facture facilement_1 -> (item_1, item_2) puis une autre facture_1 -> (item_1, item_2) mais la différence entre deux articles en GSI serait dans la SK (elle serait associée à différents CompanyCode
(mais pour démonstration) J'ai utilisé facture_1 et facture_2).Comme je suis sûr que vous avez compris que vous ne pouvez pas avoir plus de deux attributs de votre clé primaire (hachage + plage). Ainsi, selon le type de requêtes que vous effectuerez et la taille de vos données, vous pouvez structurer votre table de différentes manières.
(Optimisé pour le type de requête que vous avez mentionné ci-dessus: uniquement CompanyCode
et tous les 3)
Meilleur sol'n pour les ensembles de données de petite/moyenne taille:
CompanyCode
CompanyCode
, puis filtrez vos résultats sur les deux autres attributsSolution optimale pour les grands ensembles de données:
CompanyCode
InvoiceNumber
+ LineItemId