mongodb的join操作


     眾所周知,mongodb是不支持join操作的,因此我們只能自己來實現這個功能。前段時間,我遇到這個一個業務場景:

     collection A 的數據格式:

{ "_id" : { "username" : "jifeng.zjd", "version" : 2 }, "value" : 1 }

     collection B 的數據格式:

{ "user_id" : 12630, "username" : "jifeng.zjd" }

     A表的數據量為2w,B表的數據量為25w。為了說明簡單,我簡化下需求,就是計算A._id.username = B.username 的B表中的用戶數據,也就是求A和B的交集。沒有join,怎么辦呢?

     相信大家都應該有自己的解答了,由於A表的數據量相對於B表來講是少的,所以可以先取出A表的所有數據,然后去B表查詢,看那些數據同時存在於A和B表中。當然在mongodb中對A和B建立適當的索引是非常必要的。我采用的方法是對B表的username字段進行索引。如對mongodb索引不了解,可以參見《mongoDB的索引使用及索引機制》 一文。

     這里我使用的語言是nodejs,node_module采用的mongoskin,我剛開始寫了一個簡單的實現:

db.A.find({}, {}, function(err, adata){
  if (err) return callback(err);
  //得到A表中的所有數據
  adata.toArray(function(err, aArray){
    if (err) return callback(err);
    var len = aArray.length;
    var result = [];
    for (var i = 0; i < len; i++) {
      var item = aArray[i];
      var username = item._id.username;
      var op = {username: username};
      //查看B表中這條數據
      db.B.findOne(op, {}, function(err, data){
        allcount++;
        if (data) {
          result.push(data.username); 
        }
        if (allcount === len) {
          callback(null, result); 
        } 
      })
    }
  })
})

      這段代碼是能滿足業務需求,但大家有沒有發現它存在一個致命的問題?對,運行速度慢!

      原因很簡單,我是從A表中批量取到所有數據,然后又用findOne方法一條條去B表中查詢,A表中有2w數據,也就是要查B表2w次,雖然B表中已經建立索引,但這樣的查詢邏輯明顯是不可接受。知道問題所在,解決方案也就清楚了:對B表進行批量查詢:

db.A.find({}, {}, function(err, adata){
  if (err) return callback(err);
  //得到A表中的所有數據
  adata.toArray(function(err, aArray){
    if (err) return callback(err);
    var len = aArray.length;
    var result = [];
    var usernames = [];
    for (var i = 0; i < len; i++) {
      var item = aArray[i];
      var username = item._id.username;
      usernames.push(username);
    }
    var op = {username: {$in: usernames}};
    //查看B表中這條數據
    db.B.find(op, {}, function(err, bdata){
      ddata.toArray(function(err, barray){
        callback(barray);  
      })
    })
  })
})

     經過這樣的優化,程序性能會有明顯的提升。

     希望對大家有所幫助。

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM