2015-09-21 2 views
1

Я пытаюсь использовать таблицу DynamoDB для хранения этих данных:DynamoDB Xcode6 Swift с использованием трех колонок в качестве ключевых

DartsPlayerInsultTable

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 is my Hash Key PlayerId - это мой ключ диапазона , и я пытаюсь использовать PlayerInsult в ключе так, чтобы второе значение PlayerInsult вставляло вторую запись вместо замены существующей.

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

Любые предложения по наилучшему подходу к использованию для этого - DynanoDB? Мне нужно создать гибридный столбец для ключа диапазона? Пытаясь сохранить это просто ...

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 
    }) 

} 
+0

Как долго могут быть оскорбления и сколько их будет в среднем? Не могли бы вы опечатать оскорбления в виде списка в коде и сериализовать их в одном поле? Возможно, вы все равно столкнетесь с ситуацией, когда вам нужно ведро на PlayerId, если вы нарушите ограничение по размеру для одной записи. –

+0

Приговоры, менее 100. Хранение их в «Динамо» поставляется с готовым шаблоном для отображения/вставки/обновления/удаления из приложения iOS. Не уверен, есть ли простой способ сопоставить контроллер быстрого просмотра таблицы с массивом или аналогичным, но я должен исследовать. Это может упростить ситуацию. – iWombat

ответ

0

Положив это как ответ, а не другой комментарий в случае, если он получает долго ...

Это звучит как оскорблениями среднестатистического пользователя может поместиться в одной записи , С отказом от ответственности, что я абсолютно ничего не знаю о быстрой, это может быть, по крайней мере, относительно простым. Держите ключи для клиентов и игроков. Прежде чем упорствовать в оскорблениях, переведите весь список в одну большую строку, используя любую версию соединения («|») swift. Когда вы извлекаете запись, выполните разделение («|»), чтобы вернуть свой список. (Просто будьте осторожны с вашим выбором разделителей, я использую в качестве примера только «|», вы не хотите выбирать что-то, что может появиться в оскорблении ...)

Там будет что один пользователь с достаточным количеством оскорблений, чтобы взять вас за ограничение объекта 400kb. Задайте максимальную константу размера списка в своем коде - когда вы переводите свои списки в строки, чтобы сохранить их на динамо, проверьте длину списка игроков на этот предел. Если вы его превысите, разбейте свой список на куски такого размера и используйте хеш-ключи и клавиши диапазона, такие как («foo», «bar»), («foo», «bar1»), («foo», «bar2») и т. д. Да, первый делает не имеет номер ведра в конце ...

Когда вы запрашиваете данные, сначала выполните прямой запрос и предположите, что вы будете в хорошем случае (просто «foo» и «bar», никаких других ведер). Когда вы распаковываете этот первый список, проверьте его длину. Если он равен вашей константе максимального размера списка, вы знаете, что у вас «плохой» пользователь, и вам нужно выполнить запрос диапазона. Этот второй может использовать хеш-ключ «foo» и диапазон «bar» на «bar9999». Вы будете возвращать все эти ведра с этим запросом диапазона. Распакуйте и соедините все списки.

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

0

То, что я решил сделать, это сделать обычную таблицу dynamodb только с одним хэш-ключ, но новый хэш-ключ представляет собой комбинированную строку:

CustomerId + «|» + PlayerId

Непросто поддерживать синхронизацию между игроками и таблицами оскорблений, потому что, как только игрок вставлен в таблицу игроков, изменение имени игрока приводит к вставке новой строки. Таким образом, оскорбления не нужно изменять, если имя игрока изменяется. Вам нужно только очистить оскорбления, если игрок удален.

Это поведение обновления - это то, как работает dynamodb, если вы сделаете имя игрока хеш-ключом, который я сделал, чтобы гарантировать, что они уникальны.

Смежные вопросы