Zabawa z Cursor.observe odpowiedziała na moje pytanie. Może nie jest to najskuteczniejszy sposób na zrobienie tego, ale rozwiązuje moje przyszłe problemy związane z odraczaniem „łączy” DBRefs
Więc dla serwera musimy opublikować specjalną kolekcję. Taki, który może wyliczyć kursor i dla każdego dokumentu wyszukać odpowiedni DBRef. Pamiętaj, że ta implementacja jest zakodowana na sztywno i powinna być wykonana jako pakiet, taki jak UnRefCollection.
Po stronie serwera
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();
});
Dla każdego dodanego dokumentu z logami przeszuka kolekcję użytkowników i spróbuje dodać do zbioru logów brakujące informacje. Dodana funkcja jest wywoływana dla każdego dokumentu w kolekcji logs w pierwszym uruchomieniu Utworzyłem listę startową i tablicę unikalnych użytkowników ids, więc przy pierwszym uruchomieniu zapyta on db tylko raz. Dobrym pomysłem jest umieszczenie mechanizmu stronicowania, aby przyspieszyć działanie.
Strona klienta
Na kliencie zasubskrybuj kolekcję logsAndUsers, jeśli chcesz wprowadzić zmiany, zrób to bezpośrednio w kolekcji 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);
});