在dynamodb中,全局二級(jí)索引(gsi)不直接支持基于表達(dá)式的條件投影。然而,通過巧妙地利用“稀疏gsi”機(jī)制,開發(fā)者可以實(shí)現(xiàn)按需將主表記錄有條件地添加或移除出索引。核心思想是,僅當(dāng)主表記錄滿足特定條件時(shí),才在記錄中包含gsi分區(qū)鍵屬性,從而控制其是否被索引。
DynamoDB的全局二級(jí)索引(GSI)提供了一種靈活的方式來查詢非主鍵屬性。當(dāng)你在主表上定義一個(gè)GSI時(shí),DynamoDB會(huì)自動(dòng)維護(hù)這個(gè)索引,確保它與主表的數(shù)據(jù)保持同步。然而,GSI的投影(即索引中包含哪些屬性)通常是固定的:要么是所有屬性(ALL),要么是僅鍵屬性(KEYS_ONLY),要么是指定屬性(INCLUDE)。DynamoDB本身并不提供一種機(jī)制,讓你基于主表記錄的某個(gè)屬性值,來決定該記錄是否應(yīng)該被包含在GSI中。
這意味著,如果你有一個(gè)名為Attachment的主表,其中包含customerState和isIntermediateState等屬性,并且你希望只在isIntermediateState = 1時(shí)才將記錄添加到某個(gè)GSI中,而在isIntermediateState = 0時(shí)將其移除,傳統(tǒng)的GSI配置無法直接滿足這種條件性需求。
解決上述挑戰(zhàn)的關(guān)鍵在于利用“稀疏GSI”的概念。稀疏GSI的原理非常簡單而強(qiáng)大:如果一個(gè)項(xiàng)目不包含GSI定義的分區(qū)鍵屬性,那么該項(xiàng)目就不會(huì)被包含在GSI中。
基于此原理,我們可以設(shè)計(jì)一個(gè)GSI,其分區(qū)鍵是一個(gè)專門用于控制索引行為的“標(biāo)記”屬性。當(dāng)主表中的某個(gè)記錄滿足被索引的條件時(shí),我們就在該記錄中添加這個(gè)標(biāo)記屬性,并為其賦予一個(gè)值;當(dāng)記錄不再滿足條件時(shí),我們則從記錄中移除這個(gè)標(biāo)記屬性。
假設(shè)我們希望:
1. 定義GSI
首先,在Attachment表上創(chuàng)建一個(gè)名為IntermediateStateGSI的GSI,其分區(qū)鍵為GSI1PK。
2. 應(yīng)用程序邏輯
初始創(chuàng)建或更新為中間狀態(tài): 當(dāng)一個(gè)Attachment記錄被創(chuàng)建,并且customerState是Attaching或Detaching時(shí),或者現(xiàn)有記錄更新為這些狀態(tài)時(shí),我們應(yīng)該在PutItem或UpdateItem操作中添加GSI1PK屬性。
import boto3 dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('Attachment') def put_attachment_in_intermediate_state(attachment_id, customer_state): item = { 'AttachmentId': attachment_id, 'customerState': customer_state, 'isIntermediateState': 1 if customer_state in ['Attaching', 'Detaching'] else 0 } # 如果是中間狀態(tài),則添加GSI1PK if item['isIntermediateState'] == 1: item['GSI1PK'] = 'INTERMEDIATE#STATE' # 常量值,或更具體的標(biāo)識(shí) table.put_item(Item=item) print(f"Attachment {attachment_id} put/updated with state {customer_state}. GSI1PK {'added' if 'GSI1PK' in item else 'not added'}.") # 示例:添加一個(gè)處于Attaching狀態(tài)的記錄 put_attachment_in_intermediate_state('attach-001', 'Attaching') # 這條記錄將包含GSI1PK,并被索引 # 示例:添加一個(gè)處于Attached狀態(tài)的記錄 (不會(huì)被索引) put_attachment_in_intermediate_state('attach-002', 'Attached')
更新為最終狀態(tài)(從GSI中移除): 當(dāng)一個(gè)Attachment記錄從Attaching/Detaching狀態(tài)更新為Attached/Detached時(shí),我們需要移除GSI1PK屬性。
def update_attachment_to_final_state(attachment_id, customer_state): update_expression = "SET customerState = :cs, isIntermediateState = :is" expression_attribute_values = { ':cs': customer_state, ':is': 0 # 最終狀態(tài) } # 如果當(dāng)前記錄處于中間狀態(tài),并且更新后變?yōu)樽罱K狀態(tài),則需要移除GSI1PK # 實(shí)際應(yīng)用中,可能需要先讀取當(dāng)前狀態(tài)來判斷 # 這里簡化處理,只要更新為最終狀態(tài)就嘗試移除GSI1PK update_expression += " REMOVE GSI1PK" # 嘗試移除,如果不存在也不會(huì)報(bào)錯(cuò) table.update_item( Key={'AttachmentId': attachment_id}, UpdateExpression=update_expression, ExpressionAttributeValues=expression_attribute_values ) print(f"Attachment {attachment_id} updated to final state {customer_state}. GSI1PK removed.") # 示例:將attach-001從Attaching更新為Attached update_attachment_to_final_state('attach-001', 'Attached') # 這條記錄的GSI1PK將被移除,從而從IntermediateStateGSI中消失
通過采用稀疏GSI策略,即使DynamoDB不直接支持基于表達(dá)式的條件投影,你也能靈活地控制哪些記錄被包含在全局二級(jí)索引中,從而滿足復(fù)雜的業(yè)務(wù)需求,同時(shí)保持?jǐn)?shù)據(jù)的一致性和查詢效率。
以上就是DynamoDB稀疏全局二級(jí)索引:按條件管理索引記錄的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個(gè)人都需要一臺(tái)速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊(cè)表數(shù)據(jù)和不必要的后臺(tái)進(jìn)程會(huì)占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號(hào)
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)