ในโมดูลก่อนหน้า คุณได้ตั้งค่าการเข้าถึงเอนทิตีหลักของคุณใน DynamoDB โครงสร้างของคีย์หลักจะแก้ไขจำนวนรูปแบบการเข้าถึงหลักของเรา ซึ่งประกอบด้วยรูปแบบทั้งหมดในการอ่านหรือเขียนเอนทิตีเดียว รวมถึงรูปแบบในการดึงข้อมูลเอนทิตีที่เกี่ยวข้องหลายรายการ เช่น รูปภาพทั้งหมดที่เป็นของผู้ใช้ที่ระบุ

ในโมดูลนี้ คุณจะได้เรียนรู้เกี่ยวกับการใช้ดัชนีย้อนกลับ ซึ่งเป็นรูปแบบการออกแบบทั่วไปสำหรับ DynamoDB

ดัชนีรอง คือเครื่องมือในการทำโมเดลข้อมูลที่สำคัญใน DynamoDB ซึ่งจะทำให้คุณสามารถเปลี่ยนรูปแบบของข้อมูลให้รองรับรูปแบบการสืบค้นอื่นๆ ได้

ดัชนีย้อนกลับเป็นรูปแบบการออกแบบดัชนีรองทั่วไปที่มีใน DynamoDB ด้วยดัชนีย้อนกลับ คุณจะสามารถสร้างดัชนีรองที่เป็นการย้อนกลับของคีย์หลักสำหรับตารางของคุณ คีย์ HASH สำหรับตารางของคุณ จะเป็นคีย์ RANGE ในดัชนีของคุณ และคีย์ RANGE สำหรับตารางของคุณจะเป็นคีย์หลักสำหรับดัชนีของคุณ

ดัชนีย้อนกลับเป็นประโยชน์ในสถานการณ์สมมติสองแบบ อันดับแรก ดัชนีย้อนกลับจะเป็นประโยชน์ในการสืบค้น “อีกด้านหนึ่ง” ของความสัมพันธ์แบบกลุ่มต่อกลุ่ม นี่คือกรณีสำหรับเอนทีตี มิตรภาพ ของคุณ ด้วยโครงสร้างคีย์หลักของคุณ คุณจะสามารถสืบค้นผู้ติดตามทั้งหมดสำหรับผู้ใช้เฉพาะรายที่ทำการสืบค้นต่อคีย์หลักของตาราง เมื่อคุณเพิ่มดัชนีย้อนกลับ คุณจะสามารถค้นหาผู้ใช้ที่ผู้ใช้รายหนึ่งกำลังติดตามอยู่ (เรียกว่าผู้ใช้ที่ “ถูกติดตาม”) โดยการสืบค้นดัชนีย้อนกลับ

นอกจากนี้ ดัชนีย้อนกลับยังเป็นประโยชน์สำหรับการสืบค้นความสัมพันธ์แบบหนึ่งต่อกลุ่มสำหรับเอนทีตีที่เป็นหัวเรื่องของความสัมพันธ์แบบหนึ่งต่อกลุ่ม คุณสามารถมองเห็นรายการนี้ได้ด้วยเอนทิตี การโต้ตอบ ในตารางของคุณ ทั้งนี้ อาจมีการโต้ตอบหลายรายการในรูปภาพหนึ่ง และการโต้ตอบแต่ละรายการจะประกอบด้วยรูปภาพที่มีการปรับใช้การโต้ตอบ ชื่อผู้ใช้ของผู้ใช้ที่ทำการโต้ตอบ และประเภทของการโต้ตอบ อย่างไรก็ตาม เนื่องจากผู้ใช้สามารถมีรูปภาพได้หลายรูป ตัวระบุหลักสำหรับรูปภาพจะอยู่ในคีย์ RANGE -- PHOTO#<USERNAME>#<TIMESTAMP> ดังนั้น คุณจะไม่สามารถใช้คีย์หลักของคุณในการผูกการโต้ตอบกับรูปภาพต่างๆ ได้

