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