Ответ 1
Если я правильно понимаю, вы хотите, чтобы в каждом фиде было поле lastActivity
, которое содержит отметку времени последнего поданного элемента фида этого фида. Вы хотите, чтобы это поле было реактивным, и вы не хотите публиковать все элементы фида.
В этом случае агрегация не является решением, потому что Метеор не допускает реактивных агрегатов.
Вам необходимо использовать низкоуровневый API публикации: http://docs.meteor.com/#/full/meteor_publish (см. раздел примера).
Низкоуровневый публичный API (this.added
/this.removed
/this.changed
/others) дает вам полный контроль над тем, какие данные вы отправляете клиенту с помощью метода Meteor.publish
.
Вот как вы можете решить свою проблему (я использую синтаксис ES2015):
// client/client.js
Meteor.subscribe('userFeeds', { userId: 1 });
// lib/lib.js
Feeds = new Mongo.Collection('feeds');
FeedElements = new Mongo.Collection('FeedElements');
// server/server.js
// When setting `submitted` field, automatically set `submittedAt` field
// (I use matb33:collection-hooks here)
FeedElements.before.update((userId, elem, fieldNames, modifier) => {
if (modifier.$set.submitted) {
modifier.$set.submittedAt = new Date();
}
});
function getLastActivity(feedId) {
const lastSubmittedElem = FeedElements.findOne(
{
feedId,
submitted: true,
},
{
sort: { submittedAt: -1 }
}
);
return lastSubmittedElem ? lastSubmittedElem.submittedAt : null;
}
Meteor.publish('userFeeds', function({ userId }) {
const elemsObservers = {};
// Observe all user feeds
var feedObserver = Feeds.find({ userId: userId }).observeChanges({
added: (feedId, fields) => {
// Observe feed elements of the feed
elemsObservers[feedId] = FeedElements.find({ feedId }).observeChanges({
changed: (elemId, fields) => {
// Update `lastActivity` field when new element is submitted
if (fields.submitted) {
this.changed('feeds', feedId, { lastActivity: fields.submittedAt });
}
},
});
fields.lastActivity = getLastActivity(feedId);
this.added('feeds', feedId, fields);
},
changed: (feedId, fields) => {
this.changed('feeds', feedId, fields);
},
removed: (feedId) => {
elemsObservers[feedId].stop();
delete elemsObservers[feedId];
this.removed('feeds', feedId);
},
});
this.ready();
this.onStop(function() {
feedObserver.stop();
for (const feedId in elemsObservers) {
elemsObservers[feedId].stop();
}
});
});
Также я подготовил github repo https://github.com/imkost/feeds. Просто git clone
и meteor run
.