2015-09-28 6 views
11

Hier sind meine Anwendungsfälle: Ich habe eine Dynamo-Tabelle mit einem Hash + Bereich Schlüssel. Wenn ich neue Gegenstände in den Tisch lege, möchte ich eine Eindeutigkeitsprüfung durchführen. Manchmal möchte ich garantieren, dass der Hash eindeutig ist (den Bereich ignorierend). Andere Male möchte ich doppelte Hashes zulassen, aber garantiere, dass die Hash- und Bereichskombination eindeutig ist. Wie kann ich das erreichen?DynamoDB - Platzieren Sie Element, wenn Hash (oder Hash-und Bereichskombination) nicht existiert

Ich experimentierte mit attribute_nist_exists. Es scheint den zweiten Fall zu behandeln, wo es die Kombination aus Hash und Schlüssel überprüft. Hier ist ein PHP Beispiel:

$client->putItem(array(
    'TableName' => 'test', 
    'Item' => array(
     'hash' => array('S' => 'abcdefg'), 
     'range' => array('S' => 'some other value'), 
     'whatever' => array('N' => 233) 
    ), 
    'ConditionExpression' => 'attribute_not_exists(hash)' 
)); 

Merkwürdig ist, dass es keine Rolle scheint, wenn ich attribute_not_exists(hash) oder attribute_not_exists(range) verwenden. Beide scheinen genau das Gleiche zu tun. Soll das so funktionieren?

Irgendeine Idee, wie man den Fall behandelt, in dem ich nur hash für Eindeutigkeit überprüfen möchte?

+0

Weitere Experimente zeigen, dass attribute_not_exists diese bizarre Logik folgt: ' attribute_not_exists (any_attribute_that_exists_in_the_table) 'gibt true zurück, wenn die Hash + range-Kombination in der Tabelle nicht existiert, andernfalls wird false zurückgegeben. 'attribute_not_exists (attribute_that_does_not_exist_in_the_table)' gibt immer true zurück. Sekundäre Indizes (global oder lokal) haben keinen Einfluss auf das Verhalten. – mrog

Antwort

18

Sie können nicht. Alle Elemente in DynamoDB werden entweder durch ihre hash oder hash + range (abhängig von Ihrer Tabelle) indiziert. Ein einzelner Hash-Schlüssel kann mehrere Bereichsschlüssel haben.

Sagen Sie zum Beispiel haben Sie die folgenden Elemente:

  1. hash=A,range=1
  2. hash=A,range=2

Sie haben zwei mögliche Ergebnisse:

  1. Wenn Sie versuchen, ein Element zu setzen mit hash=A,range=3 und attribute_not_exists(hash), Sie erhalten true. Es gibt kein Objekt mit hash=A,range=3, das ein Attribut mit dem Namen hash enthält. Wenn Sie stattdessen attribute_not_exists(range) verwenden, gibt es kein Objekt mit der Nummer hash=A,range=3, das ein Attribut mit dem Namen range enthält. Sie erhalten also auch true.

  2. Wenn Sie versuchen, ein Element mit hash=A,range=1 und attribute_not_exists(hash) zu setzen, werden Sie false bekommen es ist ein Element mit hash=A,range=3 dass das ein Attribut hash Namen existiert hat. Wenn Sie stattdessen attribute_not_exists(range) verwenden, gibt es ein Objekt mit hash=A,range=3, das ein Attribut mit dem Namen range enthält.

Was attribute_not_exist effektiv für diese beiden zu tun ist, ist ein nicht das Element Prüfung bestehen.


Mehr in der Tiefe Erklärung:

  • Jedes Element hat sowohl eine hash und ein range Schlüssel
  • Sie führen ein PutItem Anfrage und muss bieten sowohl die hash und range
  • Sie stellen ConditionExpression mit attribute_not_exists entweder hash oderzur VerfügungSchlüssel

Das bedeutet, dass eine von zwei Dinge passieren:

  1. Die hash + range Paar in der Datenbank vorhanden ist.
    • attribute_not_exists(hash) muss true sein
    • attribute_not_exists(range)true
  2. Die hash + range Paar existiert nicht in der Datenbank sein.
    • attribute_not_exists(hash) muss false sein
    • attribute_not_exists(range)false

In beiden Fällen müssen Sie das gleiche Ergebnis, unabhängig davon, ob Sie es auf dem Hash oder Bereich Schlüssel setzen. Sie überprüfen , ob ein Element mit diesem Hash + Bereichsschlüssel bereits existiert.

+0

Ich bin immer noch nicht klar, warum das der Fall ist. Wenn ich ein Element mit dem Hash "123" und dem Bereich "abc" einfüge, verhindert 'attribute_not_exists (hash)', dass ich ein anderes Element mit dem gleichen Hash und Bereich einfügen kann. Aber es wird mich nicht davon abhalten, ein Objekt mit Hash "123" und Bereich "xyz" einzufügen, obwohl es den gleichen Hash wie das erste Element hat. Wie soll ich mit dem Fall umgehen, in dem doppelte Duplikate vermieden werden sollen, auch wenn die Bereichswerte unterschiedlich sind? – mrog

+0

@mrog Das ist wegen der Art, wie 'Hash' +' Bereich' Tabellen entworfen werden. Ein einzelner Hash-Schlüssel kann viele Bereichsschlüssel haben. Jede Kombination aus "Hash" + "Bereich" ** muss eindeutig sein. Werfen Sie einen Blick auf [diese Antwort] (http://stackoverflow.com/a/27348364/627727), um den Unterschied zwischen "hash" und "hash" + "range" zu sehen. – mkobit

+0

Ich verstehe das Konzept eines Hash + Bereichsschlüssel, aber das beantwortet meine Frage nicht. Warum überprüft 'attribute_not_exists (hash)' sowohl den Hash als auch den Bereich? Ist es überhaupt möglich, eine Bedingung zu schreiben, die nur den Hash prüft?Und warum tun 'attribute_not_exists (hash)', 'attribute_not_exists (range)' und 'attribute_not_exists (was auch immer)' alle genau dasselbe? – mrog

3

Sie können UND-Verknüpfung, wenn Ihre Tabelle Hash und Reichweite hat

'ConditionExpression' => 'attribute_not_exists (hash) UND attribute_not_exists (Bereich)'

Verwandte Themen