說說MongoDB的插入原理

字號:


    在開發(fā)之前,選擇MongoDB驅(qū)動是件很重要的事情。如果選擇不好,在后期的開發(fā)的是件很費力的事情,因為我就遇到這樣的問題。MongoDB驅(qū)動有幾種比較流行驅(qū)動,官方驅(qū)動和samus是兩種使用比較多的。
    好了,接著說今天的內(nèi)容了。
    首先從MongoDB的官方網(wǎng)站上下載CSharp驅(qū)動(https://github.com/mongodb/mongo-csharp-driver/downloads)。我使用的是CSharpDriver-1.1.0.4184,里面還包含一個CSharpDriverDocs.chm的文檔。
    MongoDB插入原理:使用驅(qū)動程序進(jìn)行插入的時候,會將數(shù)據(jù)轉(zhuǎn)換成BSON格式。數(shù)據(jù)庫會解析BSON,并檢驗是否含有“_id”鍵,因為“_id”鍵在插入到數(shù)據(jù)庫時MongoDB會自動生成。而且每次插入文檔不能超過4M。這個應(yīng)該是和MongoDB本身有關(guān)。但是MongoDB1.8版本的支持16M,為什么是這個樣子我到?jīng)]怎么研究。這個想留給有心人幫忙解決下了。
    插入的Shell操作有Insert和Save兩種語法,先看下面的Shell
    > var time = new Date("2011/8/28 21:50:00") //定義一個時間對象
    > var i = {"time":time,"userid":10001,"sessionid":"20110829215100","ip":"192.168.0.1","title":"Login","url":"Login.aspx"} //定義一個文檔對象
    > i //查看 i 文檔
    {
    "time" : ISODate("2011-08-28T13:50:00Z"),
    "userid" : 10001,
    "sessionid" : "20110829215100",
    "ip" : "192.168.0.1",
    "title" : "Login",
    "url" : "Login.aspx"
    }
    > use testDb
    > show collections //查看當(dāng)前集合,把i文檔插入到login集合中
    myc
    myc1
    myc2
    system.indexes
    > db.login.insert(i)
    > db.login.findOne()
    {
    "_id" : ObjectId("4e5b99e62690d28cadd0f58d"), //MongoDb會為每個插入的對象自動生成一個"_id"的值,你可以在插入的時候自己指定這個值,如下面
    "time" : ISODate("2011-08-28T13:50:00Z"),
    "userid" : 10001,
    "sessionid" : "20110829215100",
    "ip" : "192.168.0.1",
    "title" : "Login",
    "url" : "Login.aspx"
    }
    > i = {"_id":"newid_100001","time":time,"userid":10001,"sessionid":"20110829215100","ip":"192.168.0.1","title":"Login","url":"Login.aspx"}
    {
    "_id" : "newid_100001",
    "time" : ISODate("2011-08-28T13:50:00Z"),
    "userid" : 10001,
    "sessionid" : "20110829215100",
    "ip" : "192.168.0.1",
    "title" : "Login",
    "url" : "Login.aspx"
    }
    > db.login.save(i) //這里用save插入文檔到數(shù)據(jù)庫
    > db.login.find() //查詢結(jié)果兩條文檔,第二條文檔"_id"是自定義的值
    { "_id" : ObjectId("4e5b99e62690d28cadd0f58d"), "time" : ISODate("2011-08-28T13:50:00Z"), "userid" : 10001, "sessionid" : "20110829215100",
    "ip" : "192.168.0.1", "title" : "Login", "url" : "Login.aspx" }
    { "_id" : "newid_100001", "time" : ISODate("2011-08-28T13:50:00Z"), "userid" : 10001, "sessionid" : "20110829215100", "ip" : "192.168.0.1",
    "title" : "Login", "url" : "Login.aspx" }
    注意:
    1:Insert和Save的區(qū)別是:如果插入的集合的“_id”值,在集合中已經(jīng)存在,用Insert執(zhí)行插入操作回報異常,已經(jīng)存在"_id"的鍵。用Save如果系統(tǒng)中沒有相同的"_id"就執(zhí)行插入操作,有的話就執(zhí)行覆蓋掉原來的值。相當(dāng)于修改操作。我這里就不做演示了。
    下面說下用C#驅(qū)動 添加文檔。
    2:在新建一個集合或者一個數(shù)據(jù)庫時,MongoDb不會在馬上生成。而是在你添加了第一個數(shù)據(jù)后才會有顯示。這個特性很多的數(shù)據(jù)庫都用,比如說SQLite。
    下面說下用 C#驅(qū)動 添加文檔
    #region Version Info
    /* ========================================================================
    * 【說明描述】
    *
    * 作者:yoolo 時間:2011/8/29 21:15:38
    * 文件名:NoSpiderAuto.LoginDemo
    * 版本:V1.0.1
    *
    * 修改者: 時間:
    * 修改說明:
    * ========================================================================
    */
    #endregion
    namespace NoSpiderAuto
    {
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using MongoDB.Driver;
    using MongoDB.Bson;
    internal class LoginDemo
    {
    MongoDatabase db;
    MongoCollection coll;
    public LoginDemo()
    {
    MongoServerSettings set = new MongoServerSettings()
    {
    Server = new MongoServerAddress("127.0.0.1")
    };
    MongoServer server = new MongoServer(set);
    db = server.GetDatabase("testDb");
    coll = db.GetCollection("login");
    }
    /// <summary>
    /// 單個對象插入
    /// </summary>
    public void InsertLogin()
    {
    var Time = DateTime.Now.ToUniversalTime();
    //實例一 添加匿名對象
    var login = new { _id = "newid_100002", time = Time, userid = 10002, sessionid = "20110829215102", ip = "192.168.0.2", title = "注冊", url = "Register.aspx" };
    coll.Insert(login);//插入成功
    //添加一個BsonDocument對象
    BsonDocument doc = new BsonDocument();
    doc.Add("_id", BsonValue.Create("newid_100003"));
    doc.Add("time", BsonValue.Create(Time));
    doc.Add("userid", BsonValue.Create(10003));
    doc.Add("sessionid", BsonValue.Create("20110829215103"));
    doc.Add("ip", BsonValue.Create("192.168.0.3"));
    doc.Add("title", BsonValue.Create("注冊"));
    doc.Add("url", BsonValue.Create("Register.aspx"));
    coll.Insert(doc);//插入成功
    //添加一個對象
    Login man = new Login();
    man._id = "newid_100004";
    man.time = Time;
    man.userid = 10004;
    man.sessionid = "20110829215104";
    man.ip = "192.168.0.4";
    man.title = "注冊";
    man.url = "Register.aspx";
    coll.Insert(man);//插入成功
    }
    /// <summary>
    /// 批量插入
    /// </summary>
    public void InsertBatchLogin()
    {
    var Time = DateTime.Now.ToUniversalTime();
    List<Login> logins = new List<Login>();
    for (int i = 0; i < 100; i++)
    {
    Login man = new Login();
    man._id = "newid_100001" + i.ToString();//_id在批量插入的時候不能重復(fù),如果有一個重復(fù)全部集合無法插入到集合
    man.time = Time;
    man.userid = 10004 + i;
    man.sessionid = "20110829215104";
    man.ip = "192.168.0.4";
    man.title = "注冊";
    man.url = "Register.aspx";
    logins.Add(man);
    }
    coll.InsertBatch(typeof(Login), logins); //插入成功
    }
    }
    public class Login
    {
    public string _id { get; set; }
    public DateTime time { get; set; }
    public int userid { get; set; }
    public string sessionid { get; set; }
    public string ip { get; set; }
    public string title { get; set; }
    public string url { get; set; }
    }
    }
    如果要插入多個文檔,使用批量插入會快一些。一次批量插入只是單個Tcp請求,也就是避免了多個請求帶來的開銷!