使用嵌套集合时 Dynamodb 查询未返回预期结果
Dynamo DB query not returning expected results when using nested collections
我有一个具有以下结构的 AWS DynamoDB Table:
我正在尝试取回至少有一个 ID 为 3401 的 RequestItem 的所有项目。
这是我到目前为止尝试过的(c# 代码):
IAmazonDynamoDB client = new AmazonDynamoDBClient(
new BasicAWSCredentials(configuration["AccessKey"], configuration["SecretKey"]),
RegionEndpoint.USEast1);
var request = new ScanRequest
{
TableName = "dynamo-table-name",
ExpressionAttributeNames = new Dictionary<string, string>
{
{"#requestItems", "RequestItems"},
{"#requestId", "Id"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{":val", new AttributeValue {N = "3401"}}
},
FilterExpression = "contains(#requestItems.#requestId, :val)"
};
var response = await client.ScanAsync(request);
我对 FilterExpression 做了一些修改(使用简单的“=”而不是 "contains")但是...我仍然没有得到结果。查询顺利通过,但结果是一个空列表。
但是,相同的代码适用于非集合的属性(例如 Contact.EmailAddress)
我错过了什么?
[编辑]
我尝试了另一个建议的解决方案:
var request = new ScanRequest
{
TableName = "dynamo-table-name",
ExpressionAttributeNames = new Dictionary<string, string>
{
{"#requestItems", "RequestItems"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{
":val",
new AttributeValue
{
L = new List<AttributeValue>
{
{
new AttributeValue
{
M = new Dictionary<string, AttributeValue>
{{"Id", new AttributeValue {N = "3401"}}}
}
}
}
}
}
},
FilterExpression = "contains(#requestItems, :val)"
};
var response = await client.ScanAsync(request);
但我仍然没有收到结果。
如有不当之处,敬请见谅
我怀疑 DynamoDB 不能做到这一点。
此外,DynamoDB 背后的想法是它不应该那样做。
DynamoDB 不支持对数据进行任意函数求值。
DynamoDB 是 K-V(有点)存储,而不是数据库。 "dynamo" 方法是查询您可能需要的所有行(项目)并在客户端分析列(键)。请注意,它的成本完全相同(对于 dynamo,流量差异很小),因为 aws 会向您收取类似 "database disk reads" 的费用。而且它同样繁琐或简单,例如,您仍然需要处理分页。
您无法真正使用 DynamoDB 执行您想要的查询。如果您知道 RequestItems
中可能包含的项目的最大数量,您唯一可以做的就是将大量 contains
检查与 OR
链接在一起:(RequestItems.0.Id = :val) OR (RequestItems.1.Id = :val) OR (RequestItems.2.Id = :val) ...
。但这似乎不是一个好主意,除非您事先知道 RequestItems
将始终包含一定数量的项目。
contains
没有按您希望的方式工作。如果您执行 contains(path, <some number>)
,DynamoDB 将检查在 path
处找到的值是否为 数字集 以及 <some number>
中提供的值是否包含在那一套。
鉴于您的数据模式,恐怕您唯一的选择是获取所有项目并在您的代码中过滤它们。
我有一个具有以下结构的 AWS DynamoDB Table:
我正在尝试取回至少有一个 ID 为 3401 的 RequestItem 的所有项目。 这是我到目前为止尝试过的(c# 代码):
IAmazonDynamoDB client = new AmazonDynamoDBClient(
new BasicAWSCredentials(configuration["AccessKey"], configuration["SecretKey"]),
RegionEndpoint.USEast1);
var request = new ScanRequest
{
TableName = "dynamo-table-name",
ExpressionAttributeNames = new Dictionary<string, string>
{
{"#requestItems", "RequestItems"},
{"#requestId", "Id"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{":val", new AttributeValue {N = "3401"}}
},
FilterExpression = "contains(#requestItems.#requestId, :val)"
};
var response = await client.ScanAsync(request);
我对 FilterExpression 做了一些修改(使用简单的“=”而不是 "contains")但是...我仍然没有得到结果。查询顺利通过,但结果是一个空列表。
但是,相同的代码适用于非集合的属性(例如 Contact.EmailAddress)
我错过了什么?
[编辑]
我尝试了另一个建议的解决方案:
var request = new ScanRequest
{
TableName = "dynamo-table-name",
ExpressionAttributeNames = new Dictionary<string, string>
{
{"#requestItems", "RequestItems"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{
":val",
new AttributeValue
{
L = new List<AttributeValue>
{
{
new AttributeValue
{
M = new Dictionary<string, AttributeValue>
{{"Id", new AttributeValue {N = "3401"}}}
}
}
}
}
}
},
FilterExpression = "contains(#requestItems, :val)"
};
var response = await client.ScanAsync(request);
但我仍然没有收到结果。
如有不当之处,敬请见谅
我怀疑 DynamoDB 不能做到这一点。
此外,DynamoDB 背后的想法是它不应该那样做。
DynamoDB 不支持对数据进行任意函数求值。
DynamoDB 是 K-V(有点)存储,而不是数据库。 "dynamo" 方法是查询您可能需要的所有行(项目)并在客户端分析列(键)。请注意,它的成本完全相同(对于 dynamo,流量差异很小),因为 aws 会向您收取类似 "database disk reads" 的费用。而且它同样繁琐或简单,例如,您仍然需要处理分页。
您无法真正使用 DynamoDB 执行您想要的查询。如果您知道 RequestItems
中可能包含的项目的最大数量,您唯一可以做的就是将大量 contains
检查与 OR
链接在一起:(RequestItems.0.Id = :val) OR (RequestItems.1.Id = :val) OR (RequestItems.2.Id = :val) ...
。但这似乎不是一个好主意,除非您事先知道 RequestItems
将始终包含一定数量的项目。
contains
没有按您希望的方式工作。如果您执行 contains(path, <some number>)
,DynamoDB 将检查在 path
处找到的值是否为 数字集 以及 <some number>
中提供的值是否包含在那一套。
鉴于您的数据模式,恐怕您唯一的选择是获取所有项目并在您的代码中过滤它们。