尝试在 MongoDB 中更新记录时重复键 _id
Duplicate key _id when trying to Upsert a record in MongoDB
我正在尝试使用 MongoDB 驱动程序 1.9.2 for .NET 在 C# 中实现 Upsert 方法。
想法是传递一个对象给方法;如果对象已经存在于 MongoDB 中,则更新所有列中的数据;如果不存在,则在 MongoDB 中创建一个新文档。
我的对象有一个名为 id
的成员。如果我的方法接收到一个没有设置 id
的对象,那么将在 MongoDB 中创建一条新记录,正如预期的那样。
但是,如果它确实有一个 id
,例如“2”,它会抛出此异常而不是更新值:
Command 'findAndModify' failed: exception: insertDocument :: caused by
:: 11000 E11000 duplicate key error index:
XXXXXXXX.MyObjectClassName.$id dup key: {: 2 } ...
方法如下所示:
public override void Save(TModel modelObject)
{
MongoServer server = ConnectMongo();
var database = server.GetDatabase(ModelDatabaseName);
// custom method that determines which column is the key column for this type of object, e.g. "id" or "requestID" or "taskID"
var query = BuildQueryByKey(modelObject);
var update = Update<TModel>.Replace(modelObject);
MongoCollection collection = database.GetCollection<TModel>(mWriteCollectionName);
FindAndModifyArgs args = new FindAndModifyArgs()
{
Upsert = true, //update if exists, otherwise insert
Query = query,
Update = update,
VersionReturned = FindAndModifyDocumentVersion.Modified
//Fields =
};
var result = collection.FindAndModify(args);
}
在研究 Whosebug 后,我发现有些人通过将 [BsonIgnoreIfDefault]
属性添加到对象定义中的 id 列来解决问题,但对我来说没有任何改变。
知道我做错了什么吗? FindAndModify 是否有任何示例实现来更新或插入 MongoDB 中的对象?
更新:
我通过手动构建查询而不是使用我的自定义方法让它(部分)工作。所以自定义方法返回一个查询 id=2
,结果我需要的是 _id=2
。
所以现在更新有效,但插入无效。 Mongo 似乎没有自动生成 _id,而是希望我传递下一个 ID,例如如果我已经有 7 行,则为“8”。然后插入成功。它不能自动生成一个自动递增的ID吗?
是的,检查
我看不到 BuildQueryByKey 中发生了什么。但是您确实需要找出您的代码发送给 FindAndUpdate 命令的文档。
只需打印出您的查询并更新变量以查看发生了什么。
编辑:对于自动生成的 _id,只需将其从文档中删除;-) 或者将其设置为 null 并添加 [BsonIgnoreIfDefault] 属性
我正在尝试使用 MongoDB 驱动程序 1.9.2 for .NET 在 C# 中实现 Upsert 方法。
想法是传递一个对象给方法;如果对象已经存在于 MongoDB 中,则更新所有列中的数据;如果不存在,则在 MongoDB 中创建一个新文档。
我的对象有一个名为 id
的成员。如果我的方法接收到一个没有设置 id
的对象,那么将在 MongoDB 中创建一条新记录,正如预期的那样。
但是,如果它确实有一个 id
,例如“2”,它会抛出此异常而不是更新值:
Command 'findAndModify' failed: exception: insertDocument :: caused by :: 11000 E11000 duplicate key error index: XXXXXXXX.MyObjectClassName.$id dup key: {: 2 } ...
方法如下所示:
public override void Save(TModel modelObject)
{
MongoServer server = ConnectMongo();
var database = server.GetDatabase(ModelDatabaseName);
// custom method that determines which column is the key column for this type of object, e.g. "id" or "requestID" or "taskID"
var query = BuildQueryByKey(modelObject);
var update = Update<TModel>.Replace(modelObject);
MongoCollection collection = database.GetCollection<TModel>(mWriteCollectionName);
FindAndModifyArgs args = new FindAndModifyArgs()
{
Upsert = true, //update if exists, otherwise insert
Query = query,
Update = update,
VersionReturned = FindAndModifyDocumentVersion.Modified
//Fields =
};
var result = collection.FindAndModify(args);
}
在研究 Whosebug 后,我发现有些人通过将 [BsonIgnoreIfDefault]
属性添加到对象定义中的 id 列来解决问题,但对我来说没有任何改变。
知道我做错了什么吗? FindAndModify 是否有任何示例实现来更新或插入 MongoDB 中的对象?
更新:
我通过手动构建查询而不是使用我的自定义方法让它(部分)工作。所以自定义方法返回一个查询 id=2
,结果我需要的是 _id=2
。
所以现在更新有效,但插入无效。 Mongo 似乎没有自动生成 _id,而是希望我传递下一个 ID,例如如果我已经有 7 行,则为“8”。然后插入成功。它不能自动生成一个自动递增的ID吗?
是的,检查
我看不到 BuildQueryByKey 中发生了什么。但是您确实需要找出您的代码发送给 FindAndUpdate 命令的文档。
只需打印出您的查询并更新变量以查看发生了什么。
编辑:对于自动生成的 _id,只需将其从文档中删除;-) 或者将其设置为 null 并添加 [BsonIgnoreIfDefault] 属性