22

Meteor を使用して、同じサーバー側データベース コレクションを共有するさまざまなクライアント側コレクションをどのように処理するのが最善かを考えています。次の例を考えてみましょう:Userコレクションがあり、クライアント側に友人であるユーザーのリストがあり、ユーザー データベース全体に対してクエリを実行し、クエリに一致するユーザー名のリストを返す検索機能があります。 .

Publish サーバー側メソッドでは、同じコレクションに対して異なるドキュメント セットを返す 2 つのクエリがあります。このデータは、クライアント側の 2 つの別々のコレクションに入れる必要がありますか? それとも、両方のクエリに一致するすべてのユーザー ドキュメントを同じコレクションにする必要がありますか? 後者の場合、サーバー側とクライアント側の両方のクエリに使用されるコードを複製しますか?

サーバー上:

Meteor.publish('searchResults', function(query){
  var re = new RegExp(query, 'i')
  return Users.find({ 'name' : {$regex: re}})
})

クライアントで:

Session.set('searchQuery', null)

Meteor.autosubscribe(function(){
  Meteor.subscribe('searchResults', Session.get('searchQuery'))
})

Template.search.events = {
  'keyup #user-search' : function(e){
    Session.set('searchQuery', e.target.value)
  }
}

_.extend(Template.search, {

  searchResults: function() {
    var re = new RegExp(Session.get('searchQuery'), 'i')
    return Users.find({ 'name' : {$regex: re}})
  }
})

これはもっともらしい解決策のように思えますが、最適な解決策ではありません。複数のサーバー側コレクションからの検索結果で構成される新しいクライアント側コレクションを作成したい場合はどうすればよいですか?

4

3 に答える 3

24

共有エリア:

function getSearchUsers(query) {
  var re = new RegExp(query, "i");
  return Users.find({name: {$regex: re}});
}

function getFriendUsers() {
  return Users.find({friend: true});    // or however you want this to work
}

サーバー上:

Meteor.publish("searchUsers", getSearchUsers);
Meteor.publish("friendUsers", getFriendUsers);

クライアントで:

Template.search.onCreated(function () {
   var self = this;
   self.autorun(function () {
     self.subscribe("searchUsers", Session.get("searchQuery"));
   });
});

Template.friends.onCreated(function () {
  this.subscribe("friendUsers");
});

Template.search.helpers({
  searchResults: function () {
    return getSearchUsers(Session.get("searchQuery"));
  }
});

Template.friends.helpers({
  results: function () {
    return getFriendUsers();
  }
});

ここで重要なことは、データがネットワーク経由で転送されているときに舞台裏で何が起こっているかは明らかではないということです。Meteor は、サーバー上のさまざまなクエリで一致したレコードを結合 し、これをクライアントに送信するようです。次に、クライアントが同じクエリを再度実行して、それらを分割します。

たとえば、サーバー側のコレクションに 20 のレコードがあるとします。次に、2 つのパブリッシュがあります。1 つ目は 5 つのレコードに一致し、2 つ目は 6 つに一致し、そのうち 2 つが同じです。Meteor は 9 つのレコードを送信します。次にクライアントで、サーバーで実行したのとまったく同じクエリを実行すると、それぞれ 5 レコードと 6 レコードになるはずです。

于 2012-10-25T20:29:37.677 に答える
10

パーティーには少し遅れましたが、1 つのサーバー コレクションのサブセットに対して、クライアント上で個別のコレクションを実際に持つ方法があります。entitiesこの例では、 とに関する情報を保持するというサーバー コレクションがありpolygonsますrectangles
共有コード (lib フォルダー):

// main collection (in this example only needed on the server
Entities = new Meteor.Collection('entities');
// partial collections
RectEntities = new Mongo.Collection('rectEntities');
PolyEntities = new Mongo.Collection('polyEntities');

クライアントコード:

// this will fill your collections with entries from the Entities collection
Meteor.subscribe('rectEntities');
Meteor.subscribe('polyEntities');

サブスクリプションの名前は、パブリケーションの名前と一致する必要があることに注意してください (ただし、コレクション自体の名前ではありません)
サーバー コード:

Meteor.publish('rectEntities', function(){
    Mongo.Collection._publishCursor( Entities.find({shapeType: 'rectangle'}), this, 'rectEntities'); 
    this.ready();
});

Meteor.publish('polyEntities', function(){
    Mongo.Collection._publishCursor( Entities.find({shapeType: 'polygon'}), this, 'polyEntities'); 
    this.ready();
});

_publishCursor()!を使用したはるかに簡単なソリューションを提供してくれた user728291 に感謝します。
関数の 3 番目の引数は、_publishCursor()新しいコレクションの名前です。
ソース: http://docs.meteor.com/#/full/publish_added

于 2014-12-18T10:12:50.933 に答える