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
相关产品推荐
相关产品推荐

