Nel modulo precedente, hai aggiunto un indice invertito alla tua tabella. L'indice invertito aggiunge ulteriori pattern di query per i dati relazionali. Tuttavia, ci siamo resi conto di riscontrare ancora problemi. Sebbene sia possibile eseguire una query su tutte le entità di Amicizia per una determinata entità Utente, l'entità Amicizia non contiene informazioni sull'utente che viene seguito.

In questo modulo apprenderai la normalizzazione parziale.

Nel secondo modulo, abbiamo visto che non dovresti provare a simulare uno schema relazionale durante la modellazione con DynamoDB. Un tenant principale del modello relazionale è la normalizzazione dei dati in cui si evita la duplicazione dei dati in più punti. La normalizzazione rappresenta un pattern utile nei database relazionali, tuttavia durante l'esecuzione di una query potresti avere bisogno di join costosi per riassemblare i tuoi dati.

Con DynamoDB, spesso desideri denormalizzare i tuoi dati. La denormalizzazione consente di evitare join e di migliorare le prestazioni delle query. Per eseguirla, puoi copiare gli attributi da un determinato elemento a un altro elemento che fa riferimento ad esso per evitare di recuperare entrambi gli elementi durante una query.

Tuttavia, ci sono casi in cui la denormalizzazione può complicare il modello di dati. Ad esempio, il modello di dati ha un'entità Amicizia che fa riferimento sia a un utente che viene seguito che a un utente che segue. Potresti copiare tutti gli attributi di ciascuna entità Utente nell'entità Amicizia quando crei l'entità Amicizia. Quindi, quando recuperi l'entità Amicizia, avresti anche tutti i dettagli su entrambi gli utenti.

Questo potrebbe rappresentare un problema ogni volta che un utente modifica le informazioni nel proprio profilo. Ad esempio, se un utente modifica la propria immagine del profilo, i dati in ciascuna entità Amicizia contenente tale utente diventerebbero obsoleti. Pertanto, ogni volta che c'è un aggiornamento, dovresti aggiornare ogni entità Amicizia che contiene l'utente.

Nelle fasi successive, vedrai come utilizzare la normalizzazione parziale e la chiamata API BatchGetItem per gestire questa situazione.

Tempo necessario per completare il modulo: 20 minuti


  • Fase 1: Utilizza la normalizzazione parziale per trovare gli utenti seguiti

    In questa fase vedrai come trovare gli utenti seguiti. Questi sono gli utenti che un determinato utente sta seguendo nella tua applicazione. Vedrai anche come recuperare tutti i dati sugli utenti che vengono seguiti.

    Come descritto nell'introduzione a questo modulo, potresti desiderare di usare una tecnica di normalizzazione parziale per amicizie e utenti. Anziché archiviare le informazioni complete su ciascun utente nell'entità Amicizia, puoi utilizzare l'API BatchGetItem per recuperare informazioni su un utente in un'entità Amicizia.

    Nel codice che hai scaricato, nella directory application/ è presente un file denominato find_and_enrich_following_for_user.py. I contenuti di questo script sono mostrati di seguito.

    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)

    La funzione find_and_enrich_following_for_user è simile alla funzione find_follower_for_user che hai utilizzato nell'ultimo modulo. La funzione accetta un nome utente per il quale desideri cercare gli utenti seguiti. La funzione dapprima effettua una richiesta di Query utilizzando l'indice invertito per trovare tutti gli utenti che il nome utente specificato sta seguendo. Quindi, assembla un BatchGetItem per recuperare l'entità Utente completa per ciascuno degli utenti seguiti e restituisce tali entità.

    Ciò comporta due richieste a DynamoDB, anziché un'unica richiesta che è la soluzione ideale. Tuttavia, soddisfa un modello di accesso piuttosto complesso ed evita la necessità di aggiornare costantemente le entità di amicizia ogni volta che viene aggiornato un profilo utente. Questa normalizzazione parziale può essere un ottimo strumento per le tue esigenze di modellazione.

    Lancia lo script eseguendo il seguente comando nel tuo terminale.

    python application/find_and_enrich_following_for_user.py

    La tua console dovrebbe generare un elenco di utenti seguito dal nome utente indicato.

    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>
    

    Nota che ora hai a che fare con entità Utente anziché entità Amicizia. L'entità utente disporrà delle informazioni più complete e aggiornate sul tuo utente. Anche se ci sono volute due richieste per arrivare a questo risultato, potrebbe essere comunque un'opzione migliore rispetto alla denormalizzazione completa e ai problemi di integrità dei dati che ne derivano

  • Conclusioni

    In questo modulo, abbiamo visto come la normalizzazione parziale e la chiamata all'API BatchGetItem possano essere utili per mantenere l'integrità dei dati tra gli oggetti mantenendo basse le richieste di query.

    Nel modulo successivo, utilizzeremo le transazioni DynamoDB mentre aggiungiamo una reazione a una foto o seguiamo un utente.