如何在 Meteor.js 中的服务器端转换函数后设置 mongo 投影?
How to setup a mongo projection AFTER a server side transform function in Meteor.js?
在应用需要访问原始文档的转换后,我需要限制从发布函数发送到客户端的字段数。
我基本上是在尝试避免向客户端发送可能很大的数组,并且 运行 一堆检查 return 一个很好的整洁对象。
这是我现在得到的功能 - 它可以工作,只是不是我想要的方式,基本上限制了观察功能的字段。有没有办法在观察/变换之后添加投影。
Meteor.publish('network', function() {
var self = this;
// get the user values initially
var user = Meteor.users.findOne(self.userId);
var followingUsers = user.following ? user.following.users || [] : [];
var followingChannels = user.following ? user.following.channels || [] : [];
var transformMedia = function(doc) {
// get the user each time to keep this publication reactive
votesUp = doc.votes ? doc.votes.up || [] : [];
votesDown = doc.votes ? doc.votes.down || [] : [];
favourites = doc.votes ? doc.votes.favourites || [] : [];
doc.userActions = {
votedUp: _.contains(votesUp, doc._id) ? 1 : 0,
votedDown: _.contains(votesDown, doc._id) ? 1 : 0,
isFavourite: _.contains(favourites, doc._id) ? 1 : 0,
played: _.contains(doc.played, self.userId) ? 1 : 0,
};
return doc;
};
var networkQuery = Media.find({
$and: [
{
$and: [
{processedAt: { $exists: true} },
{processedStatus: 'successful'},
{publishStatus: 'published'}
]
},
{
// if created by this user, user they follow or channels they subscribe to
$or: [
{createdBy: self.userId },
{createdBy: { $in: followingUsers} },
{channels: { $in: followingChannels} },
]
}
// TODO : add not banned or trashed once implemented
]
}, mediaModifiers).observe({
added: function(doc) {
self.added('media', doc._id, transformMedia(doc));
},
changed: function(doc, oldDoc) {
self.changed('media', doc._id, transformMedia(doc));
},
removed: function(doc) {
self.removed('media', doc._id, transformMedia(doc));
},
});
self.onStop(function() {
networkQuery.stop();
});
self.ready();
});
我有 。我使用 cursor.observe()
+ 自定义函数(就像你所做的那样)处理它,我只是添加了一个 _.pick()
来过滤不必要的字段。看看这个发布代码的例子(特别是白名单 docToPublish
部分):
var self = this;
// Modify the document we are sending to the client.
function filter(doc) {
var length = doc.item.length;
// White list the fields you want to publish.
var docToPublish = _.pick(doc, [
'someOtherField'
]);
// Add your custom fields.
docToPublish.itemLength = length;
return docToPublish;
}
var handle = myCollection.find({}, {fields: {item:1, someOtherField:1}})
// Use observe since it gives us the the old and new document when something is changing.
// If this becomes a performance issue then consider using observeChanges,
// but its usually a lot simpler to use observe in cases like this.
.observe({
added: function(doc) {
self.added("myCollection", doc._id, filter(doc));
},
changed: function(newDocument, oldDocument)
// When the item count is changing, send update to client.
if (newDocument.item.length !== oldDocument.item.length)
self.changed("myCollection", newDocument._id, filter(newDocument));
},
removed: function(doc) {
self.removed("myCollection", doc._id);
});
self.ready();
self.onStop(function () {
handle.stop();
});
这段代码是从@datacarl 对我上面提到的主题的回答中借用的。
请注意,如果您扩展到多台服务器,这种方法的缺点是每台服务器都必须 运行 cursor.observe()
函数。
您还忘记准备发布并在发布结束时处理您的观察者(这可能是因为您没有粘贴所有发布)。它看起来像这样:
self.ready();
self.onStop(function () {
networkQuery.stop();
});
在应用需要访问原始文档的转换后,我需要限制从发布函数发送到客户端的字段数。
我基本上是在尝试避免向客户端发送可能很大的数组,并且 运行 一堆检查 return 一个很好的整洁对象。
这是我现在得到的功能 - 它可以工作,只是不是我想要的方式,基本上限制了观察功能的字段。有没有办法在观察/变换之后添加投影。
Meteor.publish('network', function() {
var self = this;
// get the user values initially
var user = Meteor.users.findOne(self.userId);
var followingUsers = user.following ? user.following.users || [] : [];
var followingChannels = user.following ? user.following.channels || [] : [];
var transformMedia = function(doc) {
// get the user each time to keep this publication reactive
votesUp = doc.votes ? doc.votes.up || [] : [];
votesDown = doc.votes ? doc.votes.down || [] : [];
favourites = doc.votes ? doc.votes.favourites || [] : [];
doc.userActions = {
votedUp: _.contains(votesUp, doc._id) ? 1 : 0,
votedDown: _.contains(votesDown, doc._id) ? 1 : 0,
isFavourite: _.contains(favourites, doc._id) ? 1 : 0,
played: _.contains(doc.played, self.userId) ? 1 : 0,
};
return doc;
};
var networkQuery = Media.find({
$and: [
{
$and: [
{processedAt: { $exists: true} },
{processedStatus: 'successful'},
{publishStatus: 'published'}
]
},
{
// if created by this user, user they follow or channels they subscribe to
$or: [
{createdBy: self.userId },
{createdBy: { $in: followingUsers} },
{channels: { $in: followingChannels} },
]
}
// TODO : add not banned or trashed once implemented
]
}, mediaModifiers).observe({
added: function(doc) {
self.added('media', doc._id, transformMedia(doc));
},
changed: function(doc, oldDoc) {
self.changed('media', doc._id, transformMedia(doc));
},
removed: function(doc) {
self.removed('media', doc._id, transformMedia(doc));
},
});
self.onStop(function() {
networkQuery.stop();
});
self.ready();
});
我有 cursor.observe()
+ 自定义函数(就像你所做的那样)处理它,我只是添加了一个 _.pick()
来过滤不必要的字段。看看这个发布代码的例子(特别是白名单 docToPublish
部分):
var self = this;
// Modify the document we are sending to the client.
function filter(doc) {
var length = doc.item.length;
// White list the fields you want to publish.
var docToPublish = _.pick(doc, [
'someOtherField'
]);
// Add your custom fields.
docToPublish.itemLength = length;
return docToPublish;
}
var handle = myCollection.find({}, {fields: {item:1, someOtherField:1}})
// Use observe since it gives us the the old and new document when something is changing.
// If this becomes a performance issue then consider using observeChanges,
// but its usually a lot simpler to use observe in cases like this.
.observe({
added: function(doc) {
self.added("myCollection", doc._id, filter(doc));
},
changed: function(newDocument, oldDocument)
// When the item count is changing, send update to client.
if (newDocument.item.length !== oldDocument.item.length)
self.changed("myCollection", newDocument._id, filter(newDocument));
},
removed: function(doc) {
self.removed("myCollection", doc._id);
});
self.ready();
self.onStop(function () {
handle.stop();
});
这段代码是从@datacarl 对我上面提到的主题的回答中借用的。
请注意,如果您扩展到多台服务器,这种方法的缺点是每台服务器都必须 运行 cursor.observe()
函数。
您还忘记准备发布并在发布结束时处理您的观察者(这可能是因为您没有粘贴所有发布)。它看起来像这样:
self.ready();
self.onStop(function () {
networkQuery.stop();
});