Im vorherigen Modul haben Sie Ihrer Tabelle einen invertierten Index hinzugefügt. Dieser invertierte Index fügt zusätzliche Abfragemuster für relationale Daten hinzu. Wir haben allerdings erkannt, dass noch immer ein Problem besteht. Auch wenn wir alle Freundschafts-Entitäten für eine bestimmte Benutzer-Entität abfragen können, enthält die Freundschafts-Entität keine Informationen über den Benutzer, dem gefolgt wird.

In diesem Modul werden Sie die partielle Normalisierung kennenlernen.

Im zweiten Modul haben wir gesehen, dass Sie beim Modellieren mit DynamoDB nicht versuchen sollten, ein relationales Muster zu fälschen. Ein Core-Tenant des relationalen Modells ist die Normalisierung von Daten, bei der Sie vermeiden, Daten an mehreren Stellen zu duplizieren. Die Normalisierung bietet ein schönes Muster in relationalen Datenbanken, doch Sie benötigen möglicherweise kostspielige Verknüpfungen, um Ihre Daten bei der Abfrage wieder zusammenzusetzen.

Bei DynamoDB sollten Sie Ihre Daten häufig denormalisieren. Die Denormalisierung hilft, Verknüpfungen zu vermeiden und die Abfrageleistung zu verbessern. Um dies zu bewerkstelligen können Sie Attribute von einem Element in ein anderes Element kopieren, das auf ersteres verweist. So können Sie vermeiden, dass beide Elemente während einer Abfrage abgerufen werden.

Es gibt allerdings Situationen, in denen die Denormalisierung Ihr Datenmodell komplizieren kann. Das Datenmodell verfügt beispielsweise über eine Freundschafts-Entität, die sich sowohl auf einen Benutzer bezieht, dem gefolgt wird, als auch auf einen verfolgenden Benutzer. Sie könnten alle Attribute von jeder Benutzer-Entität in die Freundschafts-Entität kopieren, wenn Sie die Freundschafts-Entität erstellen. Wenn Sie anschließend die Freundschafts-Entität abrufen, liegen Ihnen auch alle Details zu beiden Benutzern vor.

Dies kann ein Problem darstellen, wenn ein Benutzer Informationen in seinem Profil ändert. Wenn ein Benutzer beispielsweise sein Profilbild ändert, sind die Daten in jeder Freundschafts-Entität, die diesen Benutzer enthält, veraltet. Sie müssten jede Freundschafts-Entität, die den Benutzer enthält, bei jeder Aktualisierung aktualisieren.

In den folgenden Schritten erfahren Sie, wie Sie die partielle Normalisierung und den BatchGetItem-API-Aufruf verwenden, um diese Situation zu bewältigen.

