web-dev-qa-db-fra.com

Pourquoi l’analyse DynamoDB avec Limit et FilterExpression ne renvoie-t-elle pas les éléments correspondant aux exigences du filtre?

J'ai besoin de faire un scan avec limite et une condition sur DynamoDB.

Le docs dit:

Dans une réponse, DynamoDB renvoie tous les résultats correspondants dans l'étendue de la valeur Limite. Par exemple, si vous émettez une requête ou une requête d'analyse avec une valeur limite de 6 et sans expression de filtre, DynamoDB renvoie les six premiers éléments de la table correspondant aux conditions de clé spécifiées dans la demande (ou uniquement les six premiers éléments de la demande). le cas d'un Scan sans filtre). Si vous fournissez également une valeur FilterExpression, DynamoDB renverra les éléments des six premiers qui correspondent également aux exigences du filtre (le nombre de résultats renvoyés sera inférieur ou égal à 6).


Le code (NODEJS):

var params = {
    ExpressionAttributeNames: {"#user": "User"},
    ExpressionAttributeValues: {":user": parseInt(user.id)},
    FilterExpression: "#user = :user and attribute_not_exists(Removed)",
    Limit: 2,
    TableName: "XXXX"
};

DynamoDB.scan(params, function(err, data) {
    if (err) {
        dataToSend.message = "Unable to query. Error: " + err.message;
    } else if (data.Items.length == 0) {
        dataToSend.message = "No results were found.";
    } else {
        dataToSend.data = data.Items;
        console.log(dataToSend);
    }
});



Définitions du tableau XXXX:

  • Clé de partition principale: utilisateur (nombre)
  • Clé de tri primaire: Identifiant (Chaîne)
  • INDICE:
    • Nom d'index: RemovedIndex
    • Type: GSI
    • Clé de partition: Supprimée (Nombre)
    • Clé de tri: -
    • Attributs: ALL


Dans le code ci-dessus, si je supprime le paramètre Limit, DynamoDB renverra les éléments correspondant aux exigences du filtre. Donc, les conditions sont ok. Mais lorsque je numérise avec le paramètre Limit, le résultat est vide.

La table XXXX, a 5 éléments. Seuls les 2 premiers ont l'attribut Removed. Lorsque j'analyse sans le paramètre Limit, DynamoDB renvoie les 3 éléments sans l'attribut Removed.

Qu'est-ce que je fais mal?

8
Gabriel Cunha

Parmi les documents que vous avez cités:

Si vous fournissez également une valeur FilterExpression, DynamoDB renverra les Éléments dans les six premiers qui correspondent également aux exigences du filtre.

En combinant Limit et FilterExpression, vous avez demandé à DynamoDB de ne regarder que les deux premiers éléments du tableau et d’évaluer FilterExpression par rapport à ces éléments. Limiter dans DynamoDB peut être déroutant, car il fonctionne différemment de limit dans une expression SQL dans un SGBDR.

15
Mark B

Également rencontré ce problème, je suppose que vous aurez juste à parcourir la table entière jusqu'à un maximum de 1 Mo

Scan Le résultat d'une numérisation est limité à 1 Mo par appel. Vous pouvez utiliser la variable LastEvaluatedKey de la réponse d'analyse pour extraire davantage de résultats.

http://docs.aws.Amazon.com/amazondynamodb/latest/developerguu/Limits.html

1
Samuel Okpapi

Vous pourriez peut-être obtenir ce dont vous avez besoin en utilisant un index secondaire. En utilisant l’exemple classique RDB, exemple client - commande: vous disposez d’une table pour les clients et d’une autre pour les commandes. La table Commandes a une clé composée de Client - HASH, Commande - GAMME. Donc, si vous vouliez obtenir les 10 derniers ordres, il n'y aurait aucun moyen de le faire sans un scan

Mais si vous créez un index secondaire global sur des ordres de "Some Constant" - HASH, Date RANGE et interrogé sur cet index, la requête fera ce que vous voulez et ne vous facturera que pour les UCR impliquées dans les enregistrements renvoyés. Aucun scan coûteux nécessaire. Notez que les écritures seront plus chères, mais dans la plupart des cas, il y a beaucoup plus de lectures que d'écritures. 

Maintenant, vous avez votre problème initial si vous voulez obtenir les 10 plus grosses commandes pour un jour supérieur à 1000 $. La requête renverrait les 10 dernières commandes, puis filtrerait celles de moins de 1 000 dollars.

Dans ce cas, vous pouvez créer une clé calculée avec Date-OrderAmount, et les requêtes sur cet index renvoient ce que vous voulez.

Ce n'est pas aussi simple que SQL, mais vous devez également penser aux modèles d'accès en SQL. Si vous avez beaucoup de données, vous devez créer des index en SQL ou la base de données se fera un plaisir de classer les analyses en votre nom, ce qui compromettrait les performances et augmenterait vos coûts.

Notez que tout ce que j'ai proposé est normalisé dans le sens où il n'y a qu'une source de vérité. Vous ne dupliquez pas de données, vous ne faites que redistribuer des vues pour obtenir ce dont vous avez besoin de DynamoDB.

N'oubliez pas que CONSTANT, en tant que hachage, est soumis à une limite de 10 Go par partition. Vous devez donc vous y adapter si vous avez beaucoup de données actives. Par exemple, en fonction de votre modèle d'accès attendu, vous pouvez utiliser Client et non une constante en tant que HASH. Ou utilisez STreams pour organiser les données (ou sous-ensembles) d'une autre manière. 

1
Andy Brand

Petit hack - Itérer jusqu'à ce que vous obteniez les résultats 

lastEvaluatedKey = null;
do {

    if(lastEvaluatedKey != null) {
        // query or scan data with last evaluated key 
    } else {
        // query or scan data WITHOUT last evaluated key 
    }        

    lastEvaluatedKey == key of last item retrieved

} while(lastEvaluatedKey != null && retrievedResultSize == 0); // == 0 or < yourLimit

Si le nombre d'éléments récupérés est 0 et lastEvaluatedKey n'est pas null, cela signifie qu'il a analysé ou interrogé le nombre de lignes correspondant à votre limite. (et la taille du résultat est zéro car ils ne correspondaient pas à l'expression du filtre)

0
Naween Niroshan