13

我试图了解如何使用 DataModel 在 dynamo 中查询表。但是,我发现了两种似乎可行的方法,但我找不到正在发生的事情的解释或文档,或者它们之间是否有任何区别。

我发现的方法是使用FilterKeyExpression + 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、密钥和分区

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、密钥和分区

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();
}
4

1 回答 1

6

令人困惑的是,这些选项之间似乎几乎没有区别。AWSSDK.DynamoDBv2 程序集中的注释似乎提供了最好的文档。尽管 DynamoDb 中的术语“查询过滤器”专门指读后处理,但绝对可以应用QueryOperationConfig.Filter针对关键属性的查询过滤器(并在运行时检查)。注释指定关键属性与非关键属性的事实清楚地表明,这些实际上是读取时关键表达式“过滤器”,而不是真正意义上的读取后过滤器。

当然,这与我们对 DynamoDb 查询的一般了解一致:它们以分区为目标。因此,在哈希键上具有单个过滤条件的 QueryOperationConfig 必须以该分区为目标,并且不可能充当读取后过滤器。以其他方式解释它会假设实际扫描表然后应用过滤器,这对Query.

总而言之:DocumentModel 提供了两个等效选项 -QueryOperationConfig.KeyExpression选项非常清晰,但暴露了较低级别的 API,QueryOperationConfig.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);
    }
}

于 2021-01-26T00:51:21.673 回答