鍍金池/ 問答/數(shù)據(jù)庫  HTML/ mongodb的關聯(lián)查詢$lookup

mongodb的關聯(lián)查詢$lookup

  • 現(xiàn)在有這樣的數(shù)據(jù)結構,比如在集合 class 里有一條
    {
        _id:ObjectId(123456789...),
        number:10,
        students:[
            {
                studentId:ObjectId(123456789...)/* 這個是student集合的id */
            },
            {
                studentId:ObjectId(123456789...)/* 這個是student集合的id */
            },
            ...
        ],
        teacher:ObjectId(123456789...),
        
    }
  • student 集合的數(shù)據(jù)結構是
    {
        _id:ObjectId(123456789...);
        name:'zhangsan',
        age:20,
    }
  • 現(xiàn)在的需求是查詢class的時候把student也取出來,這樣就要關聯(lián)查詢,我用的是pipeline的$lookup,但是好像只能查詢class下一級的屬性,比如關聯(lián)查詢teacher
    db.class.aggregate([
       {
          $lookup:
             {
                from: "teacher",
                localField: "teacher",
                foreignField: "_id",
                as: "teacher"
            }
       }
    ])
  • 但是student下的studentId,就無法實現(xiàn),我試過
    db.class.aggregate([
       {
           $unwind:students,
       },
       {
          $lookup:
             {
                from: "student",
                localField: "students.studentId",
                foreignField: "_id",
                as: "student",/* 這里可能不對,但是不影響把student取出來 */
            }
       }
    ])
  • 希望有大佬可以解惑!不能改數(shù)據(jù)結構
回答
編輯回答
小眼睛

使用MongoDB的第一件事情就是忘掉關系模型,充分利用反范式、冗余來達成最高的讀寫效率。你已經(jīng)發(fā)現(xiàn)了現(xiàn)在的數(shù)據(jù)模型不好用,為什么不換個思路來解決問題?
決定數(shù)據(jù)模型的是你需要怎么使用這些數(shù)據(jù)。在不知道你打算怎么用這些數(shù)據(jù)的前提下,以下是一些按照常理的推測。
現(xiàn)在涉及的實體有3個:

  • teacher
  • student
  • class

其中:

  • teacher:class = 1:n
  • class:student = 1:n

對于1:n的情況,最常見的做法是把1冗余到n。比如學生可以是:

{
    _id:ObjectId(123456789...),
    name:'zhangsan',
    age:20,
    class: {
        classId: ObjectId(123456789...),
        number:10,
        // 其他常用字段
    }
}

當然你也可以不要class的詳細信息,畢竟一個班的學生只用查一次班級信息。

{
    _id:ObjectId(123456789...),
    name:'zhangsan',
    age:20,
    classId: ObjectId(123456789...)
}

用的時候是不是會方便一些?
沒錯,冗余有可能會造成數(shù)據(jù)不一致,但是你真的會這么在乎一致性嗎?通常的回答是不會。
比如如果班級信息如果要修改怎么辦?那就會造成每個學生的班級信息都更新一遍,修改時壓力會比較大操作比較復雜。但是別忘了你的系統(tǒng)大部分壓力是來自讀而不是寫。班級修改的概率有多大?可能幾個月不見得有一次。但是讀班級的概率有多大?可能每天就有好多次。比較一下孰輕孰重不言而喻。

綜上,使用MongoDB時不要用范式來約束自己,從性能,易用性來考慮就可以了。

2018年3月27日 03:12