1

DynamoDB テーブルを使用してこのデータを保存しようとしています。

ダーツプレーヤー侮辱テーブル

CustomerId   String

PlayerId     String

PlayerInsult String

ここで説明されている方法 (コードではなく概念) を使用します。

https://java.awsblog.com/post/Tx3GYZEVGO924K4/The-DynamoDBMapper-Local-Secondary-Indexes-and-You

ここ:

http://mobile.awsblog.com/post/TxTCW7KW8BGZAF/Amazon-DynamoDB-on-Mobile-Part-4-Local-Secondary-Indexes

そしてここ:

http://labs.journwe.com/2013/12/15/dynamodb-secondary-indexes/comment-page-1/#comment-116

顧客プレーヤーごとに複数の侮辱記録が必要です。CustomerId は私のハッシュ キー PlayerId は私の範囲キーであり、キーで PlayerInsult を使用して、2 番目の PlayerInsult 値が既存のレコードを置き換えるのではなく 2 番目のレコードを挿入しようとしています。

このためにグローバル インデックスとセカンダリ インデックスの両方を試しましたが、新しい侮辱を含む行を追加しようとすると、新しい侮辱を追加するのではなく、侮辱を同じ顧客プレーヤー キーに置き換えます。

これに使用する最善のアプローチについて何か提案はありますか? 範囲キーのハイブリッド列を作成する必要がありますか? これをシンプルにしようと...

class func createDartsPlayerInsultTable() -> BFTask {
    let dynamoDB = AWSDynamoDB.defaultDynamoDB()

    let hashKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
    hashKeyAttributeDefinition.attributeName = "CustomerId"
    hashKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S

    let hashKeySchemaElement = AWSDynamoDBKeySchemaElement()
    hashKeySchemaElement.attributeName = "CustomerId"
    hashKeySchemaElement.keyType = AWSDynamoDBKeyType.Hash

    let rangeKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
    rangeKeyAttributeDefinition.attributeName = "PlayerId"
    rangeKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S

    let rangeKeySchemaElement = AWSDynamoDBKeySchemaElement()
    rangeKeySchemaElement.attributeName = "PlayerId"
    rangeKeySchemaElement.keyType = AWSDynamoDBKeyType.Range

    /*
    let indexRangeKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
    indexRangeKeyAttributeDefinition.attributeName = "PlayerInsult"
    indexRangeKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S

    let rangeKeySchemaElement = AWSDynamoDBKeySchemaElement()
    rangeKeySchemaElement.attributeName = "PlayerId"
    rangeKeySchemaElement.keyType = AWSDynamoDBKeyType.Range

    let indexRangeKeyElement =  AWSDynamoDBKeySchemaElement()
    indexRangeKeyElement.attributeName = "PlayerInsult"
    indexRangeKeyElement.keyType = AWSDynamoDBIndexRangeKeyType.
    */

    //Add non-key attributes
    let playerInsultAttrDef = AWSDynamoDBAttributeDefinition()
    playerInsultAttrDef.attributeName = "PlayerInsult"
    playerInsultAttrDef.attributeType = AWSDynamoDBScalarAttributeType.S

    let provisionedThroughput = AWSDynamoDBProvisionedThroughput()
    provisionedThroughput.readCapacityUnits = 5
    provisionedThroughput.writeCapacityUnits = 5

    // CREATE GLOBAL SECONDARY INDEX
    /*
    let gsi = AWSDynamoDBGlobalSecondaryIndex()
    let gsiArray = NSMutableArray()

    let gsiHashKeySchema = AWSDynamoDBKeySchemaElement()
    gsiHashKeySchema.attributeName = "PlayerId"
    gsiHashKeySchema.keyType = AWSDynamoDBKeyType.Hash

    let gsiRangeKeySchema = AWSDynamoDBKeySchemaElement()
    gsiRangeKeySchema.attributeName = "PlayerInsult"
    gsiRangeKeySchema.keyType = AWSDynamoDBKeyType.Range

    let gsiProjection = AWSDynamoDBProjection()
    gsiProjection.projectionType = AWSDynamoDBProjectionType.All;

    gsi.keySchema = [gsiHashKeySchema,gsiRangeKeySchema];
    gsi.indexName = "PlayerInsult";
    gsi.projection = gsiProjection;
    gsi.provisionedThroughput = provisionedThroughput;

    gsiArray .addObject(gsi)
    */

    // CREATE LOCAL SECONDARY INDEX

    let lsi = AWSDynamoDBLocalSecondaryIndex()
    let lsiArray = NSMutableArray()

    let lsiHashKeySchema = AWSDynamoDBKeySchemaElement()
    lsiHashKeySchema.attributeName = "CustomerId"
    lsiHashKeySchema.keyType = AWSDynamoDBKeyType.Hash

    let lsiRangeKeySchema = AWSDynamoDBKeySchemaElement()
    lsiRangeKeySchema.attributeName = "PlayerInsult"
    lsiRangeKeySchema.keyType = AWSDynamoDBKeyType.Range

