【发布时间】:2020-09-01 04:12:56
【问题描述】:
亲爱的 Cosmos 会员,
我正在使用 CosmosTrigger 创建 Azure Function (Python):
- 从 source_collection 读取数据
- 将数据写入 target_collection(仅当文档不存在时)
为了实现“如果不存在则插入”功能,我使用唯一键“名称”配置了 target_collection。
例子:
- 写入 target_collection
{"name": "John", "id": "1"}=> 好的 - 写入 target_collection
[{"name": "John", "id": "2"}, {"name": "Mary", "id": "3"}]=> System.Private.CoreLib:执行函数时出现异常:Functions.CosmosTrigger。 Microsoft.Azure.DocumentDB.Core:系统中已存在具有指定 ID 的实体。
唯一键“name”:target_collection 中已存在“John”。所以 outdocs:func.Out[func.Document],outdocs.set() 返回冲突 409 并且“Mary”永远不会被写入 target_collection。
重要提示:当我将带有项目数组的 json 从数据资源管理器上传到 target_collection 时,所有冲突都会返回错误,但所有项目都会得到处理。 当我尝试从 Azure 函数编写它时,第一次冲突会引发错误,并且剩余的项目永远不会进入 target_collection。
我的问题:
- 有没有办法忽略引发的错误并使用 func.Out[func.Document].set() 处理整个项目数组?
- 或者,您能否告诉我在 Cosmos 中实现批量“如果不存在则插入”行为的最佳方法是什么?
def main(docs: func.DocumentList, outdocs: func.Out[func.Document]) -> str:
compl_docs = func.DocumentList()
compl_docs_dict = {
"name": "John",
"id": "2"
}
compl_docs.append(func.Document.from_dict(compl_docs_dict))
compl_docs_dict = {
"name": "Mary",
"id": "3"
}
compl_docs.append(func.Document.from_dict(compl_docs_dict))
outdocs.set(compl_docs)
【问题讨论】:
-
你能分享一下你是如何写的代码吗? Cosmos DB 中的“如果不存在则插入”是 Upsert。问题是这不能解决你的问题。您的问题不是因为文档已经存在而创建失败,而是因为违反唯一键约束(因为
name)而失败。在您的情况下,带有id2 的文档与带有id1 的文档是不同的文档,但它们具有相同的name,这违反了唯一密钥策略。 -
也许我会改写 - 我想实现“如果文档存在则不插入”。我计划使用唯一键约束来自动处理重复项,但它会在上面抛出错误。我想在一个函数运行中发送 ["John", "Mary"]。如果集合中已经有“John”,则只写入“Mary”。目前我在“John”唯一键违规后出现错误,“Mary”从未得到处理。
-
Cosmos DB 输出绑定使用 Upsert,遗憾的是没有选项可以更改该行为。您唯一的选择似乎是独立维护 SDK 客户端(不使用输出绑定)。这样您就可以发出 Create(而不是 Upsert)并处理冲突(项目已经存在)。
标签: python azure-functions azure-cosmosdb bulkinsert conflict