2016-08-04 32 views
5

我需要在DynamoDB上進行限制和條件掃描。爲什麼使用Limit和FilterExpression進行DynamoDB掃描不會返回符合過濾器要求的項目?

docs說:

在響應,DynamoDB返回限制值的範圍內的所有匹配的結果。例如,如果您發出限值爲6且沒有過濾器表達式的查詢或掃描請求,則DynamoDB會返回表中與請求中指定的關鍵條件匹配的前六個項目(或者僅返回前六個項目掃描不帶過濾器的情況)。如果您還提供FilterExpression值,那麼DynamoDB將返回前六個中也與過濾器要求相匹配的項目(返回結果的數量將小於或等於6)。


的代碼(的NodeJS):

var params = { 
    ExpressionAttributeNames: {"#user": "User"}, 
    ExpressionAttributeValues: {":user": parseInt(user.id)}, 
    FilterExpression: "#user = :user and attribute_not_exists(Removed)", 
    Limit: 2, 
    TableName: "XXXX" 
}; 

DynamoDB.scan(params, function(err, data) { 
    if (err) { 
     dataToSend.message = "Unable to query. Error: " + err.message; 
    } else if (data.Items.length == 0) { 
     dataToSend.message = "No results were found."; 
    } else { 
     dataToSend.data = data.Items; 
     console.log(dataToSend); 
    } 
}); 



表XXXX定義:

  • 主分區鍵:用戶(數量)
  • 主排序關鍵字:標識符(字符串)
  • INDEX:
    • 指數名稱:RemovedIndex
    • 類型:GSI
    • 分區鍵:刪除(號碼)
    • 排序鍵: -
    • 屬性:ALL


在上面的代碼中,如果我刪除Limit參數,DynamoDB將返回符合過濾器要求的項目。所以,條件是好的。但是當我用Limit參數掃描時,結果是空的。

該XXXX表,有5個項目。只有2個第一個具有Removed屬性。當我在沒有Limit參數的情況下掃描時,DynamoDB將返回3個不帶Removed屬性的項目。

我做錯了什麼?

回答

8

從您引用文檔:

如果您同時提供FilterExpression值,DynamoDB將返回 項目在第6也匹配濾波器的要求

通過結合限制和FilterExpression,您已告知DynamoDB僅查看錶中的前兩項,並針對這些項目評估FilterExpression。 DynamoDB中的限制可能會引起混淆,因爲它與RDBMS中的SQL表達式中的limit不同。

+0

謝謝你的回答!我不明白該文件,你向我澄清。你有關於如何在RDBMS中使用'limit'的提示嗎? –

+1

對此有一些疑惑:https://github.com/clarkie/dynogels/issues/12這種有用的行爲如何?確定掃描,直到你有6個物品與過濾器相匹配,或者你到達表格的最後會更有用? – Clarkie

+0

@Clarkie這很有用,因爲它允許您限制掃描操作評估的記錄數,這是出於性能原因。僅僅因爲它不像RDBMS一樣工作並不意味着它沒有用處。另外,你對Github的評論關於「對文檔所說的一些混淆」似乎對我不正確。文檔(正如我在我的回答中引用的)非常清楚。混淆來自那些認爲'limit'在DynamoDB中的工作方式與RDBMS中的方式相同,而無需花時間閱讀文檔。 –

1

你也許能夠得到你所需要的使用輔助指標。使用傳統的RDB示例,客戶訂單示例:客戶有一張表,訂單有一張。訂單表有一個由客戶 - 哈希,訂單 - 範圍組成的密鑰。所以如果你想獲得最新的10個訂單,沒有掃描就沒有辦法做到這一點

但是,如果你創建一個全球二級索引的訂單「某些常量」 - HASH,日期範圍和查詢針對該索引,他們的查詢會做你想做的事情,並且只收取與返回的記錄有關的RCU的費用。不需要昂貴的掃描。請注意,寫入操作會更加昂貴,但在大多數情況下,讀取操作比寫入操作要多得多。

如果您想要獲得大於1000美元的一天中的10個最大訂單,現在您有您的原始問題。該查詢將返回最後10個訂單,然後過濾出價值低於1000美元的訂單。

在這種情況下,您可以創建Date-OrderAmount的計算密鑰,並且針對該索引的查詢將返回所需內容。

它不像SQL那麼簡單,但是您也需要考慮SQL中的訪問模式。如果您有大量數據,則需要在SQL中創建索引,否則數據庫將很樂意代表您進行表掃描,這會影響性能並提高成本。

請注意,我提出的所有事情都是在只有一個事實根源的意義上歸一化的。您沒有複製數據 - 您只是重新編寫數據視圖,以便從DynamoDB獲得所需的信息。

請記住,CONSTANT作爲HASH的受限於每個分區10GB的限制,因此如果您有大量活動數據,則需要圍繞它進行設計。例如,根據您預期的訪問模式,您可以使用Customer而不是常量作爲HASH。或者使用STreams以其他方式組織數據(或子集)。

相關問題