如何通过Alexa Skill的DynamoDB Adapter迭代更新嵌套属性
问题:Alexa技能中DynamoDB嵌套属性更新失败
我正在为Alexa技能使用DynamoDB Adapter,刚接触开发,问题可能比较基础。
我要持久化的嵌套属性初始格式如下:
enqueue_data = { "ENQUEUE": [ { "link_enqueue": "http://link1.com", "offset_in_milliseconds_enqueue": "numerical value", "title": "title 1" }, { "link_enqueue": "http://link2.com", "offset_in_milliseconds_enqueue": "numerical value", "title": "title 2" } ] }
但在DynamoDB中实际存储的格式是:
{ "link" : { "S" : "http://link1.com" }, "ENQUEUE" : { "L" : [ { "M" : { "title_enqueue" : { "S" : "Title 1" }, "link_enqueue" : { "S" : "http://link1.com" }, "offset_in_milliseconds_enqueue" : { "N" : "15645" } } }, { "M" : { "title_enqueue" : { "S" : "title 2" }, "link_enqueue" : { "S" : "http://link2.com" }, "offset_in_milliseconds_enqueue" : { "N" : "52546" } } } ] } }
我已经通过selected_link = attr['link']成功获取到了selected_link变量,现在需要实现以下逻辑:
- 判断ENQUEUE键是否存在;
- 若存在,遍历ENQUEUE中的link_enqueue值,找到与selected_link匹配的项;
- 匹配成功则更新该项的offset_in_milliseconds_enqueue值。
举个例子:当selected_link为http://link1.com时,找到ENQUEUE中对应项,将其offset_in_milliseconds_enqueue更新为新值。
我写了如下Python代码,但没达到预期效果:
def handle(self, handler_input): offset_in_milliseconds = '3232' # 获取dynamodb中的属性 attr = handler_input.attributes_manager.persistent_attributes # 获取link值 selected_link = attr['link'] # 检查持久化属性中是否存在'ENQUEUE'键 if 'ENQUEUE' in attr: enqueue_data = attr['ENQUEUE'] # 检查ENQUEUE中是否有项包含匹配的link_enqueue relevant_items = [item for item in enqueue_data.values() if item.get('link_enqueue') == selected_link] if relevant_items: relevant_item = relevant_items[0] # 假设取第一个匹配项 relevant_item['offset_in_milliseconds_enqueue'] = offset_in_milliseconds # 保存更新后的持久化属性 handler_input.attributes_manager.save_persistent_attributes() return return return
我期望更新后只有目标项的offset值变更,其余内容保持不变,预期格式如下:
enqueue_data = { "ENQUEUE": [ { "link_enqueue": "http://link1.com", "offset_in_milliseconds_enqueue": "new numerical value", "title": "title 1" }, { "link_enqueue": "http://link2.com", "offset_in_milliseconds_enqueue": "numerical value", "title": "title 2" } ] }
解决方案
你的代码核心问题在于对enqueue_data的类型判断错误:attr['ENQUEUE']对应的是列表(对应DynamoDB中的L类型),而非字典,所以不能用enqueue_data.values()来遍历,直接遍历列表即可。另外注意DynamoDB中offset_in_milliseconds_enqueue是数字类型(N),如果你的新值是字符串,建议转为整数或保持数字类型,避免类型不匹配。
修改后的代码如下:
def handle(self, handler_input): # 注意:如果DynamoDB中存储的是数字类型,这里用整数更合适 offset_in_milliseconds = 3232 attr = handler_input.attributes_manager.persistent_attributes selected_link = attr['link'] if 'ENQUEUE' in attr: enqueue_list = attr['ENQUEUE'] # 遍历ENQUEUE列表中的每一项 for item in enqueue_list: if item.get('link_enqueue') == selected_link: # 更新offset值,注意类型匹配 item['offset_in_milliseconds_enqueue'] = offset_in_milliseconds # 保存更新 handler_input.attributes_manager.save_persistent_attributes() # 找到匹配项后即可退出循环,避免多余遍历 break return
关键修改点:
- 把
enqueue_data.values()改为直接遍历enqueue_list(因为attr['ENQUEUE']是列表); - 遍历过程中找到匹配项就更新并break,提升效率;
- 调整offset值的类型为数字,和DynamoDB中存储的
N类型对应(如果业务需要字符串类型,可以改回字符串,但建议保持类型一致)。
内容的提问来源于stack exchange,提问作者calengineer
相关产品推荐
相关产品推荐

