1. 环境准备与基础认知

在超市购物需要先准备购物袋,操作数据库也需要先搭建环境。我们选择MongoDB.Driver 2.18.0作为技术栈,这是目前(截至2023年)最稳定的官方驱动版本。

通过NuGet安装:

Install-Package MongoDB.Driver -Version 2.18.0

基础概念速览:

  • BsonDocument:MongoDB的JSON-like数据格式
  • IMongoCollection:相当于关系型数据库中的表
  • InsertOne/InsertMany:原子性写入方法

2. 数据库连接的三种姿势

2.1 基础连接模式

var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("SchoolDB");
var collection = database.GetCollection<BsonDocument>("Students");

// 等效于在Mongo Shell执行:
// use SchoolDB
// db.Students.insertOne({...})

2.2 带身份验证的连接

var settings = new MongoClientSettings {
    Server = new MongoServerAddress("localhost", 27017),
    Credential = MongoCredential.CreateCredential(
        "admin", 
        "root", 
        "securePassword123")
};
var client = new MongoClient(settings);

2.3 云数据库连接

var connectionString = "mongodb+srv://<username>:<password>@cluster0.abcd.mongodb.net/?retryWrites=true&w=majority";
var client = new MongoClient(connectionString);

3. 文档插入的四种实战模式

3.1 基础插入(BsonDocument)

var document = new BsonDocument {
    { "name", "张三" },
    { "age", 18 },
    { "courses", new BsonArray { "数学", "物理" } },
    { "registration_date", DateTime.Now }
};

collection.InsertOne(document);
Console.WriteLine($"插入文档ID:{document["_id"]}");

/* 生成的MongoDB文档:
{
    "_id": ObjectId("..."),
    "name": "张三",
    "age": 18,
    "courses": ["数学", "物理"],
    "registration_date": ISODate("2023-08-20T08:30:00Z")
}
*/

3.2 强类型插入(POCO)

定义数据模型类:

public class Student
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }
    
    [BsonElement("full_name")]
    public string Name { get; set; }
    
    [BsonElement("age")]
    public int Age { get; set; }
    
    [BsonIgnore]
    public string TemporaryNote { get; set; }
}

插入操作:

var student = new Student {
    Name = "李四",
    Age = 20,
    TemporaryNote = "需要补交材料"
};

var typedCollection = database.GetCollection<Student>("Students");
typedCollection.InsertOne(student);
Console.WriteLine($"生成的学生ID:{student.Id}");

3.3 批量插入优化

var batch = new List<BsonDocument>();
for (int i = 0; i < 1000; i++) {
    batch.Add(new BsonDocument {
        { "index", i },
        { "timestamp", DateTime.Now.AddSeconds(i) }
    });
}

var options = new BulkWriteOptions { IsOrdered = false };
collection.BulkWrite(batch.Select(d => new InsertOneModel<BsonDocument>(d)), options);

// 比InsertMany快3-5倍,特别适合日志类数据写入

3.4 异步插入实践

async Task InsertWithRetryAsync()
{
    var document = new BsonDocument { ["data"] = "重要数据" };
    
    try {
        await collection.InsertOneAsync(document);
    }
    catch (MongoWriteException ex) when (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) {
        // 处理主键冲突
        Console.WriteLine("检测到重复插入");
    }
    catch (TimeoutException) {
        // 处理超时重试
        await collection.InsertOneAsync(document);
    }
}

4. 关联技术深度解析

4.1 事务处理

using (var session = client.StartSession())
{
    session.StartTransaction();

    try {
        collection.InsertOne(session, new BsonDocument { ["type"] = "订单" });
        database.GetCollection<BsonDocument>("Inventory").UpdateOne(
            session,
            Builders<BsonDocument>.Filter.Eq("product_id", 123),
            Builders<BsonDocument>.Update.Inc("stock", -1));
        
        session.CommitTransaction();
    }
    catch {
        session.AbortTransaction();
        throw;
    }
}

4.2 插入性能调优

var settings = new MongoClientSettings {
    WriteConcern = WriteConcern.W1, // 只需主节点确认
    WriteEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false),
    ServerSelectionTimeout = TimeSpan.FromSeconds(5)
};

// 适合日志场景的配置组合:
// WriteConcern.Unacknowledged + 禁用Journaling
// 最高可提升10倍写入速度

5. 应用场景全景图

  1. 实时日志系统:配合BulkWrite实现每秒万级写入
  2. 物联网数据采集:灵活Schema适应异构设备
  3. 用户行为分析:动态字段存储点击流数据
  4. 内容管理系统:嵌套文档存储文章版本历史

6. 技术优缺点分析

优势矩阵

  • 无模式设计适合快速迭代
  • 原子性操作保证数据一致性
  • 横向扩展能力优秀

局限所在

  • 事务支持在分片集群中存在限制
  • 不适合强关系型数据场景
  • 内存消耗高于传统SQL数据库

7. 注意事项备忘录

  1. 连接池管理:默认维持100个连接,通过MaxConnectionPoolSize调整
  2. 文档大小限制:单个文档不超过16MB
  3. 索引策略:在插入前建立必要索引
  4. 写关注级别:根据业务需求选择w=0或w=1
  5. 异常处理:重点监控以下错误代码:
    • 11000:主键冲突
    • 16500:查询超时
    • 89:网络中断

8. 最佳实践总结

经过多个生产项目的验证,我们总结出以下黄金法则:

  1. 批量操作优先使用BulkWrite
  2. 重要数据必须设置WriteConcern
  3. 定期检查孤儿文档(通过TTL索引)
  4. 监控慢查询日志(profileLevel=1)
  5. 使用变更流(Change Stream)实现事件溯源