MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Meteor und DBRefs

Herumspielen mit Cursor.observe hat meine Frage beantwortet. Es ist vielleicht nicht der effektivste Weg, dies zu tun, aber es löst meine zukünftigen Probleme beim Dereferenzieren von DBRefs-„Links“

Für den Server müssen wir also eine spezielle Sammlung veröffentlichen. Eine, die den Cursor aufzählen und für jedes Dokument nach dem entsprechenden DBRef suchen kann. Denken Sie daran, dass diese Implementierung fest codiert ist und als Paket wie UnRefCollection erfolgen sollte.

Serverseite

    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();
});

Für jedes hinzugefügte Protokolldokument wird die Benutzersammlung durchsucht und versucht, die fehlenden Informationen zur Protokollsammlung hinzuzufügen. Die hinzugefügte Funktion wird für jedes Dokument in der Protokollsammlung aufgerufen. Beim ersten Durchlauf habe ich eine StartupList und ein Array eindeutiger Benutzer erstellt ids, also wird die Datenbank beim ersten Lauf nur einmal abgefragt. Es ist eine gute Idee, einen Paging-Mechanismus einzusetzen, um die Dinge zu beschleunigen.

Clientseite

Abonnieren Sie auf dem Client die logsAndUsers-Sammlung, wenn Sie Änderungen vornehmen möchten, tun Sie dies direkt an der Logs-Sammlung.

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