Amazon dynamodb 当映射不存在时,如何设置DynamoDB映射属性值';还不存在
如何将属性“向上插入”到DynamoDB行。例如,Amazon dynamodb 当映射不存在时,如何设置DynamoDB映射属性值';还不存在,amazon-dynamodb,Amazon Dynamodb,如何将属性“向上插入”到DynamoDB行。例如,SET address.state=“MA”对于某些项目,当address还不存在时 我觉得我遇到了鸡和蛋的问题,因为DynamoDB不允许您预先定义一个草率的模式 如果地址已经存在于该项目上,类型为M(用于地图),互联网告诉我可以发布更新表达式,如: SET#address.#state=:value 分别将#地址、#状态和:值适当映射到地址、状态和MA 但是如果address属性不已存在,则会出现错误: ''' ValidationExcep
SET address.state=“MA”
对于某些项目,当address
还不存在时
我觉得我遇到了鸡和蛋的问题,因为DynamoDB不允许您预先定义一个草率的模式
如果地址
已经存在于该项目上,类型为M
(用于地图),互联网告诉我可以发布更新表达式,如:
SET#address.#state=:value
分别将#地址
、#状态
和:值
适当映射到地址
、状态
和MA
但是如果address
属性不已存在,则会出现错误:
'''
ValidationException:更新表达式中提供的文档路径对于更新无效
'''
所以。。看来我要么需要:
address.state
(例如,SET address={};SET address.state='MA'
在单个命令中)SET address={}代码>失败,然后重试
啊。。我喜欢Dynamo,但除非我遗漏了一些明显的东西,否则这有点疯狂。如果父文档不存在,则无法设置嵌套属性。由于
地址
不存在,因此无法在其内部设置属性省
。如果在创建项目时将address
设置为空映射,则可以实现目标。然后,您可以使用以下参数对尚未存在的属性address.province
进行条件更新
var params = {
TableName: 'Image',
Key: {
Id: 'dynamodb.png'
},
UpdateExpression: 'SET address.province = :ma',
ConditionExpression: 'attribute_not_exists(address.province)',
ExpressionAttributeValues: {
':ma': 'MA'
},
ReturnValues: 'ALL_NEW'
};
docClient.update(params, function(err, data) {
if (err) ppJson(err); // an error occurred
else ppJson(data); // successful response
});
顺便说一句,我不得不用省替换州,因为州是一个保留字。您可以通过两次往返来完成,第一次有条件地为
地址设置一个空映射,如果它不存在,第二次设置州:
db.update({
UpdateExpression: 'SET #a = :value',
ConditionExpression: 'attribute_not_exists(#a)',
ExpressionAttributeValues: {
":value": {},
},
ExpressionAttributeNames: {
'#a': 'address'
}
}, ...);
然后:
另一种完全不同的方法是,首先创建父文档时,只需创建地址
节点。例如,假设您的哈希键为id
,您可以执行以下操作:
db.put({
Item: {
id: 42,
address: {}
}
}, ...);
这将允许您简单地设置地址。将值声明为地址
映射已经存在:
db.update({
UpdateExpression: 'SET #a.#b = :v',
AttributeExpressionNames: {
'#a': 'address',
'#b': 'state'
},
AttributeExpressionValues: {
':v': 'whatever'
}
}, ...);
一些kotlin代码可以递归地执行此操作,而不管它有多深。它将父路径的存在设置为条件,如果条件检查失败,则首先递归创建这些路径。它必须在库的包中,这样它才能访问那些包私有字段/类
package com.amazonaws.services.dynamodbv2.xspec
导入com.amazonaws.services.dynamodbv2.document.Table
导入com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException
导入com.amazonaws.services.dynamodbv2.xspec.ExpressionSpecBuilder.attribute_存在
fun Table.UpdateItemByPath(hashKeyName:String,hashKeyValue:Any,updateActions:List){
val parentpath=updateActions.map{it.pathOperand.path.parent()}
.filter{it.isNotEmpty()}
.toSet()//删除重复项的步骤
试一试{
val builder=ExpressionSpecBuilder()
updateActions.forEach{builder.addUpdate(it)}
if(parentpath.isNotEmpty()){
变量条件:条件=比较条件(“=”,文字操作数(真),文字操作数(真))
parentpath.forEach{condition=condition.and(attribute_exists(it))}
建造商。withCondition(条件)
}
this.updateItem(hashKeyName、hashKeyValue、builder.buildForUpdate())
}捕获(e:ConditionalCheckFailedException){
this.updateItemByPath(hashKeyName、hashKeyValue、parentPaths.map{M(it).set(mapOf())})
this.updateItemByPath(hashKeyName、hashKeyValue、updateActions)
}
}
private fun String.parent()=此.substringBeforeLast('.','')
这是我在Typescript中编写的一个助手函数,它使用递归方法实现单级嵌套
我将顶级属性称为列
//usage
await setKeyInColumn('customerA', 'address', 'state', "MA")
//更新映射值以保存新的键值对。如果它不存在,它将创建一个顶级地址。
静态异步setKeyInColumn(primaryKeyValue:string,colName:string,key:string,value:any,_doNotCreateColumn?:布尔){
常量obj={};
obj[key]=value;//创建类似{address:value}的嵌套值
//某些条件取决于列是否已存在
const ConditionExpression=\u doNotCreateColumn?未定义:`attribute\u not\u exists(${colName})`
const AttributeValue=_doNotCreateColumn?值:obj;
const UpdateExpression=\u doNotCreateColumn?`SET${colName}.${key}=:keyval`:`SET${colName}=:keyval`;
试一试{
常数更新图={
TableName:TABLE_NAME,
键:{Key:primaryKeyValue},
UpdateExpression,
表达式属性值:{
“:keyval”:属性值
},
条件表达式,
ReturnValues:“全新”,
}
const resp=wait docClient.update(updateParams.promise())
if(resp&&resp[colName]){
返回resp[colName];
}
}捕获(ex){
//如果该列已存在,请重新运行并不要创建它
如果(例如,代码=='ConditionalCheckFailedException'){
返回此.setKeyInColumn(primaryKeyValue、colName、key、value、true)
}
console.log(“未能更新DynamoDB中的列”)
控制台日志(ex);
返回未定义
}
}
您使用的是哪种语言sdk?您解决过这个问题吗?您可以绕过reserv
//usage
await setKeyInColumn('customerA', 'address', 'state', "MA")