Ist es möglich, Ergebnisse mit Abfrage oder Scan in DynamoDB zu BESTELLEN?

83

Ist es möglich, Ergebnisse mit der Abfrage- oder Scan-API in DynamoDB zu BESTELLEN?

Ich muss wissen, ob DynamoDB so etwas wie [ORDER BY 'field'] aus SQL-Abfragen hat.

Vielen Dank.

Samuel Negru
quelle

Antworten:

42

Nicht explizit ist die Bestellung jedoch offensichtlich für viele Anwendungsfälle in der realen Welt erforderlich und kann mit dem Primärschlüssel Hash und Range Type entsprechend modelliert werden :

In diesem Fall besteht der Primärschlüssel aus zwei Attributen. Das erste Attribut ist das Hash-Attribut und das zweite das Bereichsattribut. Amazon DynamoDB erstellt einen ungeordneten Hash-Index für das Hash-Primärschlüsselattribut und einen sortierten Bereichsindex für das Range-Primärschlüsselattribut . [Hervorhebung von mir]

Mit diesem Bereichsindex können Sie dann optional Elemente über den Parameter RangeKeyCondition der Abfrage-API anfordern und über den Parameter ScanIndexForward die Vorwärts- oder Rückwärtsdurchquerung des Index (dh die Sortierrichtung) angeben .

Update: Sie können auf die gleiche Weise nach einem Attribut mit einem lokalen Sekundärindex sortieren .

Steffen Opel
quelle
18
Die ScanIndexForward param scheint nur anwenden Abfrage , nicht Scan korrekt? Wie würde man mit Query eine geordnete paginierte Liste aller Elemente in einer Tabelle zurückgeben? Scan scheint der Weg zu sein, "*" zurückzugeben, aber es scheint keinen Parameter für die Reihenfolge der Ergebnisse zu geben.
case2000
Ich habe diese Funktion nicht verwendet, sondern nur gelesen, aber Query unterstützt die Angabe eines Limits , um die Anzahl der empfangenen Ergebnisse zu begrenzen. Wenn mehr Elemente zu Ihrer Abfrage passen, wenn das Limit erreicht ist, erhalten Sie einen LastEvalencedKey Dies kann verwendet werden, um eine weitere Abfrage durchzuführen und weiterhin Ergebnisse abzurufen.
Fernio
1
Wichtiges Problem: Die zurückgegebenen Ergebnisse werden nicht sortiert. Die Sortierung kommt nur ins Spiel, wenn Sie einen Grenzwert anwenden oder die Anzahl der Elemente das Suchlimit von 1 MB überschreitet. Beispielsweise könnten Sie 5 Datensätze mit dem Partitionsschlüssel 'p1' und den Sortierschlüsseln haben: ['b', 'd', 'a', 'c', 'e']. Wenn Sie nur 'p1' abfragen, erhalten Sie ['b', 'd', 'a', 'c', 'e']. Wenn Sie jedoch ein Limit von 2 angeben, wird ['b', 'a']
jameslol
29

Sie können den Sortierschlüssel verwenden und den Parameter ScanIndexForward in einer Abfrage anwenden , um entweder in aufsteigender oder absteigender Reihenfolge zu sortieren. Hier beschränke ich die zurückgegebenen Artikel auf 1.

var params = {
    TableName: 'Events',
    KeyConditionExpression: 'Organizer = :organizer',
    Limit: 1,
    ScanIndexForward: false,    // true = ascending, false = descending
    ExpressionAttributeValues: {
        ':organizer': organizer
    }
};

docClient.query(params, function(err, data) {
    if (err) {
        console.log(JSON.stringify(err, null, 2));
    } else {
        console.log(JSON.stringify(data, null, 2));
    }
});
kometen
quelle
8
Problem ist, wenn Sie alle Artikel zurückgeben möchten . Im Wesentlichen bedeutet dies, dass Sie eine neue Dummy-Spalte erstellen, allen Zeilen denselben Wert zuweisen, eine GSI für diese Spalte erstellen und die Abfrage anstelle des Scans aufrufen müssen.
JHH
Was ist, wenn ich basierend auf einem Nicht-Schlüsselfeld zurückkehren möchte? wie created_on number field
Yusuf
Dann möchten Sie vielleicht alle Datensätze abrufen und diese dann mit Javascript oder ähnlichem filtern. DynamoDB ist im Grunde ein Schlüsselwertspeicher mit eingeschränkter Funktionalität. Ist aber sehr schnell, wenn Sie die Schlüssel verwenden können.
Kometen
7

