Cosmos Db:使用补丁在不存在的父项中添加项目
Cosmos Db : Add Item in non existent parent using Patch
技术:Cosmos DB 模拟器,Microsoft.Azure.Cosmos 3.23.0
目标:使用 Path Add 添加数组的第一项
初始数据:
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA"
}
请求的最终数据:
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA",
"Products" : [{"Id" : "P-1", "Description" : "My Product"}]
}
我的代码:
PatchOperation operation = PatchOperation.Add("/Products/-", command);
TransactionalBatch batch = container.CreateTransactionalBatch(new PartitionKey(project_Id))
.PatchItem(project_Id, new[] { operation },
new TransactionalBatchPatchItemRequestOptions
{
EnableContentResponseOnWrite = false,
IndexingDirective = IndexingDirective.Exclude
});
TransactionalBatchResponse batchResponse = await batch.ExecuteAsync();
我收到 BadRequest 错误。
我试试 :
"/Products/" => 将项目作为对象而不是数组的项目插入
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA",
"Products" : {"Id" : "P-1", "Description" : "My Product"}
}
"/Products/0/" => BadRequest
"/Products/0" => BadRequest
"/Products/-" => BadRequest
"/Products/-/" => BadRequest
"/Products//" => BadRequest
根据文档:https://docs.microsoft.com/en-us/azure/cosmos-db/partial-document-update
Add Add performs one of the following, depending on the target path:
If the target path specifies an element that does not exist, it is
added. If the target path specifies an element that already exists,
its value is replaced. If the target path is a valid array index, a
new element will be inserted into the array at the specified index. It
shifts existing elements to the right. If the index specified
is equal to the length of the array, it will append an element to the
array. Instead of specifying an index, you can also use the -
character. It will also result in the element being appended to the
array.
Note: Specifying an index greater than the array length will result in
an error.
是否存在 Cosmos Db 模拟器限制?
我的代码有什么问题?
编辑 1:
更多信息:
如果初始数据是:
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA",
"Products" : []
}
PatchOperation.Add("/产品/-", 命令); => 工作
但在我的例子中,Products 数组以前不存在(数据模型迁移)
最后我认为不可能自动执行我想要的操作。
来自未使用事务时的异常消息:
BadRequest (400); Substatus: 0; ActivityId:
c12f915a-3c4a-4d76-bd7d-ad519bbb8f02; Reason: (Message:
{"Errors":["For Operation(1): Add Operation can only create a child
object of an existing node(array or object) and cannot create path
recursively, no path found beyond: 'Products'.
所以我设法自己做了,它不是真正的切肉刀,但它是工作的。
try
{
PatchOperation operationAdd = PatchOperation.Add("/Products/-", command);
var patchAddResponse = await container.PatchItemAsync<ProjectResponse>(project_Id, new PartitionKey(project_Id), new[] { operationAdd },
new PatchItemRequestOptions
{
FilterPredicate = $"from c where IS_DEFINED(c.Products) AND c.id = '{project_Id}'",
EnableContentResponseOnWrite = false,
IndexingDirective = IndexingDirective.Exclude
});
this.log.LogInformation($"ru : {patchAddResponse.RequestCharge} - AddProductAsync " + command.Id);
return patchAddResponse.Resource;
}
catch (CosmosException ex)
{
if (ex.StatusCode == System.Net.HttpStatusCode.PreconditionFailed)
{
PatchOperation operationCreate = PatchOperation.Add("/Products", new IProduct[] { command });
var patchCreateResponse = await container.PatchItemAsync<ProjectResponse>(project_Id, new PartitionKey(project_Id), new[] { operationCreate },
new PatchItemRequestOptions
{
EnableContentResponseOnWrite = false,
IndexingDirective = IndexingDirective.Exclude
});
this.log.LogInformation($"ru : {patchCreateResponse.RequestCharge} - AddProductAsync " + command.Id);
return patchCreateResponse.Resource;
}
else
throw ex;
}
先决条件使用 1 RU,因此可以接受
技术:Cosmos DB 模拟器,Microsoft.Azure.Cosmos 3.23.0
目标:使用 Path Add 添加数组的第一项
初始数据:
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA"
}
请求的最终数据:
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA",
"Products" : [{"Id" : "P-1", "Description" : "My Product"}]
}
我的代码:
PatchOperation operation = PatchOperation.Add("/Products/-", command);
TransactionalBatch batch = container.CreateTransactionalBatch(new PartitionKey(project_Id))
.PatchItem(project_Id, new[] { operation },
new TransactionalBatchPatchItemRequestOptions
{
EnableContentResponseOnWrite = false,
IndexingDirective = IndexingDirective.Exclude
});
TransactionalBatchResponse batchResponse = await batch.ExecuteAsync();
我收到 BadRequest 错误。
我试试 :
"/Products/" => 将项目作为对象而不是数组的项目插入
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA",
"Products" : {"Id" : "P-1", "Description" : "My Product"}
}
"/Products/0/" => BadRequest
"/Products/0" => BadRequest
"/Products/-" => BadRequest
"/Products/-/" => BadRequest
"/Products//" => BadRequest
根据文档:https://docs.microsoft.com/en-us/azure/cosmos-db/partial-document-update
Add Add performs one of the following, depending on the target path: If the target path specifies an element that does not exist, it is added. If the target path specifies an element that already exists, its value is replaced. If the target path is a valid array index, a new element will be inserted into the array at the specified index. It shifts existing elements to the right. If the index specified is equal to the length of the array, it will append an element to the array. Instead of specifying an index, you can also use the - character. It will also result in the element being appended to the array.
Note: Specifying an index greater than the array length will result in an error.
是否存在 Cosmos Db 模拟器限制? 我的代码有什么问题?
编辑 1:
更多信息: 如果初始数据是:
{
"id": "P1-86",
"ProjectType_Id": "1",
"Description": "AAA",
"Products" : []
}
PatchOperation.Add("/产品/-", 命令); => 工作
但在我的例子中,Products 数组以前不存在(数据模型迁移)
最后我认为不可能自动执行我想要的操作。
来自未使用事务时的异常消息:
BadRequest (400); Substatus: 0; ActivityId: c12f915a-3c4a-4d76-bd7d-ad519bbb8f02; Reason: (Message: {"Errors":["For Operation(1): Add Operation can only create a child object of an existing node(array or object) and cannot create path recursively, no path found beyond: 'Products'.
所以我设法自己做了,它不是真正的切肉刀,但它是工作的。
try
{
PatchOperation operationAdd = PatchOperation.Add("/Products/-", command);
var patchAddResponse = await container.PatchItemAsync<ProjectResponse>(project_Id, new PartitionKey(project_Id), new[] { operationAdd },
new PatchItemRequestOptions
{
FilterPredicate = $"from c where IS_DEFINED(c.Products) AND c.id = '{project_Id}'",
EnableContentResponseOnWrite = false,
IndexingDirective = IndexingDirective.Exclude
});
this.log.LogInformation($"ru : {patchAddResponse.RequestCharge} - AddProductAsync " + command.Id);
return patchAddResponse.Resource;
}
catch (CosmosException ex)
{
if (ex.StatusCode == System.Net.HttpStatusCode.PreconditionFailed)
{
PatchOperation operationCreate = PatchOperation.Add("/Products", new IProduct[] { command });
var patchCreateResponse = await container.PatchItemAsync<ProjectResponse>(project_Id, new PartitionKey(project_Id), new[] { operationCreate },
new PatchItemRequestOptions
{
EnableContentResponseOnWrite = false,
IndexingDirective = IndexingDirective.Exclude
});
this.log.LogInformation($"ru : {patchCreateResponse.RequestCharge} - AddProductAsync " + command.Id);
return patchCreateResponse.Resource;
}
else
throw ex;
}
先决条件使用 1 RU,因此可以接受