我有一个简单的应用程序,显示了Projects个列表.我已经删除了autopublish软件包,所以我不会把所有东西都发送给客户.

 <template name="projectsIndex">    
   {{#each projects}}      
     {{name}}
   {{/each}}
 </template>

启用autopublish时,将显示所有项目:

if Meteor.isClient
  Template.projectsIndex.projects = Projects.find()

移除后,我还需要做以下工作:

 if Meteor.isServer
   Meteor.publish "projects", ->
     Projects.find()
 if Meteor.isClient
   Meteor.subscribe "projects"
   Template.projectsIndex.projects = Projects.find()

那么,客户端find()方法只搜索从服务器端发布的记录是否准确?它一直在绊倒我,因为我觉得我应该只打一次find().

推荐答案

Collection 、出版物和订阅是Meteor的一个棘手领域,文档可以更详细地讨论,以避免frequentconfusion,有时会被放大confusing terminology.

下面是Sacha Greif位(DiscoverMeteor的合著者)在一张幻灯片中解释出版物和订阅:

订阅

为了正确理解为什么您需要多次拨打find(),您需要了解Meteor中的Collection 、出版物和订阅是如何工作的:

  1. 您可以在MongoDB中定义集合.还没有Meteor .这些集合包含100个文档(Mongo and Meteor也称为"文档",但"文档"比数据库记录更通用;例如,更新规范或查询 Select 器是文档too——包含field: value对的JavaScript对象).

  2. 然后用on the Meteor server定义collections

    MyCollection = new Mongo.Collection('collection-name-in-mongo')
    

    这些集合包含all个来自MongoDB集合的数据,您可以在它们上运行MyCollection.find({...}),这将返回100(一组记录,带有遍历它们并返回它们的方法).

  3. 这个光标(大多数情况下)用于100(发送)一组记录(称为"record set").您可以 Select 仅发布这些记录中的101个字段.客户机102需要的是记录集(not个集合).发布由publish function完成,它在每次新客户端订阅时都会被调用,它可以使用参数来管理要返回的记录(例如,用户id,仅返回该用户的文档).

  4. On the client,您有Minimongo个集合,其中partially个镜像了来自服务器的some条记录."部分"是因为它们可能只包含一些字段,"部分记录"是因为您通常只想向客户端发送它需要的记录,以加快页面加载,并且只有它需要的记录才有访问权限.

    Minimongo本质上是纯JavaScript中Mongo的内存中非持久性实现.它充当一个本地缓存,只存储该客户机正在使用的数据库的子集.客户机上的查询(find)直接从该缓存中提供,而无需与服务器通信.

    这些Minimongo系列最初是空的.他们被人填满了

    Meteor.subscribe('record-set-name')
    

    电话.请注意,参数subscribe不是集合名称;这是服务器在publish呼叫中使用的record set的名称.subscribe()调用将客户机订阅到服务器集合中的record set-记录子集(例如,最近的subscribe篇博客文章),每个记录中包含所有字段或字段的子集(例如,只有titledate).Minimongo如何知道将传入记录放入哪个集合?集合的名称将是发布处理程序的addedchangedremoved回调中使用的collection参数,或者如果缺少这些参数(大多数情况下都是这样),则它将是服务器上MongoDB集合的名称.

修改记录

这就是Meteor使事情变得非常方便的地方:当你在客户端上修改Minimongo集合中的记录(文档)时,Meteor将立即更新依赖它的所有模板,并将更改发送回服务器,反过来,它将把更改存储在MongoDB中,并将它们发送给订阅了包括该文档在内的记录集的相应客户端.这被称为latency compensation,是seven core principles of Meteor中的一个.

多个订阅

你可以有一堆订阅,它们会拉入不同的记录,但如果这些记录来自服务器上的同一个集合,那么它们最终都会在客户端上的同一个集合中,基于它们的_id条记录.这一点没有得到明确解释,但Meteor 文件暗示了这一点:

当您订阅一个记录集时,它会告诉服务器向客户端发送记录.客户机将这些记录存储在本地Minimongo集合中,与发布处理程序的addedchangedremoved回调中使用的collection参数同名.Meteor将对传入属性进行排队,直到您声明Mongo.具有匹配集合名称的客户端上的集合.

没有解释的是,当您don't显式地使用addedchangedremoved,或者根本不使用发布处理程序时会发生什么情况——大多数情况下都是这样.在这种最常见的情况下,collection参数(毫不奇怪)取自您在步骤1中在服务器上声明的MongoDB集合的名称.但这意味着,您可以使用不同的名称进行不同的发布和订阅,所有记录都将在客户端的同一个集合中结束.Meteor负责在文档之间执行一组并集,以使订阅可以重叠——发布功能将不同的顶级字段并排发送到客户端,在客户端上,集合中的文档将是union of the two sets of fields.

示例:在客户端上填充同一集合的多个订阅

您有一个BlogPosts集合,您在服务器和客户端上以相同的方式声明它,尽管它做的事情不同:

BlogPosts = new Mongo.Collection('posts');

在客户端上,BlogPosts个用户可以从以下位置获取记录:

  1. 订阅最近10篇博客文章

    // server
    Meteor.publish('posts-recent', function publishFunction() {
      return BlogPosts.find({}, {sort: {date: -1}, limit: 10});
    }
    // client
    Meteor.subscribe('posts-recent');
    
  2. 对当前用户帖子的订阅

    // server
    Meteor.publish('posts-current-user', function publishFunction() {
      return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10});
      // this.userId is provided by Meteor - http://docs.meteor.com/#publish_userId
    }
    Meteor.publish('posts-by-user', function publishFunction(who) {
      return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10});
    }
    
    // client
    Meteor.subscribe('posts-current-user');
    Meteor.subscribe('posts-by-user', someUser);
    
  3. 订阅最受欢迎的帖子

所有这些文档都来自MongoDB中的posts集合,通过服务器上的BlogPosts集合,最终进入客户机上的BlogPosts集合.

现在我们可以理解为什么您需要多次拨打find(),第二次是在客户机上,因为来自所有订阅的文档最终将位于同一个集合中,并且您只需要获取您关心的文档.例如,要获取客户端上的最新帖子,只需从服务器镜像查询:

var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});

这将返回一个光标,指向客户端迄今为止收到的所有文档/记录,包括顶级帖子和用户帖子.(thanks Geoffrey).

Mongodb相关问答推荐

MongoDB Aggregate:查找每个月的交叉日期范围的数量

如何在MongoDB中通过限制和跳过查找项进行匹配

MongoDB即使在使用索引时也很慢

如何在Mongodb Mongoose Nodejs中提取不等于一组值的字段

MongoDB 聚合 - $project 和 $match 阶段未按预期工作

从具有多个数组匹配 MongoDB 的两个集合中采样数据

mongoDB 过滤、排序和排名结果

在 mongodb 聚合中的阶段之后输出具有序列数字 id 的新集合

如何在mongoDB中按嵌套文档分组( group by )

MongoDB 到 Snowflake 连续加载

MongoID find 或 find_by

mongo.lock 文件有什么用?

Spring Boot MongoDB 连接问题

为什么 local.oplog.rs 上每隔几分钟的活动就会锁定 mongo 客户端

返回从循环中调用的数据库查询中检索到的数据的问题

spring-data-mongo - 可选查询参数?

MongoDB count() 未定义

在 mongodb 中的索引列上查找重复项的快速方法

如何通过键名从 mongoDB 中检索值?

Mongodb Compass 无法在 Ubuntu 18.10 中打开