Comment puis-je interroger efficacement les attributs imbriqués dans Dynamodb?
J'ai une structure de document comme ci-dessous, qui me permet de stocker des informations connexes dans le document lui-même (plutôt que de le référencer).
Il est logique de stocker les séminaires imbriqués dans le cours, car ils seront probablement interrogés à côté du cours (ils sont tous spécifiques au cours, c'est-à-dire qu'un cours a de nombreux séminaires et qu'un séminaire appartient à un cours).
Dans CouchDB, à partir duquel je migre, je pouvais écrire une vue qui projetterait des attributs imbriqués pour les requêtes. Je comprends que je ne peux pas projeter quoi que ce soit qui n'est pas un attribut de niveau supérieur dans un index secondaire dynamodb, donc cette approche ne semble pas fonctionner.
Cela me ramène à la question: comment puis-je interroger efficacement les attributs imbriqués sans les analyser, si je ne peux pas les utiliser comme clés dans un index?
Par exemple, si je veux obtenir une participation moyenne au Nelson Mandela Theatre, comment puis-je rechercher les valeurs de registrations
et attendees
dans tous les séminaires qui ont un emplacement de "Nelson Mandela Theatre" sans recourir à un scan?
{
“course_id”: “ABC-1234567”,
“course_name”: “Statistics 101”,
“tutors”: [“Cognito-sub-1”, “Cognito-sub-2”],
“seminars”: [
{
“seminar_id”: “XXXYYY-12345”,
“Epoch_time”: “123456789”,
“duration”: “5400”,
“location”: “Nelson Mandela Theatre”,
“name”: “How to lie with statistics”,
“registrations”: “92”,
“attendees”: “61”
},
{
“seminar_id”: “BBBCCC-44444”,
“Epoch_time”: “155555555”,
“duration”: “5400”,
“location”: “Nelson Mandela Theatre”,
“name”: “Statistical significance for dog owners”,
“registrations”: “244”,
“attendees”: “240”
},
{
“seminar_id”: “XXXAAA-54321”,
“Epoch_time”: “223456789”,
“duration”: “4000”,
“location”: “Starbucks”,
“name”: “Is feral cat population growth a leading indicator for the S&P 500?”,
“registrations”: “40”
}
]
}
{
“course_id”: “CJX-5553389”,
“course_name”: “Cat Health 101”,
“tutors”: [“Cognito-sub-4”, “Cognito-sub-9”],
“seminars”: [
{
“seminar_id”: “TTRHJK-43278”,
“Epoch_time”: “123456789”,
“duration”: “5400”,
“location”: “Catwoman Hall”,
“name”: “Emotional support octopi for cats”,
“registrations”: “88”,
“attendees”: “87”
},
{
“seminar_id”: “BBBCCC-44444”,
“Epoch_time”: “123666789”,
“duration”: “5400”,
“location”: “Nelson Mandela Theatre”,
“name”: “Statistical significance for cat owners”,
“registrations”: “44”,
“attendees”: “44”
}
]
}
Impossible de créer un index pour les attributs imbriqués (c'est-à-dire les types de données de document dans Dynamodb).
Types de documents - Un type de document peut représenter une structure complexe avec des attributs imbriqués, comme vous le trouveriez dans un document JSON. Les types de documents sont la liste et la carte.
Api de requête: -
Une opération de requête recherche uniquement les valeurs d'attribut de clé primaire et prend en charge un sous-ensemble d'opérateurs de comparaison sur les valeurs d'attribut de clé pour affiner le processus de recherche.
API d'analyse: -
Une opération d'analyse analyse l'ensemble de la table. Vous pouvez spécifier des filtres à appliquer aux résultats pour affiner les valeurs qui vous sont retournées, après l'analyse complète.
Pour utiliser Query API
, la valeur de la clé de hachage est requise. L'OP ne dispose d'aucune information indiquant qu'une valeur de clé de hachage est disponible. Selon OP, les données doivent être interrogées par l'attribut location
qui se trouve dans le type de données Dynamodb List
. Maintenant, l'option est de regarder GSI.
Veuillez en savoir plus sur le GSI . L'une des règles est que GSI peut être créé en utilisant uniquement des attributs de niveau supérieur. Ainsi, l'emplacement ne peut pas être utilisé pour créer l'index.
Ainsi, la création du GSI afin d'utiliser l'API de requête a également été exclue.
Les attributs de clé d'index peuvent être constitués de tous les attributs de chaîne, de nombre ou binaires de niveau supérieur de la table de base; les autres types scalaires, types de document et types d'ensemble ne sont pas autorisés.
Pour les raisons mentionnées ci-dessus, l'API de requête ne peut pas être utilisée pour obtenir les données basées sur l'attribut location
en supposant que la valeur de la clé de hachage n'est pas disponible.
Si une valeur de clé de hachage est disponible, FilterExpression
peut être utilisé pour filtrer les données. La seule façon de filtrer les données présentes dans le type de données de liste complexe est la fonction CONTAINS
. Pour utiliser la fonction CONTAINS
, tous les attributs de l'occurrence doivent correspondre aux données (c'est-à-dire ID_Séminaire, emplacement, durée et tous les autres attributs). Il n'est donc certainement pas possible de remplir le cas d'utilisation mentionné dans le PO en utilisant le modèle de données actuel.
Solution alternative proposée: -
Une nouvelle modélisation de la structure des données comme mentionné ci-dessous pourrait être une option pour résoudre le problème. Il n'y a certainement aucune autre solution disponible pour répondre au cas d'utilisation à l'aide de l'API de requête.
Tableau principal: -
Identifiant du cours - Clé de hachage
séminaire_id - Clé de tri
GSI: -
Lieu du séminaire - Hash Key
Identifiant du cours - Clé de tri
Dans une table DynamoDB, chaque valeur de clé doit être unique. Cependant, les valeurs clés dans un indice secondaire global n'ont pas besoin d'être uniques.
Maintenant, vous pouvez utiliser l'API de requête sur GSI pour obtenir les données pour Seminar location
est égal à Nelson Mandela Theatre
. Vous pouvez utiliser l'ID du cours dans l'API de requête si vous connaissez la valeur. L'API de requête donnera potentiellement plusieurs éléments dans l'ensemble de résultats. Vous pouvez utiliser FilterExpression
si vous souhaitez filtrer davantage les données en fonction de certains attributs non clés.
Vous pouvez faire une chose pour le faire fonctionner sur Scan Store l'objet au format stringify comme {"language": "[{\" language\": \" Male\", \" proficiency\": \" Female\"} ] "}` `et peut ensuite exécuter la langue de l'opération de numérisation: {contient:" Homme "}
côté client, vous pouvez effectuer JSON.parse (langue)
Vous pouvez utiliser chemins de document pour filtrer les valeurs. Utilisez séminaires.location comme chemin du document.
Je n'ai pas encore une telle expérience avec DynamoDB mais j'ai commencé à l'étudier depuis que je prévois de l'utiliser pour mon prochain projet.
Pour autant que je puisse comprendre de la documentation AWS, la réponse à votre question est: il n'est pas possible d'interroger efficacement les attributs imbriqués.
En regardant Meilleures pratiques , en particulier Meilleures pratiques pour l'utilisation des index secondaires dans DynamoDB , il est possible de comprendre que la bonne approche doit utiliser des types de ligne différents sous la même clé de partition comme indiqué ici . Ensuite, sous le même cours_id, vous auriez une clé de tri générique (sk). Le premier registre aurait alors sk = 'Details' avec les données du cours, puis d'autres registres comme "séminaire-1" et ses données, et ainsi de suite. Vous devez ensuite définir les propriétés du séminaire que vous souhaitez interroger en tant que SGI (indice global secondaire) en gardant à l'esprit qu'il ne peut avoir que 5 SGI par table.
J'espère que ça aide.
Ceci est un exemple de ici où vous utilisez une expression de filtre, c'est avec une opération d'analyse, mais peut-être pouvez-vous appliquer quelque chose de similaire pour la requête au lieu de l'analyse (jetez un oeil à API ):
{
"TableName": "MyTable",
"FilterExpression": "#k_Compatible.#k_RAM = :v_Compatible_RAM",
"ExpressionAttributeNames": {
"#k_Compatible": "Compatible",
"#k_RAM": "RAM"
},
"ExpressionAttributeValues": {
":v_Compatible_RAM": "RAM1"
}
}