Можно ли фильтровать по ключу диапазона / сортировки в Dynamodb? - PullRequest
1 голос
/ 09 июля 2020

У меня есть очень простое приложение для «крошечных URL-адресов», в котором я беру URL-адреса и возвращаю псевдоним. У меня есть таблица, определенная следующим образом:

    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 для отдельных элементов, но я не думаю, что видел что-либо в SDK go, что делает это возможным, и я бы предпочел не использовать go в командной строке.

Я должен добавить, что это обучающее упражнение. Очевидно, я могу вытащить строку в память и проверить срок ее действия вручную, но я хочу понять ключ диапазона и его назначение.

На основе чтения динамодб книги I ' я предполагаю, что где-то в моем запросе это ошибка semanti c.

Мысли?

Edit

Я представил другой способ запроса поля, и кажется, что это другая ошибка.

    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

1 Ответ

1 голос
/ 09 июля 2020

Похоже, у вас поменяли местами ключи и значения в 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),
})
...