我正在使用 C# 驱动程序(来自 NuGet 的 v1.8.3),并且很难确定$addtoSet/upsert
操作是否实际上将新项目添加到给定数组中,或者该项目是否已经存在。
添加新项目可能分为两种情况,要么文档根本不存在并且只是由 upsert 创建,要么文档存在但数组不存在或不包含给定项目。
我需要这样做的原因是,我有大量数据要加载到 MongoDB 中,这些数据可能(不应该,但可能)在处理过程中中断。如果发生这种情况,我需要能够从头开始备份,而无需进行重复的下游处理(保持处理幂等)。在我的流程中,如果确定一个项目是新添加的,我将对该给定项目的下游处理排队,如果确定已经在文档中添加,则不需要更多的下游工作。我的问题是结果总是返回说调用修改了一个文档,即使该项目已经存在于数组中并且实际上没有任何修改。
根据我对 C# 驱动程序 api 的理解,我应该能够使用 进行调用WriteConcern.Acknowledged
,然后检查WriteConcernResult.DocumentsAffected
它是否确实更新了文档。
我的问题是,在所有情况下,写关注结果都返回了 1 个文档已更新。:/
这是我的代码正在调用的示例文档$addToSet
,它可能会或可能不会在“项目”列表中包含此特定项目以开始:
{
"_id" : "some-id-that-we-know-wont-change",
"items" : [
{
"s" : 4,
"i" : "some-value-we-know-is-static",
}
]
}
我的查询始终使用_id
基于处理元数据已知的值:
var query = new QueryDocument
{
{"_id", "some-id-that-we-know-wont-change"}
};
我的更新如下:
var result = mongoCollection.Update(query, new UpdateDocument()
{
{
"$addToSet", new BsonDocument()
{
{ "items", new BsonDocument()
{
{ "s", 4 },
{ "i", "some-value-we-know-is-static" }
}
}
}
}
}, new MongoUpdateOptions() { Flags = UpdateFlags.Upsert, WriteConcern = WriteConcern.Acknowledged });
if(result.DocumentsAffected > 0 || result.UpdatedExisting)
{
//DO SOME POST PROCESSING WORK THAT SHOULD ONLY HAPPEN ONCE PER ITEM
}
如果我在一个空集合上运行此代码一次,则会添加文档并且响应符合预期(DocumentsAffected = 1
,UpdatedExisting = false
)。如果我再次运行它(任意次数),文档似乎没有更新,因为它保持不变,但结果现在出乎意料(DocumentsAffected = 1
, UpdatedExisting = true
)。
DocumentsAffected = 0
如果文档未更改,这不应该返回吗?
由于我们每天需要进行数百万次这样的调用,我很犹豫是否将此逻辑转换为每个项目的多个调用(首先检查项目是否存在于给定的文档数组中,然后添加/排队或只是跳过)如果在一切皆有可能。
有没有办法让这个工作在一个单一的电话?