เพื่อสร้างรูปแบบการเข้าถึง “ดูรูปภาพและการโต้ตอบ” ที่น่าพึงพอใจ โมเดลข้อมูลจะวางตัวระบุรูปภาพสำหรับเอนทิตีการโต้ตอบไว้ในคีย์ RANGE ขณะนี้ เมื่อทำการสืบค้นดัชนีย้อนกลับ คุณจะสามารถใช้ตัวระบุรูปภาพเพื่อเลือกรูปภาพและการโต้ตอบทั้งหมดในคำขอเดียว รายการนี้จะแสดงในขั้นตอนที่ 2 ด้านล่างนี้

ระยะเวลาที่ใช้ในการศึกษาโมดูล: 40 นาที


  • ขั้นตอนที่ 1: สร้างดัชนีรอง

    ในการสร้างดัชนีรอง คุณจะต้องกำหนดคีย์หลักของดัชนี เช่นเดียวกับที่คุณทำไว้ในตาราง จำไว้ว่าคีย์หลักสำหรับดัชนีรองรวมไม่จำเป็นต้องมีความแตกต่างกัน จากนั้น DynamoDB จะคัดลอกรายการลงในดัชนีตามคุณลักษณะที่กำหนดไว้ และคุณสามารถสืบค้นได้เช่นเดียวกับในตารางของคุณ

    ดัชนีย้อนกลับเป็นรูปแบบทั่วไปใน DynamoDB ที่คุณสร้างดัชนีรองไว้ ซึ่งจะเป็นการย้อนกลับคีย์หลักของตารางของคุณ คีย์ HASH สำหรับตารางของคุณ จะถูกระบุเป็นคีย์ RANGE ในดัชนีรองของคุณ และคีย์ RANGE สำหรับตารางของคุณ จะถูกระบุเป็นคีย์ HASH ในดัชนีรองของคุณ

    การสร้างดัชนี้รองมีความคล้ายคลึงกับการสร้างตาราง ในโค้ดที่คุณดาวน์โหลด จะมีไฟล์ในไดเรกทอรี scripts/ ที่มีชื่อว่า add_inverted_index.py เนื้อหาในไฟล์ดังกล่าวจะแสดงที่ด้านล่างนี้

    import boto3
    
    dynamodb = boto3.client('dynamodb')
    
    try:
        dynamodb.update_table(
            TableName='quick-photos',
            AttributeDefinitions=[
                {
                    "AttributeName": "PK",
                    "AttributeType": "S"
                },
                {
                    "AttributeName": "SK",
                    "AttributeType": "S"
                }
            ],
            GlobalSecondaryIndexUpdates=[
                {
                    "Create": {
                        "IndexName": "InvertedIndex",
                        "KeySchema": [
                            {
                                "AttributeName": "SK",
                                "KeyType": "HASH"
                            },
                            {
                                "AttributeName": "PK",
                                "KeyType": "RANGE"
                            }
                        ],
                        "Projection": {
                            "ProjectionType": "ALL"
                        },
                        "ProvisionedThroughput": {
                            "ReadCapacityUnits": 5,
                            "WriteCapacityUnits": 5
                        }
                    }
                }
            ],
        )
        print("Table updated successfully.")
    except Exception as e:
        print("Could not update table. Error:")
        print(e)
    

    เมื่อมีการใช้คุณลักษณะในคีย์หลักสำหรับตารางหรือดัชนีรอง จะต้องมีการกำหนดคุณลักษณะเหล่านั้นใน AttributeDefinitions จากนั้น เราจะสร้างดัชนีรองใหม่ในคุณสมบัติ GlobalSecondaryIndexUpdates สำหรับดัชนีรองนี้ เราจะกำหนดชื่อดัชนี สคีมาของคีย์หลัก ปริมาณการแสดงผลที่คาดไว้ และคุณลักษณะที่เราต้องการสำหรับโปรเจกต์

    โปรดทราบว่า ดัชนีย้อนกลับเป็นชื่อของรูปแบบการออกแบบ แทนที่จะเป็นคุณสมบัติที่เป็นทางการใน DynamoDB การสร้างดัชนีย้อนกลับจะคล้ายคลึงกับการสร้างดัชนีรองอื่นใดๆ

    สร้างดัชนีย้อนกลับโดยเรียกใช้คำสั่งด้านล่างนี้

    python scripts/add_inverted_index.py

    คุณควรจะพบข้อความต่อไปนี้ในคอนโซล: “อัปเดตตารางเสร็จสมบูรณ์”

    ในขั้นตอนถัดไป เราจะแสดงวิธีการใช้ดัชนีย้อนกลับของเราเพื่อค้นหารูปภาพ

  • ขั้นตอนที่ 2: สืบค้นดัชนีย้อนกลับเพื่อค้นหาการโต้ตอบของรูปภาพ

    ในตอนนี้ เรามีดัชนีรองที่กำหนดค่าไว้แล้ว ให้เอามาใช้ตามรูปแบบการเข้าถึงบางแบบ

    เมื่อใช้ดัชนีรอง คุณจะมีการเรียกใช้ API เพียงสองรายการที่ใช้งานได้ คือ การสืบค้น และ การสแกน เมื่อใช้ การสืบค้น คุณจะต้องกำหนดคีย์ HASH จึงจะให้ผลลัพธ์เป้าหมาย เมื่อใช้การสแกน คุณไม่จำเป็นต้องกำหนดคีย์ HASH และเรียกใช้การทำงานได้ในตารางทั้งหมด การสแกนจะไม่สามารถทำงานได้บน DynamoDB ยกเว้นในบางกรณี เนื่องจากจะเป็นการเข้าถึงทุกรายการในฐานข้อมูลของคุณ หากคุณมีข้อมูลเป็นจำนวนมากในตารางของคุณ การสแกนอาจใช้ระยะเวลานาน

    เราสามารถใช้ API การสืบค้น จากดัชนีรองของเรา เพื่อค้นหาการโต้ตอบทั้งหมดบนรูปภาพเฉพาะ เช่นที่คุณได้เห็นในโมดูลก่อนหน้า คุณจะสามารถใช้การสืบค้นนี้เพื่อเรียกดูเอนทิตีสองชนิดในคำสั่งเดียว ในการสืบค้นนี้ คุณจะสามารถเรียกดูทั้งรูปภาพและการโต้ตอบได้

    ในโค้ดที่คุณดาวน์โหลด จะมีไฟล์ในไดเรกทอรี application/ ที่เรียกว่า fetch_photo_and_reactions.py เนื้อหาของสคริปต์นี้มีดังต่อไปนี้

    import boto3
    
    from entities import Photo, Reaction
    
    dynamodb = boto3.client('dynamodb')
    
    USER = "david25"
    TIMESTAMP = '2019-03-02T09:11:30'
    
    
    def fetch_photo_and_reactions(username, timestamp):
        try:
            resp = dynamodb.query(
                TableName='quick-photos',
                IndexName='InvertedIndex',
                KeyConditionExpression="SK = :sk AND PK BETWEEN :reactions AND :user",
                ExpressionAttributeValues={
                    ":sk": { "S": "PHOTO#{}#{}".format(username, timestamp) },
                    ":user": { "S": "USER$" },
                    ":reactions": { "S": "REACTION#" },
                },
                ScanIndexForward=True
            )
        except Exception as e:
            print("Index is still backfilling. Please try again in a moment.")
            return False
    
        items = resp['Items']
        items.reverse()
    
        photo = Photo(items[0])
        photo.reactions = [Reaction(item) for item in items[1:]]
    
        return photo
    
    
    photo = fetch_photo_and_reactions(USER, TIMESTAMP)
    
    if photo:
        print(photo)
        for reaction in photo.reactions:
            print(reaction)
    

    ฟังก์ชัน fetch_photo_and_reactions มีความคล้ายคลึงกับฟังก์ชันที่มีในแอปพลิเคชันของคุณ ฟังก์ชันนี้จะยอมรับชื่อผู้ใช้และการประทับเวลา และทำการสืบค้นจาก InvertedIndex เพื่อค้นหารูปภาพ และการโต้ตอบสำหรับรูปภาพดังกล่าว จากนั้น ระบบจะรวบรวมรายการที่แสดงผลลัพธ์ไปยังเอนทิตี รูปภาพ และเอนทิตี การโต้ตอบ หลายรายการที่สามารถใช้ในแอปพลิเคชันของคุณ

    python application/fetch_photo_and_reactions.py

    คุณควรมองเห็นเอาต์พุตของรูปภาพและการโต้ตอบทั้งห้ารายการ

    Photo<david25 -- 2019-03-02T09:11:30>
    Reaction<ylee -- PHOTO#david25#2019-03-02T09:11:30 -- smiley>
    Reaction<kennedyheather -- PHOTO#david25#2019-03-02T09:11:30 -- smiley>
    Reaction<jenniferharris -- PHOTO#david25#2019-03-02T09:11:30 -- +1>
    Reaction<geoffrey32 -- PHOTO#david25#2019-03-02T09:11:30 -- +1>
    Reaction<chasevang -- PHOTO#david25#2019-03-02T09:11:30 -- +1>

    โปรดทราบว่า ดัชนีรองจะใช้เวลาสักครู่ในการเติมข้อมูล คุณอาจได้รับข้อความแสดงข้อผิดพลาด ที่ระบุว่าการเติมข้อมูลกำลังอยู่ในระหว่างการดำเนินการ หากเป็นเช่นนั้น โปรดลองใหม่อีกครั้งในอีกไม่กี่นาที

    ในขั้นตอนถัดไป เราจะเห็นวิธีการใช้ดัชนีย้อนกลับในการดึงข้อมูลที่ผู้ใช้ทั้งหมดซึ่งผู้ใช้ที่กำหนดกำลังติดตามอยู่

  • ขั้นตอนที่ 3: ค้นหาผู้ใช้ที่ถูกติดตาม

    ในขั้นตอนก่อนหน้า คุณได้เห็นวิธีการใช้ดัชนีย้อนกลับในการดึงข้อมูลความสัมพันธ์แบบหนึ่งต่อกลุ่มสำหรับเอนทีตีที่เป็นหัวเรื่องของความสัมพันธ์แบบหนึ่งต่อกลุ่ม ในขั้นตอนนี้ คุณจะใช้ดัชนีแบบย้อนกลับเพื่อดึงข้อมูล “อีกด้านหนึ่ง” ของความสัมพันธ์แบบกลุ่มต่อกลุ่ม

    คีย์หลักในตารางจะอนุญาตให้คุณสามารถค้นหาผู้ติดตามทั้งหมดของผู้ใช้เฉพาะ แต่คุณจะไม่สามารถค้นหาผู้ใช้ทั้งหมดที่บุคคลกำลังติดตามอยู่ได้ ทั้งนี้ รายการจะพลิกเนื่องด้วยดัชนีแบบย้อนกลับ คุณจะสามารถค้นหาผู้ใช้ทั้งหมดที่ติดตามโดยผู้ใช้เฉพาะได้

    ในโค้ดที่คุณดาวน์โหลด จะมีไฟล์ในไดเรกทอรี application/ ที่เรียกว่า find_following_for_user.py เนื้อหาของสคริปต์นี้มีดังต่อไปนี้

    import boto3
    
    from entities import Friendship
    
    dynamodb = boto3.client('dynamodb')
    
    USERNAME = "haroldwatkins"
    
    
    def find_following_for_user(username):
        resp = dynamodb.query(
            TableName='quick-photos',
            IndexName='InvertedIndex',
            KeyConditionExpression="SK = :sk",
            ExpressionAttributeValues={
                ":sk": { "S": "#FRIEND#{}".format(username) }
            },
            ScanIndexForward=True
        )
    
        return [Friendship(item) for item in resp['Items']]
    
    
    
    follows = find_following_for_user(USERNAME)
    
    print("Users followed by {}:".format(USERNAME))
    for follow in follows:
        print(follow)
    

    ฟังก์ชัน find_following_for_user มีความคล้ายคลึงกับฟังก์ชันที่มีในแอปพลิเคชันของคุณ ฟังก์ชันดังกล่าวจะยอมรับชื่อผู้ใช้สำหรับบุคคลที่คุณต้องการค้นหาผู้ใช้ที่ถูกติดตาม จากนั้น ฟังก์ชันจะทำการสืบค้นดัชนีย้อนกลับเพื่อค้นหาเอนทิตี มิตรภาพ ทั้งหมด ที่ผู้ใช้ที่ติดตามคือชื่อผู้ใช้ที่กำหนด

    เรียกใช้สคริปต์โดยการใช้คำสั่งต่อไปนี้ในเทอร์มินัลของคุณ

    python application/find_following_for_user.py

    คอนโซลของคุณควรแสดงเอาต์พุตเป็นรายการผู้ใช้ที่ติดตามโดยชื่อผู้ใช้ที่กำหนด:

    Users followed by haroldwatkins:
    Friendship<chasevang -- haroldwatkins>
    Friendship<david25 -- haroldwatkins>
    Friendship<frankhall -- haroldwatkins>
    Friendship<geoffrey32 -- haroldwatkins>
    Friendship<jacksonjason -- haroldwatkins>
    Friendship<natasha87 -- haroldwatkins>
    Friendship<nmitchell -- haroldwatkins>
    Friendship<ppierce -- haroldwatkins>
    Friendship<tmartinez -- haroldwatkins>
    Friendship<vpadilla -- haroldwatkins>

    โปรดทราบว่า ขณะที่การดำเนินการนี้แสดงผลลัพธ์เป็นเอนทิตี มิตรภาพ ทั้งหมดสำหรับผู้ใช้ ข้อมูลในเอนทิตี มิตรภาพ จะมีการกระจายค่อนข้างมาก โดยจะมีเฉพาะชื่อผู้ใช้ของผู้ใช้ที่ถูกติดตาม แต่ไม่ใช่โปรไฟล์ของผู้ใช้แบบเต็มรูปแบบ ในโมดูลถัดไป เราจะอภิปรายถึงวิธีการใช้การปรับมาตรฐานบางส่วนเพื่อจัดการสถานการณ์เช่นนี้ได้อย่างมีประสิทธิภาพ

  • สรุป

    ในโมดูลนี้ เราได้เพิ่มดัชนีรองไปที่ตารางของเรา โดยใช้รูปแบบของดัชนีย้อนกลับ ซึ่งเป็นไปตามรูปแบบการเข้าถึงอีกสองรูปแบบเพิ่มเติม:

    • ดูรูปภาพและการตอบสนอง (อ่าน)
    • ดูผู้ที่ผู้ใช้ติดตาม (อ่าน)

    ขณะที่เรียกดูผู้ใช้ที่ถูกติดตามทั้งหมดของผู้ใช้ เราได้มองเห็นปัญหาที่เอนทิตีมิตรภาพแต่ละรายการไม่มีข้อมูลบางอย่างเกี่ยวกับผู้ใช้ที่ถูกติดตาม ในโมดูลถัดไป เราจะมองเห็นวิธีการใช้การปรับมาตรฐานบางส่วนเพื่อช่วยเกี่ยวกับรูปแบบการเข้าถึงนี้