我有以下数据
分区键 | 排序键 | 价值 |
---|---|---|
啊 | str1 | 1 |
啊 | str2 | 123 |
啊 | str3 | 122 |
ab | str1 | 12 |
ab | str3 | 111 |
ac | str1 | 112 |
通过使用
QueryRequest
,我想选择分区键为“aa”且排序键为“str1”或“str3”的条目。我尝试创建一个 Condition
,但是对于不同的异常没有任何作用,所以有人可以指出如何编写这个查询吗?
var pkCondition = new Condition
{
ComparisonOperator = ComparisonOperator.EQ,
AttributeValueList =
{
new AttributeValue { S = "aa" },
},
};
// Exception One or more parameter values were invalid: Condition parameter type does not match schema type
var skCondition1 = new Condition
{
ComparisonOperator = ComparisonOperator.EQ,
AttributeValueList =
{
new AttributeValue { SS = { "str1", "str3" } },
},
};
// Exception: One or more parameter values were invalid: Invalid number of argument(s) for the EQ ComparisonOperator
var skCondition2 = new Condition
{
ComparisonOperator = ComparisonOperator.EQ,
AttributeValueList =
{
new AttributeValue { S = "str1" },
new AttributeValue { S = "str3" },
},
};
// Well this one is clear because IN cannot be performed on keys
// Exception: One or more parameter values were invalid: ComparisonOperator IN is not valid for SS AttributeValue type
var skCondition3 = new Condition
{
ComparisonOperator = ComparisonOperator.IN,
AttributeValueList =
{
new AttributeValue { SS = { "str1", "str3" } },
},
};
// Works, but not what I need
var skCondition4 = new Condition
{
ComparisonOperator = ComparisonOperator.EQ,
AttributeValueList =
{
new AttributeValue { S = "str1" },
},
};
return new QueryRequest
{
TableName = "My table",
KeyConditions =
{
{ "Partition key", pkCondition },
{ "Sort key", skCondition },
},
};
经过一些研究,我发现
KeyConditionExpression
也可以使用,但我还没有找到任何适合我的情况的组合。
// Exception: Invalid operator used in KeyConditionExpression: OR
const string keyConditionExpression1 = "#pk = :pkval AND (#sk = :sk1 OR #sk = :sk2)";
// Exception: Invalid operator used in KeyConditionExpression: IN
const string keyConditionExpression2 = "#pk = :pkval AND #sk IN (:sk1, :sk2)";
new QueryRequest
{
TableName = "My table",
KeyConditionExpression = keyConditionExpression,
ExpressionAttributeNames = new Dictionary<string, string>
{
{ "#pk", "Partition key" },
{ "#sk", "Sort key" },
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":pkval", new AttributeValue { S = "aa" } },
{ ":sk1", new AttributeValue { S = "str1" } },
{ ":sk2", new AttributeValue { S = "str3" } },
},
};
接下来,我还尝试使用
FilterExpression
,其中允许 IN 和 OR,但又出现了另一个例外:Filter Expression can only contain non-primary key attributes
。
new QueryRequest
{
TableName = "My table",
KeyConditionExpression = "#pk = :pkval",
FilterExpression = "#sk IN (:sk1, :sk2)",
ExpressionAttributeNames = new Dictionary<string, string>
{
{ "#pk", "Partition key" },
{ "#sk", "Sort key" },
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":pkval", new AttributeValue { S = "aa" } },
{ ":sk1", new AttributeValue { S = "str1" } },
{ ":sk2", new AttributeValue { S = "str3" } },
},
};
DynamoDB 数据结构可以比作 B 树。也就是说,一个高效的 Query 只读取一条连续的数据。
您的访问模式无法保证数据是连续的并且在磁盘上彼此相邻存储。这就是你挣扎的原因。
根据您存储在排序键中的实际数据,您可以执行
between
或 begins_with
条件。 `(str1,str3) 之间的 SK。
但是,您的访问模式似乎表明您需要不遵循模式的特定排序键,在这种情况下,您应该使用
BatchGetItem
,它允许您每个请求最多获取 100 个项目。
如果排序键的完整值未知,那么您可以执行一个
ExecuteStatement
请求,该请求将在后台执行多个查询调用,以满足您的访问模式。