You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中仅用范围键查询AWS DynamoDB服务器的问题

解决DynamoDB仅通过范围键查询的问题

你的问题核心在于DynamoDB的主表查询规则:主表的查询必须包含哈希键,因为主表是按哈希键分区存储的,没有哈希键的话,DynamoDB不知道该扫描哪个分区,所以会报错。要实现仅通过randomCode查找用户的需求,你需要创建一个全局二级索引(GSI),把randomCode作为这个索引的哈希键。

步骤1:创建全局二级索引

你需要在你的DynamoDB表上创建一个GSI,具体操作如下:

  • 登录AWS控制台,进入DynamoDB服务,找到你的Timestamps表
  • 切换到「索引」标签页,点击「创建索引」
  • 选择「全局二级索引」,设置:
    • 索引名称:比如RandomCodeIndex(自定义即可)
    • 分区键(哈希键):选择randomCode(你的原范围键字段)
    • 投影模式:选择「全部」(这样查询索引时能获取到所有属性,比如userId、songURI等;如果只需要特定属性,可以选「指定属性」并勾选需要的字段)
    • 配置读写容量(根据你的业务需求调整,初期可以用默认值)
  • 点击「创建索引」等待索引创建完成(可能需要几分钟)

步骤2:修改查询代码

创建好GSI后,你需要修改查询逻辑,指定查询这个索引,并且只使用randomCode作为查询条件,不需要再传入userId。修改后的代码如下:

// 1) 构建查询表达式,指定查询GSI
let queryExpression = AWSDynamoDBQueryExpression()
queryExpression.keyConditionExpression = "#randomCode = :randomCode"
queryExpression.expressionAttributeNames = [
    "#randomCode": "randomCode"
]
queryExpression.expressionAttributeValues = [
    ":randomCode": passedCode
]
// 指定要查询的全局二级索引名称,和你创建的GSI名称一致
queryExpression.indexName = "RandomCodeIndex"

// 2) 执行查询
dynamoDbObjectMapper.query(Timestamps.self, expression: queryExpression) { (output: AWSDynamoDBPaginatedOutput?, error: Error?) in
    if let error = error {
        print("请求失败,错误:\(error.localizedDescription)")
        return
    }
    
    guard let output = output else {
        print("输出为空")
        return
    }
    
    if output.items.isEmpty {
        print("未找到对应代码")
        DispatchQueue.main.async {
            let animation = CABasicAnimation(keyPath: "position")
            animation.duration = 0.07
            animation.repeatCount = 4
            animation.autoreverses = true
            animation.fromValue = NSValue(cgPoint: CGPoint(x: self.codeTextField.center.x - 10, y: self.codeTextField.center.y))
            animation.toValue = NSValue(cgPoint: CGPoint(x: self.codeTextField.center.x + 10, y: self.codeTextField.center.y))
            self.codeTextField.layer.add(animation, forKey: "position")
        }
    } else {
        for timestamps in output.items {
            guard let timestampItem = timestamps as? Timestamps else { continue }
            let currentSong = timestampItem._songURI as! String
            let currentTimestampDouble = timestampItem._timestamp as! Double
            self.playSync(currentSong: currentSong, currentTimestamp: currentTimestampDouble)
        }
    }
}

注意事项

  • 最终一致性:GSI使用的是最终一致性,所以当你刚生成randomCode并写入主表后,可能需要几秒才能在GSI中查到数据,这是正常现象。
  • 索引维护成本:GSI会占用额外的存储和读写容量,记得根据你的业务量调整配置,避免不必要的成本。
  • 唯一性:如果需要确保randomCode是唯一的,你可以在写入数据时先查询GSI,确认该代码未被使用,避免重复。

内容的提问来源于stack exchange,提问作者Jeffrey Bloom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:34:56