AWS DynamoDB QueryRequest 多个排序键值

问题描述 投票:0回答:1

我有以下数据

分区键 排序键 价值
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" } },
    },
};
c# .net amazon-web-services amazon-dynamodb
1个回答
0
投票

DynamoDB 数据结构可以比作 B 树。也就是说,一个高效的 Query 只读取一条连续的数据。

您的访问模式无法保证数据是连续的并且在磁盘上彼此相邻存储。这就是你挣扎的原因。

可能的解决方案

  • 根据您存储在排序键中的实际数据,您可以执行

    between
    begins_with
    条件。 `(str1,str3) 之间的 SK。

  • 但是,您的访问模式似乎表明您需要不遵循模式的特定排序键,在这种情况下,您应该使用

    BatchGetItem
    ,它允许您每个请求最多获取 100 个项目。

  • 如果排序键的完整值未知,那么您可以执行一个

    ExecuteStatement
    请求,该请求将在后台执行多个查询调用,以满足您的访问模式。

© www.soinside.com 2019 - 2024. All rights reserved.