コレクション、出版物、購読はMeteorのトリッキーな領域であり、用語の混乱によって増幅されることがある頻繁な 混乱を避けるために、ドキュメントでより詳細に説明することができます。
これがSachaGreif(DiscoverMeteorの共著者)で、出版物と購読について1つのスライドで説明しています。
find()
複数回呼び出す必要がある理由を正しく理解するには、コレクション、パブリケーション、およびサブスクリプションがMeteorでどのように機能するかを理解する必要があります。
コレクションはMongoDBで定義します。Meteorはまだ関与していません。これらのコレクションは含まれていたデータベースのレコードを(もモンゴの両方で、「文書」と呼ばれると流星;例えば、更新仕様またはクエリセレクタは文書であるが、「文書」は、データベースレコードよりも一般的である、あまりにも- JavaScriptが含むオブジェクトfield: value
のペア)。
次に、Meteorサーバーでコレクション を定義します。
MyCollection = new Mongo.Collection('collection-name-in-mongo')
これらのコレクションには、MongoDBコレクションからのすべてのデータが含まMyCollection.find({...})
れており、それらを実行すると、カーソル(レコードのセット、それらを反復処理して返すメソッドを含む)が返されます。
このカーソルは、(ほとんどの場合)レコードのセット(「レコードセット」と呼ばれる)を公開(送信)するために使用されます。オプションで、これらのレコードから一部のフィールドのみを公開できます。クライアントがサブスクライブするのは(コレクションではなく)レコードセットです。公開は、新しいクライアントがサブスクライブするたびに呼び出される公開関数によって実行されます。この関数は、返すレコードを管理するためのパラメーターを受け取ることができます(たとえば、ユーザーID、そのユーザーのドキュメントのみを返す)。
クライアントには、サーバーからのレコードの一部を部分的にミラーリングするMinimongoコレクションがあります。「部分的に」あなたは通常、ページの読み込みを高速化するために、それが必要とするレコードだけクライアントに送信する、とのみ、それが必要なため、彼らは、「レコードの一部を」唯一のいくつかのフィールドの含めると、可能性があるためとする権限を持っていますアクセス。
Minimongoは本質的に、純粋なJavaScriptでのMongoのメモリ内の非永続的な実装です。これは、このクライアントが処理しているデータベースのサブセットのみを格納するローカルキャッシュとして機能します。クライアントでのクエリ(検索)は、サーバーと通信することなく、このキャッシュから直接提供されます。
これらのMinimongoコレクションは最初は空です。彼らはによって満たされています
Meteor.subscribe('record-set-name')
呼び出します。サブスクライブするパラメーターはコレクション名ではないことに注意してください。これは、サーバーが呼び出しで使用したレコードセットの名前ですpublish
。このsubscribe()
呼び出しは、クライアントをレコードセット(サーバーコレクションのレコードのサブセット(最新の100件のブログ投稿など))にサブスクライブし、各レコードのフィールドのすべてまたはサブセット(title
およびのみなどdate
)を使用します。Minimongoは、受信レコードを配置するコレクションをどのようにして知るのですか?コレクションの名前になりますcollection
ハンドラのパブリッシュに使用される引数added
、changed
およびremoved
コールバックを、またはそれらの(最も時間の場合である)不足している場合、それはサーバー上のMongoDBのコレクションの名前になります。
レコードの変更
これがMeteorが非常に便利なところです。クライアントのMinimongoコレクションのレコード(ドキュメント)を変更すると、Meteorはそれに依存するすべてのテンプレートを即座に更新し、変更をサーバーに送り返します。変更をMongoDBに保存し、そのドキュメントを含むレコードセットをサブスクライブしている適切なクライアントに送信します。これはレイテンシー補正と呼ばれ、Meteorの7つのコア原則の1つです。
複数のサブスクリプション
さまざまなレコードを取得するサブスクリプションを多数持つことができますが、サーバー上の同じコレクションからのものである場合、それらはすべてクライアント上の同じコレクションになります_id
。これは明確に説明されていませんが、Meteorのドキュメントによって暗示されています。
レコードセットをサブスクライブすると、サーバーにレコードをクライアントに送信するように指示します。クライアント店ローカルMinimongoのコレクションにこれらのレコードと同じ名前のcollection
公開ハンドラのに使用される引数added
、changed
およびremoved
コールバック。Meteorは、一致するコレクション名を使用してクライアントでMongo.Collectionを宣言するまで、着信属性をキューに入れます。
何を説明していないと、あなたは何が起こるかですしていない明示的に使用しadded
、changed
そしてremoved
ほとんどの時間である- 、またはすべてのハンドラを公開します。この最も一般的なケースでは、コレクション引数は(当然のことながら)ステップ1でサーバー上で宣言したMongoDBコレクションの名前から取得されます。ただし、これは、異なる名前の異なるパブリケーションとサブスクリプションを持つことができることを意味します。レコードは、クライアントの同じコレクションに入れられます。レベルに至るまで、トップレベルのフィールドで、文書を横にして、クライアント上のクライアントワーク側に別のトップレベルのフィールドを出荷する機能を公開- 、流星は、サブスクリプションが重複することができるような、文書間の和集合を実行するために世話をしますコレクションは2セットのフィールドの和集合。
例:クライアント上の同じコレクションを埋める複数のサブスクリプション
BlogPostsコレクションがあります。これは、サーバーとクライアントの両方で同じように宣言しますが、実行方法は異なります。
BlogPosts = new Mongo.Collection('posts');
クライアントでBlogPosts
は、以下からレコードを取得できます。
最新の10のブログ投稿へのサブスクリプション
Meteor.publish('posts-recent', function publishFunction() {
return BlogPosts.find({}, {sort: {date: -1}, limit: 10});
}
Meteor.subscribe('posts-recent');
現在のユーザーの投稿へのサブスクリプション
Meteor.publish('posts-current-user', function publishFunction() {
return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10});
}
Meteor.publish('posts-by-user', function publishFunction(who) {
return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10});
}
Meteor.subscribe('posts-current-user');
Meteor.subscribe('posts-by-user', someUser);
最も人気のある投稿へのサブスクリプション
- 等
これらのドキュメントはすべて、サーバー上のコレクションをposts
介してMongoDBのコレクションから取得BlogPosts
され、最終BlogPosts
的にクライアント上のコレクションに格納されます。
これで、find()
複数回呼び出す必要がある理由を理解できました。2回目はクライアントで、すべてのサブスクリプションのドキュメントが同じコレクションに含まれ、必要なものだけをフェッチする必要があるためです。たとえば、クライアントで最新の投稿を取得するには、サーバーからのクエリをミラーリングするだけです。
var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});
これにより、クライアントがこれまでに受信したすべてのドキュメント/レコード(上位の投稿とユーザーの投稿の両方)にカーソルが戻ります。(Geoffreyに感謝します)。
BlogPosts.find({})
、両方のパブリケーションをサブスクライブした後にクライアントで行うとどうなるかです。つまり、現在クライアントにあるすべてのドキュメント/レコードのカーソルが、トップの投稿とユーザーの投稿の両方に返されます。質問者がこれに混乱したSOに関する他の質問を見たことがあります。