【问题标题】:Is it possible to filter by the range/sort key in Dynamodb?是否可以通过 Dynamodb 中的范围/排序键进行过滤?
【发布时间】:2020-07-09 07:09:22
【问题描述】:

我有一个非常简单的“小网址”应用程序,我在其中接收网址并返回一个别名。我有一个这样定义的表:

    input := &dynamodb.CreateTableInput{
        AttributeDefinitions: []*dynamodb.AttributeDefinition{
            {
                AttributeName: aws.String("Alias"),
                AttributeType: aws.String("S"),
            },
            {
                AttributeName: aws.String("ExpiresAt"),
                AttributeType: aws.String("S"),
            },
        },
        KeySchema: []*dynamodb.KeySchemaElement{
            {
                AttributeName: aws.String("Alias"),
                KeyType:       aws.String("HASH"),
            },
            {
                AttributeName: aws.String("ExpiresAt"),
                KeyType:       aws.String("RANGE"),
            },
        },
        ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
            ReadCapacityUnits:  aws.Int64(readCapacityUnits),
            WriteCapacityUnits: aws.Int64(writeCapacityUnits),
        },

        TableName: aws.String(tableName),
    }

主键是复合键,由别名作为分区键和到期作为排序键组成。

我的问题是我试图按分区键查询,然后按排序键过滤。用例试图返回自定义(别名)域以重定向到,只要它没有过期。

这是我的查询:

    result, err := db.Query(&dynamodb.QueryInput{
        TableName:              aws.String(tableName),
        KeyConditionExpression: aws.String("#A = :alias AND :expires_at >= #T"),
        ExpressionAttributeNames: map[string]*string{
            "#A": aws.String("Alias"),
            "#T": aws.String(time.Now().String()),
        },
        ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
            ":alias": {
                S: aws.String(alias),
            },
            ":created_at": {
                S: aws.String("ExpiresAt"),
            },
        },
        Limit: aws.Int64(1),
    })

我收到了这个问题:

ValidationException: Query condition missed key schema element
    status code: 400, request id: 7c479115-7e3d-43ae-b94e-3fdf40cb3441

现在我知道我可以设置 GSI,但我想知道排序键 (ExpiresAt) 是否可以用于此目的。我也知道我可以为每个项目设置一个 TTL,但我认为我在 go SDK 中没有看到任何使这成为可能的东西,我宁愿不去命令行。

我应该补充一点,这是一个学习练习。显然,我可以将行拉入内存并手动检查到期时间,但我想了解范围键以及它的真正用途。

根据阅读 dynamodb book 我猜这是我查询中某处的语义错误。

想法?

编辑

我提出了一种查询字段的不同方法,但它似乎遇到了不同的错误。

    result, err := db.Query(&dynamodb.QueryInput{
        TableName:              aws.String(tableName),
        KeyConditionExpression: aws.String("#A = :alias AND #T >= ExpiresAt"),
        ExpressionAttributeNames: map[string]*string{
            "#A": aws.String("Alias"),
            "#T": aws.String(time.Now().String()),
        },
        ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
            ":alias": {
                S: aws.String(alias),
            },
        },
        Limit: aws.Int64(1),
    })

现在返回:

ValidationException: Invalid condition in KeyConditionExpression: Multiple attribute names used in one condition
    status code: 400, request id: 2df7a659-0f5c-4609-a923-397a6e05b630

【问题讨论】:

    标签: go amazon-dynamodb


    【解决方案1】:

    看起来您在 KeyConditionExpression 中的键和值颠倒了。试试这个,

    result, err := db.Query(&dynamodb.QueryInput{
        TableName:              aws.String(tableName),
        KeyConditionExpression: aws.String("#A = :alias AND #E <= :expires_at"),
        ExpressionAttributeNames: map[string]*string{
            "#A": aws.String("Alias"),
            "#E": aws.String("ExpiresAt"),
        },
        ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
            ":alias": {
                S: aws.String(alias),
            },
            ":expires_at": {
                S: aws.String(time.Now().String()),
            },
        },
        Limit: aws.Int64(1),
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 2018-05-13
      相关资源
      最近更新 更多