使用 .NET SDK 查询 DynamoDB 表的正确方法

16

我正在尝试使用DataModel查询Dynamo表,但我发现有两种方法似乎都有效,但我找不到解释或文档说明它们之间的区别。

我发现的两种方法分别是使用 Filter 或者 KeyExpression + FilterExpression。它们有什么区别和正确的使用方式呢?

以下是一些示例:

选项1:

-- 使用索引和键

public async Task<List<T>> Find<T>(Guid id)
{
    var query = new QueryOperationConfig
    {
        IndexName = "Table_Id_Index",
        Filter = new QueryFilter("TableId", QueryOperator.Equal, id)
    };

    return await _dynamoDbContext
        .FromQueryAsync<T>(query)
        .GetRemainingAsync();
}

-- 带有索引、键和额外过滤条件

public async Task<List<T>> Find<T>(Guid id)
{
    var query = new QueryOperationConfig
    {
        IndexName = "Table_Id_Index",
        Filter = new QueryFilter("TableId", QueryOperator.Equal, id)
    };

    query.AddCondition("Deleted", ScanOperator.NotEqual, true);

    return await _dynamoDbContext
        .FromQueryAsync<T>(query)
        .GetRemainingAsync();
}

-- 使用GSI,Key和Partion

public async Task<List<T>> Find<T>(Guid id, string partitionKey)
{
    var query = new QueryOperationConfig
    {
        IndexName = "GSI_Index",
        Filter = new QueryFilter("TableId", QueryOperator.Equal, id)
    };

    query.AddCondition("PartitionKey", QueryOperator.Equal, partitionKey);

    return await _dynamoDbContext
        .FromQueryAsync<T>(query)
        .GetRemainingAsync();
}

选项2:

-- 带有索引和键值

public async Task<List<T>> Find<T>(Guid id)
{
    var expressionAttributeValues = new Dictionary<string, DynamoDBEntry>();
    expressionAttributeValues.Add(":v_TableId", id);

    var queryOperationConfig = new QueryOperationConfig
    {
        IndexName = "Table_Id_Index",
        KeyExpression = new Expression
        {
            ExpressionStatement = "TableId = :v_TableId"
            ExpressionAttributeValues = expressionAttributeValues
        }
    };

    var result = await _dynamoDBContext
        .FromQueryAsync<T>(query)
        .GetRemainingAsync();
}
-- 带有索引、键和额外筛选
public async Task<List<T>> Find<T>(Guid id)
{
    var expressionAttributeValues = new Dictionary<string, DynamoDBEntry>();
    expressionAttributeValues.Add(":v_TableId", id);

    var filterAttributes = new Dictionary<string, DynamoDBEntry>();
    filterAttributes.Add(":v_Deleted", true);

    var queryOperationConfig = new QueryOperationConfig
    {
        IndexName = "Table_Id_Index",
        KeyExpression = new Expression
        {
            ExpressionStatement = "TableId = :v_TableId"
            ExpressionAttributeValues = expressionAttributeValues
        }
        FilterExpression = new Expression
        {
            ExpressionStatement = "Deleted != :v_Deleted"
            ExpressionAttributeValues = filterAttributes
        };
    };

    var result = await _dynamoDBContext
        .FromQueryAsync<T>(query)
        .GetRemainingAsync();
}

-- 使用 GSI、Key 和 Partition

public async Task<List<T>> Find<T>(Guid id, string partitionKey)
{
    var expressionAttributeValues = new Dictionary<string, DynamoDBEntry>();
    expressionAttributeValues.Add(":v_TableId", id);
    expressionAttributeValues.Add(":v_PartitionKey", partitionKey);

    var queryOperationConfig = new QueryOperationConfig
    {
        IndexName = "GSI_Index",
        KeyExpression = new Expression
        {
            ExpressionStatement = "TableId = :v_TableId and PartitionKey = :v_PartitionKey"
            ExpressionAttributeValues = expressionAttributeValues
        }
    };

    var result = await _dynamoDBContext
        .FromQueryAsync<T>(query)
        .GetRemainingAsync();
}
1个回答

