1

元のドキュメントへのアクセスを必要とする変換を適用した後、公開機能からクライアントに送信されるフィールドの数を制限する必要があります。

私は基本的に、潜在的に巨大な配列をクライアントに送信することを避け、一連のチェックを実行して、処理する適切なオブジェクトを返すようにしています。

Heres私が今持っている機能です - それは機能しますが、私が望む方法ではなく、基本的に機能を観察するために与えられたフィールドを制限します。観察/変換後に投影を追加する方法はありますか?

Meteor.publish('network', function() {

  var self = this;

  // get the user values initially
  var user = Meteor.users.findOne(self.userId);
  var followingUsers = user.following ? user.following.users || [] : [];
  var followingChannels = user.following ? user.following.channels || [] : [];

  var transformMedia = function(doc) {
    // get the user each time to keep this publication reactive
    votesUp = doc.votes ? doc.votes.up || [] : [];
    votesDown = doc.votes ? doc.votes.down || [] : [];
    favourites = doc.votes ? doc.votes.favourites || [] : [];

    doc.userActions = {
      votedUp: _.contains(votesUp, doc._id) ? 1 : 0,
      votedDown: _.contains(votesDown, doc._id) ? 1 : 0,
      isFavourite: _.contains(favourites, doc._id) ? 1 : 0,
      played: _.contains(doc.played, self.userId) ? 1 : 0,
    };

    return doc;
  };

  var networkQuery = Media.find({
    $and: [
    {
        $and: [
          {processedAt: { $exists: true} },
          {processedStatus: 'successful'},
          {publishStatus: 'published'}
        ]
      },
      {
        // if created by this user, user they follow or channels they subscribe to
        $or: [
          {createdBy: self.userId },
          {createdBy: { $in: followingUsers} },
          {channels: { $in: followingChannels} },
        ]
      }

      // TODO : add not banned or trashed once implemented
    ]
  }, mediaModifiers).observe({
    added: function(doc) {
      self.added('media', doc._id, transformMedia(doc));
    },
    changed: function(doc, oldDoc) {
      self.changed('media', doc._id, transformMedia(doc));
    },
    removed: function(doc) {
      self.removed('media', doc._id, transformMedia(doc));
    },
  });

  self.onStop(function() {
    networkQuery.stop();
  });

  self.ready();

});
4

1 に答える 1

1

私はかつて同様の問題を抱えていました。+カスタム関数を使用して対処しcursor.observe()(あなたが行ったように)_.pick()、不要なフィールドをフィルタリングするために a を追加しました。例として、この公開コードを見てください (docToPublish特にホワイト リストの部分)。

var self = this;

// Modify the document we are sending to the client.
function filter(doc) {
  var length = doc.item.length;

  // White list the fields you want to publish.
  var docToPublish = _.pick(doc, [
      'someOtherField'
  ]);

  // Add your custom fields.
  docToPublish.itemLength = length;

  return docToPublish;                        
}

var handle = myCollection.find({}, {fields: {item:1, someOtherField:1}})
            // Use observe since it gives us the the old and new document when something is changing. 
            // If this becomes a performance issue then consider using observeChanges, 
            // but its usually a lot simpler to use observe in cases like this.
            .observe({
                added: function(doc) {
                    self.added("myCollection", doc._id, filter(doc));
                },
                changed: function(newDocument, oldDocument)
                    // When the item count is changing, send update to client.
                    if (newDocument.item.length !== oldDocument.item.length)
                        self.changed("myCollection", newDocument._id, filter(newDocument));
                },
                removed: function(doc) {
                    self.removed("myCollection", doc._id);                    
                });

self.ready();

self.onStop(function () {
  handle.stop();
});

このコードは、上記のトピックに対する @datacarl の回答から借用したものです。

複数のサーバーにスケールアップする場合、このアプローチの短所は、各サーバーがcursor.observe()機能を実行する必要があることです。

また、パブリケーションの準備を整え、パブリケーションの最後にオブザーバーを破棄することも忘れていました (すべてのパブを貼り付けていないことが原因である可能性があります)。次のようになります。

self.ready();
self.onStop(function () {
  networkQuery.stop();
});
于 2015-07-29T17:02:12.203 に答える