2016-02-23 5 views
5

Voglio inserire nella tabella utenti solo se userId, email e username non esistono (vuoi che siano unici).
userId è la chiave primaria (chiave hash, tipo di dati: numero).
nome utente e indirizzo email sono attributi non chiave (entrambi stringa).come verificare se l'attributo non chiave esiste già in dynamodb usando ConditionExpression?

Ecco come ho provato:

response = userTable.put_item(
Item={ 
    'userId': userIdNext, 
    'accType': 0, 
    'username': usernameInput, 
    'pwd': hashedPwd, 
    'email': emailInput 
}, 
ConditionExpression = "(attribute_not_exists(userIdNext)) AND (NOT (contains (email, :v_email))) AND (NOT (contains(username, :v_username)))", 
ExpressionAttributeValues={ 
    ":v_email": emailInput, 
    ":v_username": usernameInput 
} 
) 

ho cercato di seguire la documentazione AWS per gli operatori logici e di espressione condizione da qui: AWS Conditional Expressions

ma è inserendo ogni volta in tavola, anche se il nome utente o email esiste già nel db.
(sto dando nuova userIdNext come è chiave primaria e non può essere un duplicato)

Sto usando Python Implementazione boto3

risposta

4

DynamoDB può forzare l'unicità solo per le chiavi della tabella hash-gamma (e non per chiavi di indice secondari globali)

nel tuo caso ci sono 2 opzioni:

1) costringono sul livello di applicazione - di query per i record, e trovare se duplicare

2) aggiungere un altro tavolo DynamoDB con valori hash/intervallo (che può far rispettare uniqeness), è possibile interrogare questa tabella prima di mettere un elemento per la tabella principale

3) utilizzare i blocchi applicativi (memcache ..)

4) uso dont DynamoDB (forse non il suo rispondere alle vostre esigenze)

si riferisce alle risposte qui:

DynamoDB avoid duplicate non-key attributes

DynamoDB consistent reads for Global Secondary Index

+0

ho indici globali secondari per controllare se il nome utente o e-mail esiste già, ma non è Quindi se 2 utenti interrogano allo stesso tempo e ottengono che email1 è disponibile, entrambi inseriscono nella tabella degli utenti e, se non vi è alcun controllo per verificare se e-mail/nome utente non esistono già, abbiamo voci duplicate per email/nome utente – kishorer747

+0

ho modificato la risposta, in questo caso dovresti usare i blocchi applicazione (ad esempio memcache) –

+0

sì, ho una tabella separata che controlla l'univocità sia per il nome utente che per l'email, ma nei casi in cui 2 utenti allo stesso tempo provano a registrarsi stessa email/nome utente, sta inserendo anche wi i duplicati. Grazie. Guarderò dentro le serrature. – kishorer747

1

Ok, ho trovato il bug nella mia applicazione.

Ho provato a fare un oggetto condizionato in DynamoDB ma sto passando una chiave primaria diversa da quella esistente su DynamoDB, a questo punto verrà creato un nuovo oggetto e l'espressione condizionale è stata ignorata.

# id primary key 
id = 123 
# email is only index 
email = "[email protected]" 

item = { 
    "id": id, 
    "email": email 
    "info": { 
    "gender": "male", 
    "country": "Portugal" 
    } 
} 

response = self._table.put_item(Item=item, ConditionExpression="email <> :v_email", ExpressionAttributeValues={":v_email": email}) 

Se si vuole espressioni condizionali funzionano bene su DynamoDB put_item è necessario inviare la stessa chiave primaria di quello che esiste sul DB.

kishorer747, puoi mettere un esempio del tuo codice che lo fa? "Ho gli indici secondari globali per verificare se il nome utente o e-mail esiste già , ma non è atomico, quindi se 2 utenti interrogano allo stesso tempo e ottengono che l'e-mail1 è disponibile, entrambi inseriscono nella tabella degli utenti.E se non v'è alcun controllo per verificare se e-mail/utente non esiste già, abbiamo voci duplicate per e-mail/nomeutente "

+0

puoi menzionare l'utente per attirare la loro attenzione in questo modo: @malmeida ciao! ma dovresti farlo nel commento. – yuyoyuppe

Problemi correlati