dynamodb的全局二級(jí)索引(gsi)不支持直接的條件表達(dá)式投影。但可以通過(guò)創(chuàng)建稀疏gsi實(shí)現(xiàn)條件性索引,即僅當(dāng)基礎(chǔ)表項(xiàng)中存在gsi分區(qū)鍵屬性時(shí),該項(xiàng)才會(huì)被包含在索引中。通過(guò)應(yīng)用層邏輯動(dòng)態(tài)添加或移除此gsi鍵屬性,可以有效地控制哪些記錄進(jìn)入或離開(kāi)索引,從而實(shí)現(xiàn)基于特定字段值的條件性索引需求。
在構(gòu)建DynamoDB應(yīng)用時(shí),我們經(jīng)常需要對(duì)數(shù)據(jù)進(jìn)行靈活的查詢。全局二級(jí)索引(GSI)是實(shí)現(xiàn)這一目標(biāo)的關(guān)鍵工具,它允許我們使用不同于主表的鍵屬性進(jìn)行查詢。然而,有時(shí)我們希望GSI只包含滿足特定條件的數(shù)據(jù)項(xiàng),例如,只索引處于“中間狀態(tài)”的記錄。DynamoDB的GSI本身不提供基于表達(dá)式的條件投影功能,但我們可以利用其“稀疏索引”(Sparse Index)的特性來(lái)巧妙地實(shí)現(xiàn)這一目標(biāo)。
DynamoDB的GSI有一個(gè)核心行為:一個(gè)數(shù)據(jù)項(xiàng)只有在其GSI分區(qū)鍵屬性(以及GSI排序鍵屬性,如果定義了)存在于基礎(chǔ)表項(xiàng)中時(shí),才會(huì)被包含在GSI內(nèi)。如果這些GSI鍵屬性不存在,或者在更新操作中被移除,那么該數(shù)據(jù)項(xiàng)就不會(huì)出現(xiàn)在GSI中。這就是“稀疏索引”的本質(zhì)——索引只包含基礎(chǔ)表的一個(gè)子集。
通過(guò)利用這一特性,我們可以將條件邏輯從DynamoDB服務(wù)本身轉(zhuǎn)移到應(yīng)用程序?qū)?。?yīng)用程序負(fù)責(zé)根據(jù)業(yè)務(wù)規(guī)則,動(dòng)態(tài)地在基礎(chǔ)表項(xiàng)中添加或移除一個(gè)專門(mén)用于GSI的鍵屬性。
假設(shè)我們有一個(gè)名為 Attachment 的基礎(chǔ)表,其中包含 customerState 和 isIntermediateState 字段。customerState 可以是 Attaching、Detaching、Attached 或 Detached。isIntermediateState 字段在 customerState 為 Attaching 或 Detaching 時(shí)為 1,在 customerState 為 Attached 或 Detached 時(shí)為 0。我們的目標(biāo)是創(chuàng)建一個(gè)GSI,只包含 isIntermediateState = 1 的記錄。
定義GSI的專用鍵屬性: 在基礎(chǔ)表的數(shù)據(jù)模型中,引入一個(gè)專門(mén)用于GSI的屬性。例如,我們可以命名為 intermediateStateGSI_PK。
GSI配置: 創(chuàng)建一個(gè)新的全局二級(jí)索引,將其分區(qū)鍵設(shè)置為我們剛才定義的 intermediateStateGSI_PK。GSI的投影屬性可以根據(jù)查詢需求選擇 KEYS_ONLY、INCLUDE 或 ALL。
應(yīng)用程序邏輯管理GSI鍵屬性: 在應(yīng)用程序進(jìn)行 PutItem 或 UpdateItem 操作時(shí),根據(jù) isIntermediateState 的值或 customerState 的具體狀態(tài),動(dòng)態(tài)地管理 intermediateStateGSI_PK 屬性。
當(dāng)滿足條件時(shí)(例如 isIntermediateState = 1): 在數(shù)據(jù)項(xiàng)中添加 intermediateStateGSI_PK 屬性,并賦予一個(gè)固定值(例如 'ACTIVE_INTERMEDIATE_STATE')。這個(gè)固定值將作為GSI的分區(qū)鍵,允許我們查詢所有處于中間狀態(tài)的附件。
示例數(shù)據(jù)項(xiàng)(中間狀態(tài)):
{ "PK": "ATTACHMENT#123", "SK": "METADATA", "customerState": "Attaching", "isIntermediateState": 1, "intermediateStateGSI_PK": "ACTIVE_INTERMEDIATE_STATE", // GSI鍵存在 "otherAttribute": "value" }
當(dāng)不滿足條件時(shí)(例如 isIntermediateState = 0): 確保數(shù)據(jù)項(xiàng)中不包含 intermediateStateGSI_PK 屬性。如果之前存在,則通過(guò) UpdateItem 操作將其移除。
示例數(shù)據(jù)項(xiàng)(最終狀態(tài)):
{ "PK": "ATTACHMENT#123", "SK": "METADATA", "customerState": "Attached", "isIntermediateState": 0, // intermediateStateGSI_PK 已被移除或從未添加 "otherAttribute": "value" }
DynamoDB的GSI是異步且自動(dòng)更新的。這意味著,當(dāng)基礎(chǔ)表中的數(shù)據(jù)項(xiàng)被創(chuàng)建、更新或刪除時(shí),DynamoDB會(huì)自動(dòng)檢測(cè)GSI鍵屬性的變化,并相應(yīng)地更新GSI。
因此,GSI會(huì)持續(xù)地反映基礎(chǔ)表的最新?tīng)顟B(tài),而不是只在初始添加記錄時(shí)決定是否包含。
以下是使用AWS SDK(以JavaScript為例)進(jìn)行 UpdateItem 操作以管理GSI鍵屬性的概念性代碼:
const AWS = require('aws-sdk'); const ddb = new AWS.DynamoDB.DocumentClient(); async function updateAttachmentState(attachmentId, newCustomerState) { let updateExpression = "SET #cs = :newCs, #is = :newIs"; let expressionAttributeNames = { "#cs": "customerState", "#is": "isIntermediateState" }; let expressionAttributeValues = { ":newCs": newCustomerState }; let isIntermediateStateValue; let gsiKeyAction = null; // 'add' or 'remove' if (newCustomerState === 'Attaching' || newCustomerState === 'Detaching') { isIntermediateStateValue = 1; gsiKeyAction = 'add'; } else if (newCustomerState === 'Attached' || newCustomerState === 'Detached') { isIntermediateStateValue = 0; gsiKeyAction = 'remove'; } else { throw new Error("Invalid customer state."); } expressionAttributeValues[":newIs"] = isIntermediateStateValue; if (gsiKeyAction === 'add') { updateExpression += ", #gsiPk = :gsiPkVal"; expressionAttributeNames["#gsiPk"] = "intermediateStateGSI_PK"; expressionAttributeValues[":gsiPkVal"] = "ACTIVE_INTERMEDIATE_STATE"; } else if (gsiKeyAction === 'remove') { updateExpression += " REMOVE #gsiPk"; expressionAttributeNames["#gsiPk"] = "intermediateStateGSI_PK"; } const params = { TableName: "Attachment", Key: { "PK": `ATTACHMENT#${attachmentId}`, "SK": "METADATA" }, UpdateExpression: updateExpression, ExpressionAttributeNames: expressionAttributeNames, ExpressionAttributeValues: expressionAttributeValues, ReturnValues: "ALL_NEW" }; try { const result = await ddb.update(params).promise(); console.log("Update successful:", result.Attributes); return result.Attributes; } catch (error) { console.error("Error updating item:", error); throw error; } } // 示例調(diào)用 // updateAttachmentState("123", "Attaching"); // 會(huì)添加 GSI 鍵 // updateAttachmentState("123", "Attached"); // 會(huì)移除 GSI 鍵
盡管DynamoDB的全局二級(jí)索引不直接支持基于表達(dá)式的條件投影,但通過(guò)巧妙地利用稀疏索引的特性,我們可以通過(guò)應(yīng)用程序?qū)舆壿媮?lái)模擬實(shí)現(xiàn)這一功能。核心思想是引入一個(gè)GSI專用鍵屬性,并根據(jù)業(yè)務(wù)條件動(dòng)態(tài)地在基礎(chǔ)表項(xiàng)中添加或移除該屬性。這種方法不僅靈活有效,而且能夠充分利用DynamoDB的強(qiáng)大索引能力,為復(fù)雜查詢需求提供解決方案。
以上就是利用稀疏GSI實(shí)現(xiàn)DynamoDB條件性索引的詳細(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)