12
令人困惑的是,这些选项似乎没有什么区别。AWSSDK.DynamoDBv2程序集中的注释似乎提供了最好的文档。尽管DynamoDb中的“Query Filter”专门指后读处理,但确实可以应用一个QueryOperationConfig.Filter,它针对关键属性(并在运行时进行检查)。注释指定关键属性与非关键属性清楚地表明这些实际上是读取时间关键表达式“过滤器”,而不是真正意义上的后读过滤器。
当然,这符合我们对DynamoDb查询的一般了解:它们针对分区。因此,具有散列键上单个过滤条件的QueryOperationConfig必须针对该分区,并且不可能作为后读筛选器。否则将假定实际扫描表然后应用过滤器,这对于Query毫无意义。
因此,总之:DocumentModel提供了两个等效选项-QueryOperationConfig.KeyExpression选项非常清晰,但暴露了较低级别的API,而QueryOperationConfig.Filter选项则抽象了它,但混淆了有意义的术语“filter”。如果设计了一个KeyExpression类型,可能带有AddHashKeyCondition(...)AddRangeKeyCondition(...)方法,那么就会更清晰。
#region Assembly AWSSDK.DynamoDBv2, Version=3.3.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604
// AWSSDK.DynamoDBv2.dll
#endregion

using System.Collections.Generic;
using Amazon.DynamoDBv2.Model;

namespace Amazon.DynamoDBv2.DocumentModel
{
    //
    // Summary:
    //     Query filter.
    public class QueryFilter : Filter
    {
        //
        // Summary:
        //     Constructs an empty QueryFilter instance
        public QueryFilter();
        //
        // Summary:
        //     Constructs an instance of QueryFilter with a single condition. More conditions
        //     can be added after initialization.
        //
        // Parameters:
        //   attributeName:
        //     Target attribute name
        //
        //   op:
        //     Comparison operator
        //
        //   values:
        //     Attributes to compare
        public QueryFilter(string attributeName, QueryOperator op, List<AttributeValue> values);
        //
        // Summary:
        //     Constructs an instance of QueryFilter with a single condition. More conditions
        //     can be added after initialization.
        //
        // Parameters:
        //   attributeName:
        //     Target attribute name
        //
        //   op:
        //     Comparison operator
        //
        //   values:
        //     Attributes to compare
        public QueryFilter(string attributeName, QueryOperator op, params DynamoDBEntry[] values);

        //
        // Summary:
        //     Adds a condition for a specified key attribute that consists of an operator and
        //     any number of AttributeValues.
        //
        // Parameters:
        //   keyAttributeName:
        //     Target key attribute name
        //
        //   op:
        //     Comparison operator
        //
        //   values:
        //     AttributeValues to compare to
        public void AddCondition(string keyAttributeName, QueryOperator op, List<AttributeValue> values);
        //
        // Summary:
        //     Adds a condition for a specified key attribute that consists of an operator and
        //     any number of values
        //
        // Parameters:
        //   keyAttributeName:
        //     Target key attribute name
        //
        //   op:
        //     Comparison operator
        //
        //   values:
        //     Values to compare to
        public void AddCondition(string keyAttributeName, QueryOperator op, params DynamoDBEntry[] values);
        //
        // Summary:
        //     Adds a condition for a specified non-key attribute that consists of an operator
        //     and any number of AttributeValues.
        //
        // Parameters:
        //   nonKeyAttributeName:
        //     Target non-key attribute name
        //
        //   op:
        //     Comparison operator
        //
        //   values:
        //     AttributeValues to compare to
        public void AddCondition(string nonKeyAttributeName, ScanOperator op, List<AttributeValue> values);
        //
        // Summary:
        //     Adds a condition for a specified non-key attribute that consists of an operator
        //     and any number of values
        //
        // Parameters:
        //   nonKeyAttributeName:
        //     Target non-key attribute name
        //
        //   op:
        //     Comparison operator
        //
        //   values:
        //     Values to compare to
        public void AddCondition(string nonKeyAttributeName, ScanOperator op, params DynamoDBEntry[] values);
    }
}


谢谢这个。在今天与这个相同问题搏斗之后,我同意你关于KeyExpression类型的建议。 - jbdev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接