2012-06-28 94 views
1

我在Win7(32)中使用流星0.3.7,並試圖創建一個簡單的日誌記錄系統,使用2個MongoDB集合來存儲由DBRef鏈接的數據。流星和DBRefs

當前僞模式是:

Users { 
     username : String, 
     password : String, 
     created : Timestamp, 
    } 

    Logs { 
     user_id : DBRef {$id, $ref} 
     message : String 
    } 

我使用服務器的方法來插入日誌,所以我可以做在客戶端上收集一些upserts。

現在我想要做一箇舊的「左連接」,並顯示最後n個帶有嵌入式用戶名的日誌列表。 我不想將日誌嵌入到用戶中,因爲最常用的操作是獲取最後的n個日誌。在我看來,嵌入會對性能產生重大影響。

實現此目標的最佳方法是什麼?

下一頁這是偉大的,如果可以編輯的用戶名和所有項目更改泰斯名

問候

回答

0

爲什麼不乾脆也存儲在日誌中收集的用戶名呢? 然後你就可以直接而無需任何形式的「加入」

他們查詢,如果由於某種原因,你需要能夠處理該用戶名的變化,你只要按名稱獲取用戶對象,然後用{ user_id : user._id }的日誌查詢

+0

嗨,謝謝你的回覆。是的,這是解決這個問題的一種簡單而有效的方式,而且我目前的實施方式如前所述。但我更專注於以遊標的方式去引用DBRefs。我正在嘗試使用Cursor.observe方法來實現此目的。本週晚些時候我會發布我的發現。問候 –

2

玩弄Cursor.observe回答了我的問題。它可能不是這樣做的最有效的方式,但解決了我的未來DBRefs「鏈接」的問題

因此,對於服務器,我們需要發佈一個特殊的集合。可以枚舉遊標併爲每個文檔搜索相應的DBRef。 請記住,這個實現是硬編碼的,應該像UnRefCollection一樣完成。

服務器端

CC.Logs = new Meteor.Collection("logs"); 
    CC.Users = new Meteor.Collection("users"); 

Meteor.publish('logsAndUsers', function (page, size) { 
    var self = this; 
    var startup = true; 
    var startupList = [], uniqArr = []; 

    page = page || 1; 
    size = size || 100; 
    var skip = (page - 1) * size; 

    var cursor = CC.Logs.find({}, {limit : size, skip : skip}); 
    var handle = cursor.observe({ 
     added : function(doc, idx){ 
      var clone = _.clone(doc); 
      var refId = clone.user_id.oid; // showld search DBRefs 
      if (startup){ 
       startupList.push(clone);  
       if (!_.contains(uniqArr, refId)) 
        uniqArr.push(refId); 
      } else { 
       // Clients added logs 
       var deref = CC.Users.findOne({_id : refid}); 
       clone.user = deref; 
       self.set('logsAndUsers', clone._id, clone); 
       self.flush(); 
      } 
     }, 
     removed : function(doc, idx){ 
      self.unset('logsAndUsers', doc._id, _.keys(doc)); 
      self.flush(); 
     }, 
     changed : function(new_document, idx, old_document){ 
      var set = {}; 
      _.each(new_document, function (v, k) { 
       if (!_.isEqual(v, old_document[k])) 
       set[k] = v; 
      }); 
      self.set('logsAndUsers', new_document._id, set); 
      var dead_keys = _.difference(_.keys(old_document), _.keys(new_document)); 
      self.unset('logsAndUsers', new_document._id, dead_keys); 
      self.flush(); 
     }, 
     moved : function(document, old_index, new_index){ 
      // Not used 
     } 
    }); 

    self.onStop(function(){ 
     handle.stop(); 
    }); 

    // Deref on first Run 
    var derefs = CC.Users.find({_id : {$in : uniqArr} }).fetch(); 
    _.forEach(startupList, function (item){ 
     _.forEach(derefs, function(ditems){ 
      if (item["user_id"].oid === ditems._id){ 
       item.user = ditems; 
       return false; 
      } 
     }); 
     self.set('logsAndUsers', item._id, item); 
    }); 
    delete derefs; // Not needed anymore 

    startup = false; 
    self.complete(); 
    self.flush(); 
}); 

對於每個添加的日誌文件,它會搜索用戶收集,並嘗試添加到日誌收集丟失的信息。 在第一次運行中爲日誌集合中的每個文檔調用添加的函數我創建了一個startupList和一個唯一用戶id數組,因此對於第一次運行它只會查詢數據庫一次。把分頁機制加快速度是一個好主意。

客戶端

在客戶端,訂閱logsAndUsers集合,如果你想改變這樣做直接的日誌收集。

LogsAndUsers = new Meteor.collection('logsAndUser'); 
Logs = new Meteor.colection('logs'); // Changes here are observed in the LogsAndUsers collection 

Meteor.autosubscribe(function() { 
    var page = Session.get('page') || 1; 
    Meteor.subscribe('logsAndUsers', page); 
});