web-dev-qa-db-fra.com

Comment demander un attribut inexistant (nul) dans DynamoDB

J'essaie d'interroger une table DynamoDB pour trouver tous les éléments où l'attribut email n'est pas défini. Un index secondaire global appelé EmailPasswordIndex existe sur la table qui inclut le champ email.

var params = {
    "TableName": "Accounts",
    "IndexName": "EmailPasswordIndex",
    "KeyConditionExpression": "email = NULL",
};

dynamodb.query(params, function(err, data) {
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
});

Résultat:

{
  "message": "Invalid KeyConditionExpression: Attribute name is a reserved keyword; reserved keyword: NULL",
  "code": "ValidationException",
  "time": "2015-12-18T05:33:00.356Z",
  "statusCode": 400,
  "retryable": false
}

Définition du tableau:

var params = {
    "TableName": "Accounts",
    "KeySchema": [
        { "AttributeName": "id", KeyType: "HASH" }, // Randomly generated UUID
    ],
    "AttributeDefinitions": [
        { "AttributeName": "id", AttributeType: "S" },
        { "AttributeName": "email", AttributeType: "S" }, // User e-mail.
        { "AttributeName": "password", AttributeType: "S" }, // Hashed password.
    ],
    "GlobalSecondaryIndexes": [
        {
            "IndexName": "EmailPasswordIndex",
            "ProvisionedThroughput": {
                "ReadCapacityUnits": 1,
                "WriteCapacityUnits": 1
            },
            "KeySchema": [
                { "AttributeName": "email", KeyType: "HASH" },
                { "AttributeName": "password", KeyType: "RANGE" },
            ],
            "Projection": { "ProjectionType": "ALL" }
        },
    ],
    ProvisionedThroughput: {       
        ReadCapacityUnits: 1, 
        WriteCapacityUnits: 1
    }
};

dynamodb.createTable(params, function(err, data) {
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
});
21
Jordan Mack

Les index secondaires globaux de DynamoDB permettent aux index d'être clairsemés. Cela signifie que si vous avez un GSI dont la clé de hachage ou de plage pour un élément n'est pas définie, cet élément ne sera tout simplement pas inclus dans le GSI. Ceci est utile dans un certain nombre de cas d'utilisation car il vous permet d'identifier directement les enregistrements qui contiennent certains champs. Cependant, cette approche ne fonctionnera pas si vous recherchez l'absence de champ.

Pour obtenir tous les éléments dont le champ n'est pas défini, votre meilleur pari peut être de recourir à une analyse avec un filtre. Cette opération sera très coûteuse mais ce serait du code simple ressemblant à ceci:

var params = {
    TableName: "Accounts",
    FilterExpression: "attribute_not_exists(email)"
};

dynamodb.scan(params, {
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
});
36
JaredHatfield

@jaredHatfield est correct si le champ n'existe pas mais cela ne fonctionnera pas si le fichier est nul. NULL est un mot-clé et ne peut pas être utilisé directement. Mais vous pouvez l'utiliser avec ExpressionAttributeValues.

const params = {
    TableName: "Accounts",
    FilterExpression: "attribute_not_exists(email) or email = :null",
    ExpressionAttributeValues: {
        ':null': null
    }
}

dynamodb.scan(params, (err, data) => {
    if (err)
        console.log(JSON.stringify(err, null, 2));
    else
        console.log(JSON.stringify(data, null, 2));
})
13
Mardok