Verwenden Sie ScanIndexForward (true für aufsteigend und false für absteigend) und können Sie das Ergebnis auch mithilfe des setLimit-Werts von Query Expression einschränken.

Nachfolgend finden Sie den Code, in dem QueryPage zum Auffinden des einzelnen Datensatzes verwendet wurde.

public void fetchLatestEvents() {
    EventLogEntitySave entity = new EventLogEntitySave();
    entity.setId("1C6RR7JM0JS100037_contentManagementActionComplete");

    DynamoDBQueryExpression<EventLogEntitySave> queryExpression = new DynamoDBQueryExpression<EventLogEntitySave>().withHashKeyValues(entity);
    queryExpression.setScanIndexForward(false);
    queryExpression.withLimit(1);
    queryExpression.setLimit(1);

    List<EventLogEntitySave> result = dynamoDBMapper.queryPage(EventLogEntitySave.class, queryExpression).getResults();
    System.out.println("size of records = "+result.size() );
}

@DynamoDBTable(tableName = "PROD_EA_Test")
public class EventLogEntitySave {

        @DynamoDBHashKey
        private String id;
        private String reconciliationProcessId;
        private String vin;
        private String source;
}

public class DynamoDBConfig {
    @Bean
    public AmazonDynamoDB amazonDynamoDB() {

            String accesskey = "";
            String secretkey = "";
            //
            // creating dynamo client
            BasicAWSCredentials credentials = new BasicAWSCredentials(accesskey, secretkey);
            AmazonDynamoDB dynamo = new AmazonDynamoDBClient(credentials);
            dynamo.setRegion(Region.getRegion(Regions.US_WEST_2));
            return dynamo;
        }

    @Bean
    public DynamoDBMapper dynamoDBMapper() {
        return new DynamoDBMapper(amazonDynamoDB());
    }
}
ABHAY JOHRI
quelle
Verwenden Sie ScanIndexForward (wahr für aufsteigend und falsch für absteigend)
ABHAY JOHRI
1

Wenn Sie boto2 verwenden und den Sortierschlüssel in einer der Spalten in Ihrer Tabelle haben, können Sie das, was Sie abrufen, in der Reihenfolge oder in umgekehrter Reihenfolge sortieren, indem Sie Folgendes sagen:

result = users.query_2(
    account_type__eq='standard_user',
    reverse=True)

Wenn Sie boto3 verwenden und den Sortierschlüssel in der Spalte haben, nach der Sie das Ergebnis sortieren möchten, können Sie die abgerufenen Daten sortieren, indem Sie Folgendes sagen:

result = users.query(
    KeyConditionExpression=Key('account_type').eq('standard_user'),
    ScanIndexForward=True)

Denken Sie in boto3 daran, dass DynamoDB die Ergebnisse in der Reihenfolge zurückgibt, in der sie gespeichert sind (nach Sortierschlüsselwert), wenn ScanIndexForward true ist. Dies ist das Standardverhalten. Wenn ScanIndexForward false ist, liest DynamoDB die Ergebnisse in umgekehrter Reihenfolge nach Sortierschlüsselwert und gibt sie dann an den Client zurück.

Pilatipus
quelle
1

Eine andere Option, die das Problem lösen sollte, ist zu

  1. Definieren Sie einen lokalen Sekundärindex mit dem "normalen" Hash-Schlüssel als Hash-Schlüssel des LSI
  2. Definieren Sie das Feld, das Sie sortieren möchten, als "Sortierschlüssel" des LSI
  3. Fragen Sie die LSI ab und stellen Sie die gewünschte Reihenfolge ein (siehe oben).

Auf diese Weise können Sie jeden Wert Ihrer Tabelle nach Bedarf sortieren. Dies ist eine sehr effiziente Methode, um die Elemente mit dem höchsten Rang in Ihrer Tabelle zu finden, ohne dass die gesamte Abfrage abgerufen und anschließend gefiltert werden muss.

Geole
quelle
Was oben? Wenn der normale Hash für die sortierte ID ungeordnet ist, scheint es nicht zu funktionieren, ihn einzuschließen. Vermisse ich etwas
Samantha Atkins
0

Wenn die Tabelle bereits vorhanden ist, fügen Sie dem gewünschten Attribut für die Tabelle GSI (Global Secondary Index) hinzu und verwenden Sie Abfrage, nicht Scannen. Wenn Sie die Tabelle erstellen möchten, können Sie dem gewünschten Attribut LSI (Local Secondary Index) hinzufügen.

Sharhabeel Hamdan
quelle