    let lsiProjection = AWSDynamoDBProjection()
    lsiProjection.projectionType = AWSDynamoDBProjectionType.All;

    lsi.keySchema = [lsiHashKeySchema,lsiRangeKeySchema];
    lsi.indexName = "PlayerInsult";
    lsi.projection = lsiProjection;
    //lsi.provisionedThroughput = provisionedThroughput;

    lsiArray .addObject(lsi)


    //Create TableInput
    let createTableInput = AWSDynamoDBCreateTableInput()
    createTableInput.tableName = DartsPlayerInsultTableName;
    createTableInput.attributeDefinitions = [hashKeyAttributeDefinition, rangeKeyAttributeDefinition, playerInsultAttrDef]
    //createTableInput.attributeDefinitions = [hashKeyAttributeDefinition, rangeKeyAttributeDefinition]
    createTableInput.keySchema = [hashKeySchemaElement, rangeKeySchemaElement]
    createTableInput.provisionedThroughput = provisionedThroughput
    //createTableInput.globalSecondaryIndexes = gsiArray as [AnyObject]
    createTableInput.localSecondaryIndexes = lsiArray as [AnyObject]

    return dynamoDB.createTable(createTableInput).continueWithSuccessBlock({ (var task:BFTask!) -> AnyObject! in
        if ((task.result) != nil) {
            // Wait for up to 4 minutes until the table becomes ACTIVE.

            let describeTableInput = AWSDynamoDBDescribeTableInput()
            describeTableInput.tableName = DartsPlayerInsultTableName;
            task = dynamoDB.describeTable(describeTableInput)

            for var i = 0; i < 16; i++ {
                task = task.continueWithSuccessBlock({ (task:BFTask!) -> AnyObject! in
                    let describeTableOutput:AWSDynamoDBDescribeTableOutput = task.result as! AWSDynamoDBDescribeTableOutput
                    let tableStatus = describeTableOutput.table.tableStatus
                    if tableStatus == AWSDynamoDBTableStatus.Active {
                        return task
                    }

                    sleep(15)
                    return dynamoDB .describeTable(describeTableInput)
                })
            }
        }

        return task
    })

}
4

2 に答える 2

0

長くなった場合に備えて、これを別のコメントではなく回答として入れます...

平均的なユーザーの侮辱は 1 つのレコードに収まるように思えます。私はSwiftについてまったく知らないという免責事項があるため、これは少なくとも比較的単純なものかもしれません。顧客とプレーヤーの鍵を保管してください。侮辱を永続化する前に、join("|") swift のバージョンを使用して、リスト全体を 1 つの大きな文字列に変換します。レコードを取得するときは、split("|") を実行してリストを取得します。(セパレーターの選択には少し注意してください。例として「|」を使用しているだけです。侮辱に現れる可能性のあるものを選択したくありません...)

400kb のオブジェクト制限を超えてしまうほどの侮辱を持った 1 人のユーザーがいるでしょう。コードでリストの最大サイズ定数を設定します。リストを文字列に変換して dynamo に永続化する場合は、その制限に対してプレーヤーのリストの長さを確認してください。それを超える場合は、リストをそのサイズのチャンクに分割し、("foo", "bar")、("foo", "bar1")、("foo", "bar2")、など はい、最初のものは最後にバケット番号がありません...

データをクエリするときは、最初に単純なクエリを実行し、適切なケースになると想定します (「foo」と「bar」のみで、他のバケットはありません)。最初のリストを解凍するときは、その長さを確認してください。それが最大リスト サイズ定数と等しい場合は、「悪い」ユーザーがいて、範囲クエリを実行する必要があることがわかります。2 つ目は、ハッシュ キー "foo" と範囲 "bar" から "bar9999" を使用できます。その範囲クエリを使用して、これらすべてのバケットを取得します。すべてのリストをアンパックして連結します。

これは少し面倒ですが、最終的にはすぐにコードを作成する必要があります。うまくいけば、あなたが言及したパターンにフックするのに十分簡単です。

于 2015-09-21T23:51:37.807 に答える
0

私がやろうと決めたのは、ハッシュキーを 1 つだけ持つ従来の dynamodb テーブルを作成することでしたが、新しいハッシュキーは次の文字列を組み合わせたものです。

CustomerId + "|" + PlayerId

プレーヤーがプレーヤー テーブルに挿入されると、プレーヤー名を変更すると新しい行が挿入されるため、プレーヤーと侮辱テーブル間の同期を維持することはそれほど難しくありません。したがって、プレイヤー名が変更された場合、侮辱を変更する必要はありません。プレイヤーが削除された場合にのみ、侮辱をクリーンアップする必要があります。

この更新動作は、Player 名をハッシュ キーにした場合の dynamodb の動作と同じです。これは、一意であることを保証するために行ったものです。

于 2015-09-22T19:17:43.550 に答える