sql >> Base de Datos >  >> NoSQL >> MongoDB

Meteoro y DBRefs

Jugar con Cursor.observe respondió a mi pregunta. Puede que no sea la forma más efectiva de hacer esto, pero resuelve mis problemas futuros de anular la referencia de "enlaces" de DBRefs

Entonces, para el servidor, necesitamos publicar una colección especial. Uno que puede enumerar el cursor y para cada documento buscar el DBRef correspondiente. Tenga en cuenta que esta implementación está codificada y debe hacerse como un paquete como UnRefCollection.

Lado del servidor

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

Para cada documento de registros agregado, buscará en la colección de usuarios e intentará agregar a la colección de registros la información que falta. La función agregada se llama para cada documento en la colección de registros en la primera ejecución. Creé una lista de inicio y una matriz de usuarios únicos. ids, por lo que para la primera ejecución consultará la base de datos solo una vez. Es una buena idea poner un mecanismo de paginación para acelerar las cosas.

Lado del cliente

En el cliente, suscríbase a la colección logsAndUsers, si desea realizar cambios, hágalo directamente en la colección 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);
});