2016-02-23 3 views
5

Ich möchte nur in Benutzer Tabelle einfügen, wenn userId, E-Mail und Benutzername nicht existiert (wollen diese eindeutig sein).
userId ist der Primärschlüssel (Hash-Schlüssel, Datentyp - Zahl).
Benutzername und E-Mail sind Nicht-Schlüsselattribute (beide Zeichenfolge).Wie überprüft man, ob das Nicht-Schlüssel-Attribut in Dynamodb bereits mit ConditionExpression existiert?

Hier ist, wie ich versuchte:

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 
} 
) 

Ich habe versucht, von hier aus der aws Dokumentation für logische Operatoren und Bedingungsausdruck zu folgen: AWS Conditional Expressions

Aber es jedes Mal in der Tabelle einfügt, auch wenn Benutzername oder E-Mail existiert bereits in der Datenbank.
(Ich gebe neue userIdNext wie es Primärschlüssel ist und kann kein Duplikat sein) nur für Hash-Bereich Tabellenschlüssel Einzigartigkeit zwingen

Ich verwende Python Implementierung boto3

Antwort

4

DynamoDB kann (und nicht für globaler Sekundärindexschlüssel)

in Ihrem Fall gibt es 2 Möglichkeiten:

1) zwingen sie auf Anwendungsebene - Abfrage für Aufzeichnungen und finden, wenn doppelte

2) fügen Sie eine weitere DynamoDB Tabelle mit Hash/Bereichswerte (das uniqeness erzwingen kann), können Sie diese Tabelle abfragen, bevor ein Element in der Haupttabelle setzen

3) verwenden Anwendung Schlösser (memcache ..)

4) nicht DynamoDB verwenden (vielleicht ist es nicht Ihre Anforderungen beantworten)

meinen Sie Antworten hier:

DynamoDB avoid duplicate non-key attributes

DynamoDB consistent reads for Global Secondary Index

+0

i Globale Sekundärindizes haben zu prüfen, ob Benutzernamen oder E-Mails bereits vorhanden ist, aber es ist nicht Wenn also 2 Benutzer gleichzeitig abfragen und erhalten, dass email1 verfügbar ist, fügen sie beide in die users Tabelle ein und wenn es keine Prüfung gibt, um zu überprüfen, ob email/username bereits existiert, haben wir doppelte Einträge für email/username – kishorer747

+0

Ich habe die Antwort bearbeitet, in diesem Fall sollten Sie Anwendungssperren verwenden (zB memcache) –

+0

Ja, ich habe eine separate Tabelle, die nach Eindeutigkeit für Benutzername und E-Mail sucht, aber in Fällen, in denen 2 Benutzer gleichzeitig versuchen, sich zu registrieren gleiche E-Mail/Benutzername, es fügt sogar wi ein th die Duplikate. Vielen Dank. Ich werde in Schlösser schauen. – kishorer747

1

Ok, ich habe den Fehler in meiner Anwendung gefunden.

Ich versuche, ein bedingtes Put-Element an DynamoDB zu tun, aber ich übergebe einen anderen Primärschlüssel, der in DynamoDB existiert, an dieser Stelle wird ein neues Objekt erstellt und bedingter Ausdruck wurde ignoriert.

# 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}) 

Wenn Sie möchten, bedingte Ausdrücke auf DynamoDB funktionieren put_item Sie sollten den gleichen Primärschlüssel des einen senden, die auf DB vorhanden ist.

kishorer747, können Sie eine Probe Ihres Code zu setzen, die dies tun? „Ich habe Globale Sekundärindizes zu überprüfen, ob Benutzernamen oder E-Mails bereits vorhanden ist, aber es ist nicht atomar. Also, wenn zwei Benutzer gleichzeitig abzufragen und bekommen, dass email1 verfügbar ist, sie legen sowohl in Benutzer-Tabelle.Und wenn es keine Kontrolle, um zu überprüfen, wenn E-Mail/Benutzername nicht bereits existiert, haben wir doppelte Einträge für E-Mail/Benutzername "

+0

können Sie erwähnen, Benutzer, um ihre Aufmerksamkeit wie folgt zu bekommen: @ Malmeida Hallo! aber du solltest das im Kommentar tun. – yuyoyuppe