コレクション、出版物、購読はMeteorのトリッキーな領域であり、用語の混乱によって増幅されることがある頻繁な混乱を避けるために、ドキュメントでより詳細に説明することができます。
これがSachaGreif(DiscoverMeteorの共著者)で、出版物と購読について1つのスライドで説明しています。
find()
を呼び出す必要がある理由を正しく理解するには Meteorでコレクション、パブリケーション、サブスクリプションがどのように機能するかを何度も理解する必要があります:
-
コレクションはMongoDBで定義します。 Meteorはまだ関与していません。これらのコレクションには、データベースレコードが含まれています (MongoとMeteorの両方で「ドキュメント」とも呼ばれますが、「ドキュメント」はデータベースレコードよりも一般的です。たとえば、更新仕様やクエリセレクタもドキュメントです-
field:valueを含むJavaScriptオブジェクトコード> ペア)。
-
次に、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()
callは、クライアントをレコードセットにサブスクライブします -サーバーコレクションのレコードのサブセット(例:最新の100件のブログ投稿)。各レコードのフィールドのすべてまたはサブセット(例:title
のみ) およびdate
)。 Minimongoは、受信レコードを配置するコレクションをどのようにして知るのですか?コレクションの名前はcollection
になります 公開ハンドラーのadded
で使用される引数 、変更コード> 、および
削除
コールバック、またはそれらが欠落している場合(ほとんどの場合)、サーバー上のMongoDBコレクションの名前になります。
レコードの変更
これは、Meteorが非常に便利な場所です。クライアントでMinimongoコレクションのレコード(ドキュメント)を変更すると、Meteorはそれに依存するすべてのテンプレートを即座に更新し、サーバーに変更を送り返します。変更をMongoDBに保存し、そのドキュメントを含むレコードセットにサブスクライブしている適切なクライアントに変更を送信します。これはレイテンシー補正と呼ばれます Meteorの7つのコア原則の1つです。
複数のサブスクリプション
さまざまなレコードを取得する多数のサブスクリプションを持つことができますが、 _id
に基づいて、サーバー上の同じコレクションからのものである場合、それらはすべてクライアント上の同じコレクションになります。 。これは明確に説明されていませんが、Meteorドキュメントによって暗示されています:
レコードセットをサブスクライブすると、サーバーにレコードをクライアントに送信するように指示されます。クライアントは、これらのレコードを
collection
と同じ名前でローカルのMinimongoコレクションに保存します 公開ハンドラーのadded
で使用される引数 、変更コード> 、および
削除
コールバック。 Meteorは、一致するコレクション名を使用してクライアントでMongo.Collectionを宣言するまで、着信属性をキューに入れます。
説明されていないのは、しないときに何が起こるかです。 明示的にadded
を使用する 、変更コード> および
削除
、またはハンドラーを公開します-これはほとんどの場合です。この最も一般的なケースでは、コレクション引数は(当然のことながら)ステップ1でサーバー上で宣言したMongoDBコレクションの名前から取得されます。ただし、これは、異なる名前の異なるパブリケーションとサブスクリプションを持つことができ、すべてのレコードは、クライアントの同じコレクションに入れられます。 トップレベルフィールドのレベルまで 、Meteorは、サブスクリプションが重複する可能性があるように、ドキュメント間のセットユニオンを実行するように注意します-異なるトップレベルフィールドをクライアントワークに並べて送信する関数を公開し、クライアントでは、コレクション内のドキュメントは2つのユニオンになりますフィールドのセット。
例:クライアント上の同じコレクションを埋める複数のサブスクリプション
BlogPostsコレクションがあります。これは、サーバーとクライアントの両方で同じように宣言しますが、動作は異なります。
BlogPosts = new Mongo.Collection('posts');
クライアントでは、 BlogPosts
からレコードを取得できます:
-
最新の10件のブログ投稿へのサブスクリプション
// server Meteor.publish('posts-recent', function publishFunction() { return BlogPosts.find({}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe('posts-recent');
-
現在のユーザーの投稿へのサブスクリプション
// 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);
-
最も人気のある投稿へのサブスクリプション
- など
これらのドキュメントはすべてposts
からのものです BlogPosts
を介したMongoDBのコレクション サーバー上のコレクションであり、最終的に BlogPosts
になります クライアントのコレクション。
これで、 find()
を呼び出す必要がある理由を理解できました。 2回目-すべてのサブスクリプションからのドキュメントが同じコレクションに含まれることになり、気になるドキュメントのみをフェッチする必要があるため、2回目はクライアントに存在します。たとえば、クライアントで最新の投稿を取得するには、サーバーからクエリをミラーリングするだけです。
var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});
これにより、クライアントがこれまでに受信したすべてのドキュメント/レコード(上位の投稿とユーザーの投稿の両方)にカーソルが戻ります。 (Geoffreyに感謝します。)