Meteor:集合、变量、发布和订阅名称的区别是什么?

10
在Discover Meteor的示例中,“posts”和“Posts”有什么区别?为什么我们从服务器进行插入时使用“posts”,但在从浏览器查询时使用“Posts”?系统不会因大小写差异而混淆吗?
我在posts.js中看到了将客户端的Posts赋值给服务器端的posts的变量赋值。将客户端大写,服务器端小写是一种常规表示法吗?
Posts = new Meteor.Collection('posts')

为什么server/fixtures.js使用“Posts”? 我原以为我们在浏览器(客户端)中查询“Posts”,并在服务器中使用“posts”,就像我们在meteor mongo中所做的那样。那么为什么现在在服务器中使用Posts呢?


2个回答

38

让我们区分编程Meteor时可能需要处理的不同名称:

  • 变量名称,例如Posts = new Meteor.Collection(...)。这些仅用于使您的代码知道如何访问此变量。Meteor不知道或不关心它是什么,尽管惯例是大写。
  • 集合名称,例如new Meteor.Collection("posts")。这映射到MongoDB集合(在服务器上)或minimongo集合(在客户端上)的名称。
  • 发布和订阅名称,在Meteor.publish("foo", ...)Meteor.subscribe("foo")中使用。这些必须匹配,以便客户端订阅服务器上的某些数据。

在Meteor数据模型中,您需要匹配两个内容:

  1. 出版物的名称及其相应的订阅
  2. (通常)客户端和服务器上的集合名称,如果使用默认的集合模型

订阅名称需要始终与出版物名称匹配。但是,对于给定订阅发送的集合不必与订阅名称有任何关系。实际上,可以在一个出版物中发送多个光标或将一个集合发送到不同的出版物或甚至每个出版物有多个订阅,它们在客户端上作为一个合并显示。您还可以在服务器和客户端中使用不同的集合名称;请继续阅读...

让我们回顾不同的情况:

  1. 简单的订阅模型。这是您通常在直接的Meteor演示中看到的模型。

    在客户端和服务器上,

Posts = new Meteor.Collection("posts");

仅限服务器:

Meteor.publish("postsPub", function() { 
    return Posts.find() 
});

仅限客户端:

Meteor.subscribe("postsPub")

