我目前正在我的应用中实现实时搜索功能,而且我遇到了一些我很困惑的行为。
背景是:我在服务器上的同一个MongoDB数据库中有两个订阅,名为posts
。
第一个订阅订阅最新的50个帖子,并将数据发送到MiniMongo集合Posts
。
第二个订阅订阅匹配用户输入的任何搜索的帖子,并将此数据发送到MiniMongo集合PostsSearch
,如下所示。
// client
Posts = new Mongo.Collection('posts');
PostsSearch = new Mongo.Collection('postsSearch');
// server
Meteor.publish('postsPub', function(options, search) {
return Posts.find(search, options);
});
Meteor.publish('postsSearchPub', function(options, search) {
var self = this;
var subHandle = Posts.find(search, options).observeChanges({
added: function (id, fields) {
self.added("postsSearch", id, fields);
}
});
self.ready();
});
我的问题是,我们从文档中了解到:
如果您在创建集合时传递名称,那么您就是 声明持久集合 - 存储在服务器上的集合 并被所有用户看到。客户端代码和服务器代码都可以访问 使用相同API的相同集合。
然而PostsSearch
并非如此。当用户开始在客户端上搜索时,该功能可以完美地按预期工作 - 将正确的游标发送到客户端。
但是我的MongoDB数据库中没有postsSearch
,同样地,PostsSearch
没有在我自己以外的任何其他客户端上填充。
这是怎么回事?什么是self.added("postsSearch", id, fields);
似乎可以做到这一点,它能够将游标发送到客户端,而不是发送到MongoDB数据库。
答案 0 :(得分:1)
根据此doc,self.added("postsSearch", id, fields);
通知客户端已将文档添加到postsSeach
集合中。
或者,发布功能可以通过调用添加功能(将新文档添加到已发布的记录集)直接控制其已发布的记录集,...
所以我猜测self.added
执行这两项操作:将文档添加到发布的记录集,并通知客户端(已订阅当前的出版物) )这个补充。
现在,如果您看到Meteor.subscribe:
订阅记录集时,它会告诉服务器将记录发送到客户端。客户端将这些记录存储在本地Minimongo集合中,其名称与发布处理程序的添加,更改和删除的回调中使用的集合参数相同。 Meteor将对传入的记录进行排队,直到您在客户端上使用匹配的集合名称声明Mongo.Collection。
这表明有两件事:
您 到subscribe
以便从服务器端数据库接收数据。
必须存在某种客户端代码才能创建仅限客户端的postsSearch
集合。 (这是因为你说过,这个集合并不存在于服务器端数据库中)。
第二点可以很容易地实现,例如:
if(Meteor.isClient) {
postsSearch = new Mongo.Collection(null);
}
在上面的示例中,postsSearch
集合仅存在于客户端而不存在于服务器上。
关于第1个,订阅postsSearchPub
将自动将postsSearch
集合的数据发送给客户端(即使服务器端数据库中不存在所述集合。是因为显式调用self.added
)。
要检查的内容:根据此doc,self.ready();
会调用订阅的onReady
回调。查看此回调中的内容会很有用,也许在那里定义了仅限客户端的postsSearch
集合?
答案 1 :(得分:0)
来自doc:
SafeArrayCreate(VT_I4, 1, &bounds);
这意味着行this.added(collection, id, fields)
Call inside the publish function.
Informs the subscriber that a document has been added to the record set.
会模仿已经对self.added("postsSearch", id, fields);
集合进行了插入这一事实,尽管事实并非如此。
关于没有MongoDB集合,它可能与Meteor懒惰有关,它在第一次插入时会创建MongoDB集合,但不确定。