为什么我的DynamoDB二级索引只能与部分排序键一起使用

时间:2019-04-01 13:43:08

标签: c# .net amazon-web-services amazon-dynamodb

使用BeginsWith运算符查询二级索引中的表并不总是返回正确的记录。可能是什么原因?

我有示例代码,并针对本地DynamoDB表和AWS中的表进行了尝试。结果是一样的。

定义二级索引:

        var gsiKey1Index = new GlobalSecondaryIndex
        {
            IndexName = "GSIKey1Index",
            ProvisionedThroughput = new ProvisionedThroughput
            {
                ReadCapacityUnits = 1,
                WriteCapacityUnits = 1
            },
            Projection = new Projection { ProjectionType = "ALL" }
        };

        var indexKey1Schema = new List<KeySchemaElement> {
            {
                new KeySchemaElement
                {
                    AttributeName = "HashKey", KeyType = KeyType.HASH
                }
            },  //Partition key
            {
                new KeySchemaElement
                {
                    AttributeName = "GSISortKey1", KeyType = KeyType.RANGE
                }
            }  //Sort key
        };
        gsiKey1Index.KeySchema = indexKey1Schema;

创建表格:

        var request = new CreateTableRequest
        {
            TableName = "TestTable",
            AttributeDefinitions = new List<AttributeDefinition>
            {
                new AttributeDefinition
                {
                    AttributeName = "HashKey",
                    // "S" = string, "N" = number, and so on.
                    AttributeType = "S"
                },
                new AttributeDefinition
                {
                    AttributeName = "SortKey",
                    AttributeType = "S"
                },
                new AttributeDefinition
                {
                AttributeName = "GSISortKey1",
                // "S" = string, "N" = number, and so on.
                AttributeType = "S"
            },

            },
            KeySchema = new List<KeySchemaElement>
            {
                new KeySchemaElement
                {
                    AttributeName = "HashKey",
                    // "HASH" = hash key, "RANGE" = range key.
                    KeyType = "HASH"
                },
                new KeySchemaElement
                {
                    AttributeName = "SortKey",
                    KeyType = "RANGE"
                },
            },
            GlobalSecondaryIndexes = { gsiKey1Index },
            ProvisionedThroughput = new ProvisionedThroughput
            {
                ReadCapacityUnits = 10,
                WriteCapacityUnits = 5
            },
        };


        response2 = await _client.CreateTableAsync(request);

实体看起来像这样:

[DynamoDBTable("TestTable")]
public sealed class TestResult
{
    [DynamoDBHashKey]
    public string HashKey {get;set;}
    public string SortKey {get;set;}
    public string GSISortKey1 {get; set;}
}

要查询的代码如下:

    public async Task<List<TestResult>> GetTestResultByDateTimeAsync(Guid hashid, Guid someId, string someName, DateTime timestamp)
    {
        var key2 = $"TR-{someId}-{someName}-{timestamp:yyyy-MM-ddTHH\\:mm\\:ss.fffZ}";
        var key = $"TR-{someId}-{someName}-{timestamp:yyyy-MM-dd}";
        //var filter = new QueryFilter();
        //filter.AddCondition("HashKey", ScanOperator.Equal, hashid.ToString());
        //filter.AddCondition("GSISortKey1", ScanOperator.BeginsWith, key);
        //var queryConfig = new QueryOperationConfig
        //{
        //    Filter = filter
        //};
        DynamoDBOperationConfig operationConfig = new DynamoDBOperationConfig()
        {
            OverrideTableName = "DEVTransponderTR",
            IndexName = "GSIKey1Index",
            QueryFilter = new List<ScanCondition>()
        };
        var sc = new ScanCondition("GSISortKey1", ScanOperator.BeginsWith, new[] { key });
        operationConfig.QueryFilter.Add(sc);
        var search = _context.QueryAsync<TestResult>(tenantid.ToString(), operationConfig);
        var testresults = await search.GetRemainingAsync();
        bool keywasok = true;
        foreach (var testresult in testresults)
        {
            keywasok = testresult.GSISortKey1.StartsWith(key2) && keywasok;
        }

        if (keywasok) // this means I should find the same values if I use key2
        {
            DynamoDBOperationConfig operationConfig2 = new DynamoDBOperationConfig()
            {
                OverrideTableName = "TestTable",
                IndexName = "GSIKey1Index",
                QueryFilter = new List<ScanCondition>()
            };
            var sc2 = new ScanCondition("GSISortKey1", ScanOperator.BeginsWith, new[] { key2 });
            operationConfig2.QueryFilter.Add(sc2);
            var search2 = _context.QueryAsync<TestResult>(tenantid.ToString(), operationConfig);
            var testresults2 = await search.GetRemainingAsync();


        }

        return testresults;
    }

然后将三个实例添加到表中。重要的是,除GSISortKey1值外,所有信息都相同。这是三个项目的GSISortKey1值:

“ TR-0d798900-a852-4a75-bef0-5dd5c96c657c-Module1-2019-04-02T12:24:19.000Z-打开” “ TR-0d798900-a852-4a75-bef0-5dd5c96c657c-Module1-2019-04-02T12:24:19.000Z-发送” “ TR-0d798900-a852-4a75-bef0-5dd5c96c657c-Module1-2019-04-02T12:24:19.000Z-Test”

因此,在示例中,我首先在“ BeginsWith”上查询值“ TR-0d798900-a852-4a75-bef0-5dd5c96c657c-Module1-2019-04-02”(这是var键)

它返回所有三个项目。

然后,我检查三个返回项目的整个GSISortKey1值是否也将以值“ TR-0d798900-a852-4a75-bef0-5dd5c96c657c-Module1-2019-04-02T12:24:19.000Z-”开头,并且那是真实的。

如果是这样,我只需使用值“ TR-0d798900-a852-4a75-bef0-5dd5c96c657c-Module1-2019-04-02T12:24:19.000Z-”再次使用BeginsWith进行查询

它应该返回所有三个项目。它返回0个项目。

我想我做错了,感谢一些帮助。

0 个答案:

没有答案