1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        NoSQL | MongoDB入門實(shí)戰(zhàn)教程(7)

        共 3397字,需瀏覽 7分鐘

         ·

        2021-07-19 12:12

        【NoSQL| 總結(jié)/Edison Zhou

        前面我們學(xué)習(xí)了聚合查詢,本篇我們來(lái)看看在模型設(shè)計(jì)中如何應(yīng)用引用模式來(lái)提高查詢效率。

        1內(nèi)嵌模式

        在進(jìn)行MongoDB的模型設(shè)計(jì)中,基于JSON文檔模型,我們很容易就可以設(shè)計(jì)出一個(gè)內(nèi)嵌模式的文檔模型出來(lái)。

        可以不夸張地說(shuō),80%~90%的場(chǎng)景下,我們優(yōu)先都會(huì)使用內(nèi)嵌對(duì)象 或 內(nèi)嵌數(shù)組 的方式來(lái)設(shè)計(jì)文檔模型的所謂的1-1、1-N、N-N的關(guān)系。

        例如下面這個(gè)Contacts的文檔模型,它描述了一個(gè)聯(lián)系人的關(guān)系建模:

        Contacts
        { name: "Edison Zhou", company: "CSCEC YZW", title: ".NET Engineer", portraits: { mimetype: xxx, data: xxxx }, addresses: [ { type: home, … }, { type: work, … } ], groups: [    {name: "YZW Football Assocation" },    {name: "YZW .NET Assocation" } ]}

        可以看到,所謂的內(nèi)嵌類 其實(shí) 類似于 預(yù)先聚合(關(guān)聯(lián)),這樣的操作(引用+冗余)其實(shí)對(duì)讀操作更有性能優(yōu)勢(shì)。

        但是,內(nèi)嵌設(shè)計(jì)有一個(gè)大前提限制:即內(nèi)嵌后文檔大小不能超過(guò)16MB。

        此外,如果內(nèi)嵌的數(shù)組(通常是數(shù)組)的長(zhǎng)度太大,比如數(shù)萬(wàn)或更多的時(shí)候,也是不適合采用內(nèi)嵌模式的。

        那么,此時(shí)我們應(yīng)該怎么設(shè)計(jì)呢?

        2引用模式

        萬(wàn)級(jí)長(zhǎng)度的內(nèi)嵌數(shù)組

        這里我們?nèi)匀贿m用上面提到的Contacts模型,假設(shè)其中的groups是一個(gè)內(nèi)嵌數(shù)組,這個(gè)groups的數(shù)據(jù)可能有百萬(wàn)級(jí)的長(zhǎng)度,且每個(gè)Contacts文檔都需要冗余這么一份數(shù)據(jù),而且groups數(shù)據(jù)還面臨著頻繁修改的需求。

        Contacts
        { name: "Edison Zhou", company: "CSCEC YZW", title: ".NET Engineer", ......  // 假設(shè)下面groups有百萬(wàn)級(jí),且一個(gè)group的信息改動(dòng)會(huì)引發(fā)百萬(wàn)級(jí)的DB操作 groups: [ {name: "YZW Football Assocation" }, {name: "YZW .NET Assocation" } ]}

        適當(dāng)使用引用模式解決

        解決方案很簡(jiǎn)單,就是針對(duì)groups使用單獨(dú)的collection來(lái)存儲(chǔ),在Contancts模型中添加對(duì)group id的集合的引用。

        Collection 1 - Contacts:

        Contacts
        { name: "Edison Zhou", company: "CSCEC YZW", title: ".NET Engineer", ...... // 假設(shè)下面groups有百萬(wàn)級(jí),且一個(gè)group的信息改動(dòng)會(huì)引發(fā)百萬(wàn)級(jí)的DB操作  group_ids: [1,2,3,4,5...]}

        Collection 2 - Groups:

        Groups
        { groups_id, name}

        這樣的設(shè)計(jì)其實(shí)類似于關(guān)系型數(shù)據(jù)庫(kù)模型的設(shè)計(jì),用Id來(lái)關(guān)聯(lián),我們?cè)偈煜げ贿^(guò)了。

        但是,在MQL中,我們就需要額外使用$lookup來(lái)實(shí)現(xiàn)類似SQL中的關(guān)聯(lián)查詢了,嚴(yán)格來(lái)說(shuō),應(yīng)該算是LEFT OUTER JOIN查詢。

        嗯,這又是一種聚合操作:

        db.Contacts.aggregate([{  $lookup:  {    from: "groups",    localField: "group_ids",    foreignField: "group_id",    as: "groups"  }}]);

        這個(gè)查詢會(huì)得到如下圖所示的結(jié)果:

        .NET中的Lookup操作:

        上面講解了如何通過(guò)MQL進(jìn)行操作,那么,在.NET中如何實(shí)現(xiàn)$lookup的效果呢?

        好在MongoDB Driver已經(jīng)幫我們提供了這樣的一個(gè)LookUp,且看下面的代碼示例:

        假設(shè)我們的實(shí)體定義如下:

        public class Contact{    [BsonId]    [BsonRepresentation(BsonType.ObjectId)]    public string Id { get; set; }
        public string Name { get; set; }
        public string Company { get; set; }
        public string Title { get; set; }
        public int[] GroupIds { get; set; }
        public IList<Group> Groups { get; set; }}
        public class Group{ [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; }
        public int GroupId { get; set; }
        public string Name { get; set; }}

        那么,可以通過(guò)Driver實(shí)現(xiàn)以下操作:

        public async Task<IList<Contact>> GetAsync(){    return await _contacts        .Aggregate()        .Lookup<Contact, Group, Contact>(            _groups,            local => local.GroupIds,            from => from.GroupId,            result => result.Groups)        .ToListAsync();}

        完整示例github地址:https://github.com/EdisonChou/EDT.Mongo.Sample

        運(yùn)行結(jié)果如下所示:

        什么時(shí)候使用引用模式

        綜上所述,當(dāng)滿足以下條件之一時(shí),你可以開(kāi)始考慮引用模式設(shè)計(jì)文檔模型:

        (1)當(dāng)內(nèi)嵌后的文檔太大,有可能超過(guò)16MB限制的時(shí)候;

        (2)內(nèi)嵌的文檔 或 數(shù)組元素 有可能會(huì)頻繁修改的時(shí)候;

        (3)內(nèi)嵌數(shù)組元素 有可能會(huì)持續(xù)增長(zhǎng)且沒(méi)有封頂?shù)臅r(shí)候;

        引用模式設(shè)計(jì)的限制

        引用模式也并非銀彈,它存在以下一些限制:

        (1)MongoDB對(duì)于使用引用的集合之間沒(méi)有所謂的外鍵檢查;

        (2)MongoDB使用聚合框架的$lookup來(lái)模仿關(guān)聯(lián)查詢;

        (3)$lookup只支持LEFT OUTER JOIN,且關(guān)聯(lián)目標(biāo)(from)不能是分片表;

        db.Contacts.aggregate([{  $lookup:  {    from"groups"// 這里的from不能是分片表    ......  }}]);
        End總結(jié)

        本文簡(jiǎn)單介紹了MongoDB的模型設(shè)計(jì)中的內(nèi)嵌模式和引用模式,探討了引用模式的使用、何時(shí)使用 及 使用限制。

        下一篇,我們會(huì)學(xué)習(xí)MongoDB的模式設(shè)計(jì)中的一些設(shè)計(jì)模式并套用這些設(shè)計(jì)模式簡(jiǎn)化設(shè)計(jì)難度。


        參考資料

        唐建法,《MongoDB高手課》(極客時(shí)間)

        郭遠(yuǎn)威,《MongoDB實(shí)戰(zhàn)指南》(圖書)

        △推薦訂閱學(xué)習(xí)

        歡迎各位讀者加入微信群一起學(xué)習(xí)交流,
        在公眾號(hào)后臺(tái)回復(fù)“加群”即可~~

        ?

        ?

        瀏覽 67
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            av资源首页 | 俄罗斯2一3sex性hd | 肏屄视频网 | 影音先锋少妇 | 印度三级a做爰全过程 | 91视频导航| 国产伦精品一区二区三区… | 91蝌蚪熟女少妇嗷嗷叫 | 伊人性爱 | 狠狠干福利视频 |