Veranschlagte Zeit für das Modul: 20 Minuten


  • Schritt 1: Verwenden der partiellen Normalisierung, um „gefolgte Benutzer“ zu finden

    In diesem Schritt sehen Sie, wie Sie „gefolgte Benutzer“ finden. Bei diesen handelt es sich um die Benutzer, denen ein bestimmter Benutzer in Ihrer Anwendung folgt. Sie werden ebenfalls herausfinden, wie Sie alle Daten über die Benutzer abrufen, denen gefolgt wird.

    Wie in der Einführung zu diesem Modul erwähnt, möchten Sie möglicherweise die partielle Normalisierungstechnik für Freundschaften und Benutzer verwenden. Anstatt die vollständigen Informationen zu jedem Benutzer in der Freundschafts-Entität zu speichern, können Sie mithilfe der BatchGetItem-API Informationen zu einem Benutzer in einer Freundschafts-Entität abrufen.

    In dem Code, den Sie heruntergeladen haben, gibt es im Verzeichnis application/ eine Datei namens find_and_enrich_following_for_user.py. Der Inhalt dieses Skripts ist wie unten dargestellt.

    import boto3
    
    from entities import User
    
    dynamodb = boto3.client('dynamodb')
    
    USERNAME = "haroldwatkins"
    
    
    def find_and_enrich_following_for_user(username):
        friend_value = "#FRIEND#{}".format(username)
        resp = dynamodb.query(
            TableName='quick-photos',
            IndexName='InvertedIndex',
            KeyConditionExpression="SK = :sk",
            ExpressionAttributeValues={":sk": {"S": friend_value}},
            ScanIndexForward=True
        )
    
        keys = [
            {
                "PK": {"S": "USER#{}".format(item["followedUser"]["S"])},
                "SK": {"S": "#METADATA#{}".format(item["followedUser"]["S"])},
            }
            for item in resp["Items"]
        ]
    
        friends = dynamodb.batch_get_item(
            RequestItems={
                "quick-photos": {
                    "Keys": keys
                }
            }
        )
    
        enriched_friends =  [User(item) for item in friends['Responses']['quick-photos']]
    
        return enriched_friends
    
    
    
    follows = find_and_enrich_following_for_user(USERNAME)
    
    print("Users followed by {}:".format(USERNAME))
    for follow in follows:
        print(follow)

    Die Funktion find_and_enrich_following_for_user ähnelt der Funktion find_follower_for_user , die Sie im letzten Modul verwendet haben. Die Funktion akzeptiert einen Benutzernamen, für den Sie die gefolgten Benutzer suchen möchten. Zunächst verwendet die Funktion den invertierten Index für eine Abfrageanforderung, um alle Benutzer zu finden, denen der angegebene Benutzername folgt. Anschließend wird ein BatchGetItem zusammengestellt, um die vollständige Benutzer-Entität für jeden der gefolgten Benutzer abzurufen und diese Entitäten zurückzugeben.

    Dies führt zu zwei Anforderungen an DynamoDB anstelle von einer, wie es ideal wäre. Es erfüllt jedoch ein ziemlich komplexes Zugriffsmuster und vermeidet so die Notwendigkeit, Freundschafts-Entitäten jedes Mal zu aktualisieren, wenn ein Benutzerprofil aktualisiert wird. Diese partielle Normalisierung kann ein großartiges Werkzeug für Ihre Modellierungsanforderungen darstellen.

    Führen Sie dieses Skript aus, indem Sie den folgenden Befehl in Ihrem Terminal ausführen.

    python application/find_and_enrich_following_for_user.py

    Ihre Konsole sollte eine Liste der Benutzer gefolgt vom angegebenen Benutzernamen ausgeben.

    Users followed by haroldwatkins:
    User<ppierce -- Ernest Mccarty>
    User<vpadilla -- Jonathan Scott>
    User<david25 -- Abigail Alvarez>
    User<jacksonjason -- John Perry>
    User<chasevang -- Leah Miller>
    User<frankhall -- Stephanie Fisher>
    User<nmitchell -- Amanda Green>
    User<tmartinez -- Kristin Stevens>
    User<natasha87 -- Walter Carlson>
    User<geoffrey32 -- Mary Martin>
    

    Beachten Sie, dass Sie es jetzt mit Benutzer-Entitäten anstelle von Freundschafts-Entitäten zu tun haben. Die Benutzer-Entität wird über die vollständigsten und aktuellsten Informationen zu Ihrem Benutzer verfügen. Auch wenn zwei Anfragen erforderlich sind, um dies zu erreichen, ist dies möglicherweise immer noch eine bessere Option als die vollständige Denormalisierung und die daraus resultierenden Datenintegritätsprobleme

  • Fazit

    In diesem Modul haben wir gelernt, wie eine partielle Normalisierung und der BatchGetItem-API-Aufruf dabei helfen können, die Datenintegrität zwischen Objekten aufrechtzuerhalten und gleichzeitig die Abfrageanforderungen niedrig zu halten.

    Im nächsten Modul verwenden wir DynamoDB-Transaktionen, wenn wir einem Foto eine Reaktion hinzufügen oder einem Benutzer folgen.