这将使用名为postsPub的发布项,同步名为posts的数据库中的Posts集合。

  • 一个发布项中含有多个集合。你可以使用数组将多个游标一起发送到单个发布项上。

    在客户端和服务器端均可:

    Posts = new Meteor.Collection("posts");
    Comments = new Meteor.Collection("comments");
    

    仅限服务器:

    Meteor.publish("postsAndComments", function() { 
        return [ 
            Posts.find(), 
            Comments.find() 
        ]; 
    });
    

    仅在客户端上:

    Meteor.subscribe("postsAndComments");
    

    使用名为postsAndComments的单一发布订阅同时同步Posts集合和Comments集合。这种类型的发布订阅很适合关联数据的情况,例如您可能只想发布特定的帖子及其相关评论。请参见一个可以自动构建这些游标的包

    单个集合的多个发布订阅。您可以使用多个发布订阅将单个集合的不同数据片段发送到Meteor会自动合并的数据。

    在服务器和客户端:

    Posts = new Meteor.Collection("posts");
    

    仅在服务器上:

    Meteor.publish("top10Posts", function() { 
        return Posts.find({}, {
            sort: {comments: -1}, 
            limit: 10
        });
    });        
    Meteor.publish("newest10Posts", function() { 
        return Posts.find({}, {
            sort: {timestamp: -1},
            limit: 10
        }); 
    });
    

    仅适用于客户端:

    Meteor.subscribe("top10Posts");
    Meteor.subscribe("newest10Posts");
    

    这将把最多评论的10篇帖子和最新的10篇帖子推送给用户,将这两组数据合并到一个Posts集合中。如果最新的帖子之一也是评论最多或反之亦然,则Posts集合将包含少于20个项目。这是Meteor中数据模型允许您执行强大的数据合并操作而无需自己实现细节的示例。

    每个发布可以有多个订阅。您可以使用不同的参数从相同的发布获取多组数据。

    在服务器和客户端上:

    Posts = new Meteor.Collection("posts");
    

    仅在服务器上:

    Meteor.publish("postsByUser", function(user) { 
        return Posts.find({
            userId: user
        });
    });        
    

    仅限客户端:

    Meteor.subscribe("postsByUser", "fooUser");
    Meteor.subscribe("postsByUser", "barUser");
    

    这会导致由fooUserbarUser发布的帖子都出现在posts集合中。当您有几个不同的计算正在查看数据的不同部分并可能动态更新时,此模型非常方便。请注意,在您在Deps.autorun(...)内订阅时,Meteor会自动调用任何具有相同名称的先前订阅句柄上的stop(),但如果您在autorun之外使用这些订阅,则需要自己停止它们。目前为止,在autorun计算内无法执行具有相同名称的两个订阅,因为Meteor无法区分它们。

  • 在发布过程中推送任意数据。 您可以完全自定义发布以不要求服务器和客户端上具有相同的集合名称。实际上,服务器可以发布没有任何支持集合的数据。为此,您可以使用发布函数的 API

    仅限服务器:

  • Posts = new Meteor.Collection("posts"); 
    
    Meteor.publish("newPostsPub", function() {
        var sub = this;
        var subHandle = null;
    
        subHandle = Posts.find({}, {
            sort: {timestamp: -1},
            limit: 10
        })
        .observeChanges({
            added: function(id, fields) {
                sub.added("newposts", id, fields);            
            },
            changed: function(id, fields) {
                sub.changed("newposts", id, fields);            
            },
            removed: function(id) {
                sub.removed("newposts", id);
            }
        });
    
        sub.ready();
    
        sub.onStop(function() {
            subHandle.stop();
        })    
    });
    

    仅在客户端:

    NewPosts = new Meteor.Collection("newposts");
    
    Meteor.subscribe("newPostsPub");
    

    这将同步服务器上名称为postsPosts集合中最新的10篇文章到客户端名称为newpostsNewPosts集合,使用名为newPostsPub的发布/订阅方式。需要注意的是,observeChangesobserve不同,后者可以执行其他一些操作。

    虽然这段代码看起来很复杂,但实际上当你在发布函数中返回一个游标时,Meteor会在后台自动生成类似的代码。这种写法使你能够更好地控制发送给客户端的内容。但要注意,你必须手动关闭observe句柄并标记订阅状态为已准备就绪。更多信息,请参见Matt Debergalis关于此过程的描述(但该帖子已过时)。当然,你可以将这个方法与上面提到的其他部分结合起来,以获取非常微妙和复杂的发布内容。

    对此可能有所困惑,非常抱歉 :-) ,但我认为描述所有情况可能会有用。


    1
    Andrew:你太棒了。感谢你提供的详细分析,这解决了很多问题! - Pierre
    1
    安德鲁,这真是非常有教育意义的。这种回答会引发“有所领悟”的时刻。 :) - Sahil Tandon

    2

    您可以决定命名规则,Meteor对此并不关心。

    “Posts”成为了来自Mongo服务器的文档集合。您可以通过调用Posts.find({author: 'jim'})来查找帖子。在您编写的示例中,Meteor被告知在内部调用该集合时使用名称“posts”。如果名称相似,这应该很容易记住......

    需要一种方法来表达和跟踪客户端可用的信息。有时可能会有多个信息集,具有不同的详细程度。例如:标题列表的摘要,但对于特定文档需要详细了解情况。这些通常也被命名为“posts”,因此可能会引起初步的混淆:

    Meteor.publish "posts", ->  # on server
      Posts.find()  
    

    然后

    dbs.subscriptions.posts = Meteor.subscribe 'posts'  # on client
    

    发布和订阅名称必须匹配,但可以全部命名为类似的方式:

    PostsDB = new Meteor.Collection('postdocumentsonserver')
    

    所以在Mongo中,您需要输入以下内容:

    db.postdocumentsonserver.find()
    

    但是除此之外,您永远不需要关心“postdocumentsonserver”。然后

    Meteor.publish "post_titles", ->
      PostsDB.find({},{fields:{name:1}})  
    

    匹配

    dbs.subscriptions.post_titles = Meteor.subscribe 'post_titles'
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接