在每个文档中构建一个包含附加字段的反应性出版物
Build a reactive publication with additional fields in each document
我想制作一个包含多个附加字段的出版物,但我不想使用 Collection.aggregate
并在集合更改时丢失我的出版物更新(所以我不能只使用 self.added
在里面)。
我打算使用 Cursor.observeChanges
来实现这一点。我有两个主要限制:
- 我不想发布所有文档字段
- 我想使用一些未发布的字段来创建新的字段。例如,我有一个字段
item
,我在其中存储一个 item
_id 的数组。我不想发布它,但我想发布一个 item_count
字段,其长度为我的字段数组
方法来了:
我打算链接查找查询。我从来没有这样做过,所以我想知道这是否可能。一般(简化的)查询结构是这样的:http://jsfiddle.net/Billybobbonnet/1cgrqouj/(我无法在此处正确显示代码)
基于the count example in Meteor documentation,我将查询存储在变量handle
中,以便在客户端取消订阅时停止更改通知:
self.onStop(function () {
handle.stop();
});
- 我在查询之前添加了一个标志
initializing = true;
,并在调用 self.ready();
之前将其设置为 true
。仅当发布已初始化时,我才使用此标志更改我的 itemCount
变量。所以基本上,我像这样更改 switch
:
switch (field) {
case "item"
if (!initializing)
itemCount = raw_document.item.length;
break;
default:
}
在对我的代码进行重大更改之前,我想检查一下这种方法是否可行。如果这是正确的方法,有人可以确认我吗?
要解决您的第一个问题,您需要告诉 MongoDB 它应该 return 游标中的哪些字段。省略不需要的字段:
MyCollection.find({}, {fields: {'a_field':1}});
解决你的第二个问题也很简单,我建议使用collection helpers packages。您可以像这样轻松完成此操作:
// Add calculated fields to MyCollection.
MyCollection.helpers({
item_count: function() {
return this.items.length;
}
});
这将是 运行 在将对象添加到游标之前,并将在动态计算的 returned 对象上创建属性,而不是存储在 MongoDB 中。
保持字段私有相对容易,即使它们是数据库查询的一部分。 self.added
的最后一个参数是传递给客户端的对象,因此您可以 strip/modify/delete 发送给客户端的字段。
这是您的 fiddle 的修改版本。这应该做你所要求的。 (老实说,我不确定为什么你在 fiddle 中的 observeChanges
函数之后链接了任何东西,所以也许我误解了你,但看看你的问题的其余部分应该是这样.如果我说错了请见谅。)
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();
});
我想制作一个包含多个附加字段的出版物,但我不想使用 Collection.aggregate
并在集合更改时丢失我的出版物更新(所以我不能只使用 self.added
在里面)。
我打算使用 Cursor.observeChanges
来实现这一点。我有两个主要限制:
- 我不想发布所有文档字段
- 我想使用一些未发布的字段来创建新的字段。例如,我有一个字段
item
,我在其中存储一个item
_id 的数组。我不想发布它,但我想发布一个item_count
字段,其长度为我的字段数组
方法来了:
我打算链接查找查询。我从来没有这样做过,所以我想知道这是否可能。一般(简化的)查询结构是这样的:http://jsfiddle.net/Billybobbonnet/1cgrqouj/(我无法在此处正确显示代码)
基于the count example in Meteor documentation,我将查询存储在变量
handle
中,以便在客户端取消订阅时停止更改通知:
self.onStop(function () {
handle.stop();
});
- 我在查询之前添加了一个标志
initializing = true;
,并在调用self.ready();
之前将其设置为true
。仅当发布已初始化时,我才使用此标志更改我的itemCount
变量。所以基本上,我像这样更改switch
:
switch (field) {
case "item"
if (!initializing)
itemCount = raw_document.item.length;
break;
default:
}
在对我的代码进行重大更改之前,我想检查一下这种方法是否可行。如果这是正确的方法,有人可以确认我吗?
要解决您的第一个问题,您需要告诉 MongoDB 它应该 return 游标中的哪些字段。省略不需要的字段:
MyCollection.find({}, {fields: {'a_field':1}});
解决你的第二个问题也很简单,我建议使用collection helpers packages。您可以像这样轻松完成此操作:
// Add calculated fields to MyCollection.
MyCollection.helpers({
item_count: function() {
return this.items.length;
}
});
这将是 运行 在将对象添加到游标之前,并将在动态计算的 returned 对象上创建属性,而不是存储在 MongoDB 中。
保持字段私有相对容易,即使它们是数据库查询的一部分。 self.added
的最后一个参数是传递给客户端的对象,因此您可以 strip/modify/delete 发送给客户端的字段。
这是您的 fiddle 的修改版本。这应该做你所要求的。 (老实说,我不确定为什么你在 fiddle 中的 observeChanges
函数之后链接了任何东西,所以也许我误解了你,但看看你的问题的其余部分应该是这样.如果我说错了请见谅。)
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();
});