2016-03-04 76 views
-1

我有一个lambda Node.js的功能,像这样:发送和确认LAMBDA代码DynamoDB

function storeUser(email, username, password, salt, fn) { 
    // Bytesize 
    var len = 128; 
    crypto.randomBytes(len, function(err, token) { 
     if (err) return fn(err); 
     token = token.toString('hex'); 
     dynamodb.putItem({ 
      TableName: "Users", 
      Item: { 
       email: { 
        S: email 
       }, 
       username: { 
        S: username 
       }, 
       passwordHash: { 
        S: password 
       }, 
       passwordSalt: { 
        S: salt 
       }, 
       verified: { 
        BOOL: false 
       }, 
       verifyToken: { 
        S: token 
       } 
      }, 
      ConditionExpression: 'attribute_not_exists (email)' 
     }, function(err, data) { 
      if (err) return fn(err); 
      else fn(null, token); 
     }); 
    }); 
} 

事件处理程序是,像这样:

exports.handler = function(event, context) { 
    var email = event.email; 
    var username = event.username; 
    var clearPassword = event.password; 

    computeHash(clearPassword, function(err, salt, hash) { 
     if (err) { 
      context.fail('Error in hash: ' + err); 
     } else { 
      storeUser(email, username, hash, salt, function(err, token) { 
       if (err) { 
        if (err.code == 'ConditionalCheckFailedException') { 
         // userId already found 
         context.succeed({ 
          created: false 
         }); 
        } else { 
         context.fail('Error in storeUser: ' + err); 
        } 
       } else { 
        context.succeed({ 
         created: true 
        }); 
       } 
      }); 
     } 
    }); 
} 

我想使用户名和电子邮件独特。我如何确保在写入数据库时​​,如果其中一个(或两者)不是唯一的,则返回一个错误,说哪个不是唯一的?

+0

你的问题的标题是没有意义的。看看你的代码,你已经在使用ConditionExpression来强制执行唯一的电子邮件地址,只是对你想要强制执行唯一性的其他属性做同样的事情。 –

+0

阅读最后一行:我想知道哪一个不是唯一的(得到一个错误,说哪个不是唯一的?) – cdub

回答

2

这是一个快速和肮脏的方式来做到这一点。这不是非常有效,但它能够完成任务:为什么我说这是在做那是因为你做查询的肮脏的方式

const // You want const because no required packages ever change at runtime 
    AWS = require('aws-sdk'), 
    ddb = new AWS.DynamoDB(); 

exports.handler = function(event, context) { 
    // QUERY USERNAME FIRST 
    var table = 'tableName'; 
    var paramsUNCheck = { 
     TableName : table, 
     ProjectionExpression : 'hash', 
     KeyConditionExpression : 'hash = :v_hash AND range = :v_rng', 
     ExpressionAttributeValues : { 
      ':v_hash' : { S : 'hash' }, 
      ':v_rng' : { S : event.username } 
     } 
    } 

    ddb.query (paramsUNCheck, function(err, data) { 
     if (err) { 
      context.fail (JSON.stringify(err, null, 2)) 
     } else { 
      if (data.Count === 0) { 
       var paramsEMCheck = { 
        TableName : table, 
        ProjectionExpression : 'hash', 
        KeyConditionExpression : 'hash = :v_hash', 
        FilterExpression : 'email = :v_eml', 
        ExpressionAttributeValues : { 
         ':v_hash' : { S : 'hash' }, 
         ':v_eml' : { S : event.email } 
        } 
       } 
       ddb.query (paramsEMCheck, function(err, data) { 
        if (err) { 
         context.fail (JSON.stringify(err, null, 2)) 
        } else { 
         if (data.Count === 0) { 
          // REGISTER IF IT PASSES ALL CHECKS 
          var paramsReg = { 
           TableName : table, 
           Item : { 
            'hash' : { S : 'hash' }, 
            'username' : { S : event.username }, 
            'password' : { S : event.password }, 
            'email' : { S : event.email } 
           } 
          } 
          ddb.putItem (paramsReg, function (err, data) { 
           if (err) context.fail (JSON.stringify(err, null, 2)); 
           else 
            context.succeed ({ done: 'yes' }); 
          }); 
         } else { 
          context.succeed ('Email already used, please try again.') 
         } 
        } 
       }); 
      } else { 
       context.succeed ('Username taken, please try again.') 
      } 
     } 
    }) 
}; 

现在的原因。

随着中说,运行读取比运行写道:显著便宜。造成这种疯狂的原因:

对于大小超过4 KB的项目,一个读取容量单位=每秒一次强烈一致的读取或两次最终一致读取。

对于大小不超过1 KB的项目,一个写入容量单位=每秒写入一次。

基本上,它是便宜的方式来运行两个读请求,然后一个写请求。每临时吞吐量的成本约为0.09美元/读取吞吐量和约0.48美元/写入吞吐量。

但是,等等,你不需要写一个吗?那么,是的,你这样做,但它是一个写应该总是成功。如果你有一个用户不断点击那个lambda?你需要阅读第一道防线,而不是写作。基本上我尽可能便宜。如果它意味着没有“提高”写入(在合理的范围内),我会整天研究吞吐量。

的另一种方式做到这一点Conditional Writes,你会想检查begins_with [email protected]一路到底 - 基本上迫使满弦的检查,所以忽略了“开头”。

+0

什么是散列? v_hash – cdub

+0

@cdub,yup。 :v是值 – iSkore

+0

我必须看看散列值和范围如何作为组合键 – cdub