Question

I am using the following code querying a dynamodb instance from within a node.js/express framework. The code is querying a table called User which has a hash key primary key of username with no range. It has no local secondary indexes, and 3 global secondary indexes (last_name-first_name, email_last-name, and company_[no range]).

I want to prevent duplicate usernames and duplicate email addresses. I can successfully prevent duplicate usernames but not duplicate email addresses. The docs state the "ComparisonOperator": "NULL" or Exists: false lines should do it (they are mutually exclusive and I do NOT try them at same time). But, only the username validation is 'honored' by the AWS sdk, ie. the code below prevents duplicate usernames from being entered in to the system but duplicate email still occurs.

If I leave both "Expected:" keys out (username and email) the putitem simply adds a new record or updates the existing record with the same username (as documentation states and as I expect) but leaving both in, or just the email key in will NOT prevent duplicate emails in the database. Please help.

thanks

var d = new Date();
var dt = d.getTime();

params = {
    TableName: 'User',
    Expected: {
        "username": {
            Exists: false
            // tried this also ->  "ComparisonOperator": "NULL"
        },
        "email": {
            Exists: false
           // tried this also ->  "ComparisonOperator": "NULL"
        }

    },  
    Item: { 
        username: {S: req.body.username},
        created: {N: "" + dt + ""},
        company: {S: req.body.company},
        fname: {S: req.body.fname},
        lname: {S: req.body.lname},
        companies: {SS: [req.body.company]},
        email: {S: req.body.email},
        is_admin: {S: req.body.is_admin},
        is_vendor: {S: req.body.is_vendor},
        password: {S: req.body.pass}
    }
};

dynamodb.putItem(params, function(err, data) {
    var obj = new Object();
    obj.data = {};
    obj.data.username = req.body.username;
    obj.data.fname = req.body.fname;
    obj.data.lname = req.body.lname;
    obj.data.company = req.body.company;
    obj.data.email = req.body.email;
    obj.data.is_admin = req.body.is_admin;
    obj.data.is_vendor = req.body.is_vendor;
    if (err) {
        obj.status = "false";
        obj.error = err;
    }
    else{
        obj.status = "true";
    }
    res.send(JSON.stringify(obj));  
});
Was it helpful?

Solution

I recommend first doing a query against the email index to check for existence of the email address before creating the new user.

It sounds like you are expecting the update condition to act as a global unique key constraint, similar to what a relational database might offer. DynamoDB only really enforces uniqueness on the primary key attributes. The update condition is only evaluated against the item attributes that are matched by the key. Your conditional update strategy works for username, since username is the primary hash key and a duplicate username would match the same row. The condition on email only guarantees that the email field is null on the one row that matches the username key.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top