You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB C# Driver中SetOnInsert误区:如何仅插入时设置Guid型_id

解决MongoDB FindOneAndUpdate仅在插入时设置_id的问题

问题根源

你遇到的问题主要来自两个点:一是字符串形式的filter存在语法错误,导致每次都匹配不到已有文档,触发upsert生成新_id;二是实体类的_id字段可能配置了自动生成规则,覆盖了你SetOnInsert的赋值。

修正方案

1. 正确定义实体类

确保_id字段不配置自动生成规则,让代码手动控制赋值:

public class TestClass
{
    [BsonId]
    public Guid Id { get; set; }
    public string Path { get; set; }
    public string Name { get; set; }
}

2. 使用强类型Filter避免语法错误

放弃字符串形式的filter,改用强类型构建器,确保匹配逻辑准确:

// 序列化配置保持不变
BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
BsonSerializer.RegisterSerializer<Guid>(new GuidSerializer(GuidRepresentation.Standard));

// 强类型构建filter,精准匹配Path字段
FilterDefinition<TestClass> filter = Builders<TestClass>.Filter.Eq(t => t.Path, "a.b.c.d");

var updateBuilder = Builders<TestClass>.Update;
var update = updateBuilder
    .SetOnInsert(t => t.Id, Guid.NewGuid()) // 仅在插入新文档时设置_id
    .Set(t => t.Path, "a.b.c.d") // 插入/更新都设置Path
    .Set(t => t.Name, "c.d"); // 插入/更新都设置Name

var options = new FindOneAndUpdateOptions<TestClass>
{
    IsUpsert = true,
    ReturnDocument = ReturnDocument.After
};

var result = collNamespace.FindOneAndUpdate<TestClass>(filter, update, options);

3. 可选:给Path字段加唯一索引

为了避免重复创建相同Path的文档,同时提升查询匹配效率,给Path字段添加唯一索引:

collNamespace.Indexes.CreateOne(new CreateIndexModel<TestClass>(
    Builders<TestClass>.IndexKeys.Ascending(t => t.Path),
    new CreateIndexOptions { Unique = true }
));

关键说明

  • SetOnInsert确实只会在upsert触发插入操作时生效,更新已有文档时不会修改_id;
  • 之前的字符串filter存在引号嵌套错误("{ Path: "a.b.c.d" }"),导致MongoDB无法正确解析匹配条件,每次都执行插入;
  • 实体类的_id如果配置了GuidGenerator这类自动生成器,会覆盖SetOnInsert的赋值,所以必须去掉自动生成配置。

内容的提问来源于stack exchange,提问作者GreenEyedAndy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 16:05:18