2012-06-28 3 views
1

Win7 (32)에서 meteor 0.3.7을 사용하고 있으며 DBRef로 연결된 데이터를 저장하기 위해 2 개의 MongoDB 컬렉션을 사용하여 간단한 로깅 시스템을 만들려고합니다.Meteor and DBRefs

현재 의사 스키마이다 : 나는 클라이언트 컬렉션 일부 upserts을 할 수 있도록

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

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

내가 로그를 삽입하는 서버 방법을 사용합니다.

이제는 "왼쪽 결합"을 수행하고 포함 된 사용자 이름으로 마지막 n 개의 로그 목록을 표시하려고합니다. 가장 많이 사용되는 작업이 마지막 n 개의 로그를 가져 오기 때문에 사용자의 로그를 포함하고 싶지 않습니다. 내 의견에 퍼지면 성능에 큰 영향을 미칠 것입니다.

이것을 달성하는 가장 좋은 방법은 무엇입니까? 사용자 이름을 편집 할 수있는 경우

다음 좋았어요 모든 항목이 변경 THEIS 이름

감사

답변

0

왜 그냥 또한뿐만 아니라 로그 컬렉션에서 사용자 이름을 저장? 그런 다음 "가입"없이도 직접 쿼리 할 수 ​​있습니다.

사용자 이름을 변경해야하는 경우에는 사용자 개체를 이름으로 가져온 다음 { user_id : user._id }

+0

안녕하십니까. 답장을 보내 주셔서 감사합니다. 네, 이것은이 문제를 해결할 수있는 간단하고 효과적인 방법이며, 현재의 구현은 언급 한 것과 같습니다. 그러나 커서에서 DBRef를 참조 해제하는 방법에 좀 더 집중했습니다. 이를 달성하기 위해 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 배열을 만들었으므로 첫 번째 실행에서는 db를 한 번만 쿼리합니다. 빠른 속도로 페이징 메커니즘을 적용하는 것이 좋습니다. 변경 사항은 로그 수집에 직접 할 수 있도록하려는 경우

클라이언트에 클라이언트 측

,의 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); 
});