MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Météores et DBRefs

Jouer avec Cursor.observe a répondu à ma question. Ce n'est peut-être pas le moyen le plus efficace de le faire, mais résout mes futurs problèmes de déréférencement des "liens" DBRefs

Donc, pour le serveur, nous devons publier une collection spéciale. Celui qui peut énumérer le curseur et pour chaque document rechercher le DBRef correspondant. Gardez à l'esprit que cette implémentation est codée en dur et doit être effectuée sous la forme d'un package comme UnRefCollection.

Côté serveur

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

Pour chaque document de journaux ajouté, il recherchera la collection d'utilisateurs et tentera d'ajouter à la collection de journaux les informations manquantes. La fonction ajoutée est appelée pour chaque document de la collection de journaux lors de la première exécution. J'ai créé une startupList et un tableau d'utilisateurs uniques. ids donc pour la première exécution, il n'interrogera la base de données qu'une seule fois. C'est une bonne idée de mettre un mécanisme de pagination pour accélérer les choses.

Côté client

Sur le client, abonnez-vous à la collection logsAndUsers, si vous souhaitez apporter des modifications, faites-le directement dans la collection Logs.

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