删除时未找到 Cosmos DB 实体但存在并且能够获取
Cosmos DB entity not found on delete but exists and able to get
每当我尝试使用它的 ID 删除一个项目时,我都会收到一个实体未找到的错误,但该项目存在于数据库中,我也可以使用 SQL 格式检索它。
我不明白我在代码中哪里错了,但是每当我检索带有它的 ID 的项目时,我都能找到它,每当我尝试删除它时,它都会失败。
这是我要获取的代码:
async getAsset(assetId: string): Promise<Asset> {
const assetsDb = await getDbClient(cosmoDBContainers.assets);
const response = await assetsDb.items
.query<Asset>({
query: `SELECT * FROM ${cosmoDBContainers.assets} A
WHERE A.id = @id`,
parameters: [{ name: "@id", value: assetId }],
}).fetchAll();
return response.resources.map(x => new Asset(
x.id,
x.orgId,
x.assetType,
x.title,
x.createdAt,
x.lastUpdate,
x.fileStorageId,
))[0];
} // item successfully retrieved
这是要删除的代码(注意我正在调用 getAsset 函数):
async removeAsset(assetId: string): Promise<void> {
const assetsDb = await getDbClient(cosmoDBContainers.assets);
const asset = await this.getAsset(assetId); // calling this in order to check that the Ids are the same, which they are
const item = assetsDb.item(asset.Id); // this line seems to work
await item.delete(); // error is thrown here
}
CosmosDB 中的分区键是“/id”,我尝试在调用 assetsDb.item(asset.Id, "/id")
时添加它,但我仍然遇到相同的未找到错误。
这是完整的错误
Error: Entity with the specified id does not exist in the system.
我已经从 SO 中的其他答案中尝试了一些方法,但似乎没有任何效果,我怀疑这可能是我这边的问题,但此时我完全迷失了,任何想法都很棒有帮助。
我正在使用 TypeScript 并且 "@azure/cosmos": "^3.11.0"
谢谢。
请更改以下代码行:
const item = assetsDb.item(asset.Id);
await item.delete();
至
const item = assetsDb.item(asset.Id, asset.Id);//assuming your partition key value is same as document id.
await item.delete();
并且您的删除操作应该有效。
本质上有两个问题:
- 在下面的代码
const item = assetsDb.item(asset.Id);
中,您没有指定文档的分区键值。在这种情况下,SDK 使用默认分区键值。由于该默认分区中没有具有匹配 ID 的文档,您会收到找不到项目的错误。
- 当您尝试此代码时
assetsDb.item(asset.Id, "/id")
,您实际上需要指定分区键值而不是分区键属性名称。由于您为分区键值指定了“/id”,因此 Cosmos DB 在“/id”逻辑分区中查找具有匹配 id 的项目。同样,由于没有找到有效的组合,您得到了错误。
通过使用 const item = assetsDb.item(asset.Id, asset.Id);
,您将项目的 ID 及其分区键值告知 Azure Cosmos DB。
每当我尝试使用它的 ID 删除一个项目时,我都会收到一个实体未找到的错误,但该项目存在于数据库中,我也可以使用 SQL 格式检索它。
我不明白我在代码中哪里错了,但是每当我检索带有它的 ID 的项目时,我都能找到它,每当我尝试删除它时,它都会失败。
这是我要获取的代码:
async getAsset(assetId: string): Promise<Asset> {
const assetsDb = await getDbClient(cosmoDBContainers.assets);
const response = await assetsDb.items
.query<Asset>({
query: `SELECT * FROM ${cosmoDBContainers.assets} A
WHERE A.id = @id`,
parameters: [{ name: "@id", value: assetId }],
}).fetchAll();
return response.resources.map(x => new Asset(
x.id,
x.orgId,
x.assetType,
x.title,
x.createdAt,
x.lastUpdate,
x.fileStorageId,
))[0];
} // item successfully retrieved
这是要删除的代码(注意我正在调用 getAsset 函数):
async removeAsset(assetId: string): Promise<void> {
const assetsDb = await getDbClient(cosmoDBContainers.assets);
const asset = await this.getAsset(assetId); // calling this in order to check that the Ids are the same, which they are
const item = assetsDb.item(asset.Id); // this line seems to work
await item.delete(); // error is thrown here
}
CosmosDB 中的分区键是“/id”,我尝试在调用 assetsDb.item(asset.Id, "/id")
时添加它,但我仍然遇到相同的未找到错误。
这是完整的错误
Error: Entity with the specified id does not exist in the system.
我已经从 SO 中的其他答案中尝试了一些方法,但似乎没有任何效果,我怀疑这可能是我这边的问题,但此时我完全迷失了,任何想法都很棒有帮助。
我正在使用 TypeScript 并且 "@azure/cosmos": "^3.11.0"
谢谢。
请更改以下代码行:
const item = assetsDb.item(asset.Id);
await item.delete();
至
const item = assetsDb.item(asset.Id, asset.Id);//assuming your partition key value is same as document id.
await item.delete();
并且您的删除操作应该有效。
本质上有两个问题:
- 在下面的代码
const item = assetsDb.item(asset.Id);
中,您没有指定文档的分区键值。在这种情况下,SDK 使用默认分区键值。由于该默认分区中没有具有匹配 ID 的文档,您会收到找不到项目的错误。 - 当您尝试此代码时
assetsDb.item(asset.Id, "/id")
,您实际上需要指定分区键值而不是分区键属性名称。由于您为分区键值指定了“/id”,因此 Cosmos DB 在“/id”逻辑分区中查找具有匹配 id 的项目。同样,由于没有找到有效的组合,您得到了错误。
通过使用 const item = assetsDb.item(asset.Id, asset.Id);
,您将项目的 ID 及其分区键值告知 Azure Cosmos DB。