【问题标题】:Publish documents in a collection to a meteor client depending on the existence of a specific document in another collection (publish-with-relations)根据另一个集合中特定文档的存在,将集合中的文档发布到流星客户端(publish-with-relations)
【发布时间】:2023-03-15 04:35:01
【问题描述】:

我有两个收藏

  1. 优惠(相关字段:_id
  2. ShareRelations(相关字段:receiverIdofferId

我只想向登录的用户发布已分享给他的优惠。

实际上,我是通过使用一个辅助数组 (visibleOffers) 来实现的,我通过循环填充每个 ShareRelations 并稍后在 Offers.find 上将此数组用作 $in 选择器。

我想知道这是否可能是 meteor 方式,或者我是否可以使用更少和/或更漂亮的代码?

我发布优惠的实际代码如下:

Meteor.publish('offersShared', function () {
  // check if the user is logged in
  if (this.userId) {
    // initialize helper array
    var visibleOffers = [];
    // initialize all shareRelations which the actual user is the receiver
    var shareRelations = ShareRelations.find({receiverId: this.userId});
    // check if such relations exist
    if (shareRelations.count()) {
      // loop trough all shareRelations and push the offerId to the array if the value isn't in the array actually
      shareRelations.forEach(function (shareRelation) {
        if (visibleOffers.indexOf(shareRelation.offerId) === -1) {
          visibleOffers.push(shareRelation.offerId);
        }
      });
    }
    // return offers which contain the _id in the array visibleOffers
    return Offers.find({_id:  { $in: visibleOffers } });
  } else {
    // return no offers if the user is not logged in
    return Offers.find(null);
  }
});

此外,实际解决方案的缺点是,如果正在创建新的共享关系,客户端上的 Offers 集合不会立即更新为新可见的优惠(阅读:需要重新加载页面。但我不是确定是因为这个发布方法还是因为其他代码,这个问题不是主要的,因为这个问题)。

【问题讨论】:

  • 虽然这是关系数据库中的常见模式,但要以 Meteor 方式实现这一点仍然有些棘手。你应该看看这个视频:eventedmind.com/posts/…
  • 也许对数据进行非规范化并在 Offer 集合中添加 receiversId 数组更简单?

标签: meteor publish


【解决方案1】:

您正在寻找的是反应式联接。您可以通过直接在发布功能中使用观察来完成此操作,或者使用库为您完成此操作。 Meteor core 预计在某个时候会有join library,但在那之前我建议使用publish-with-relations。查看文档,但我认为您想要的发布功能如下所示:

Meteor.publish('offersShared', function() {
  return Meteor.publishWithRelations({
    handle: this,
    collection: ShareRelations,
    filter: {receiverId: this.userId},
    mappings: [{collection: Offers, key: 'offerId'}]
  });
});

这应该会被动地为用户发布所有ShareRelations,以及所有关联的Offers。希望两者的发布都不会成为问题。

PWR 是一个非常合法的包——我们中的一些人在生产中使用它,Tom Coleman 为它做出了贡献。我要提醒您的唯一一件事是,在撰写本文时,大气中的当前版本(v0.1.5)存在一个错误,该错误将导致相当严重的内存泄漏。在遇到问题之前,请参阅我的blog post,了解如何运行更新的本地副本。

2/5/14 更新:

发现流星博客在reactive joins 上有一篇很棒的帖子,我强烈推荐阅读。

【讨论】:

    【解决方案2】:

    这样做的方法是使用observeChanges() 沿着这个问题的思路。仍在试图弄清楚如何让这一切适用于我的示例,请参阅Meteor, One to Many Relationship & add field only to client side collection in Publish?

    【讨论】:

      【解决方案3】:

      您可以使用reactive-publish 包(我是作者之一):

      Meteor.publish('offersShared', function () {
        // check if the user is logged in
        if (this.userId) {
          this.autorun(function (computation) {
            // initialize helper array
            var visibleOffers = [];
            // initialize all shareRelations which the actual user is the receiver
            var shareRelations = ShareRelations.find({receiverId: this.userId}, {fields: {offerId: 1}});
            // loop trough all shareRelations and push the offerId to the array if the value isn't in the array actually
            shareRelations.forEach(function (shareRelation) {
              if (visibleOffers.indexOf(shareRelation.offerId) === -1) {
                visibleOffers.push(shareRelation.offerId);
              }
            });
            // return offers which contain the _id in the array visibleOffers
            return Offers.find({_id:  { $in: visibleOffers } });
          });
        } else {
          // return no offers if the user is not logged in
          return Offers.find(null);
        }
      });
      

      您可以简单地将现有的非响应式代码包装到 autorun 中,它就会开始工作。请注意准确查询您查询的字段,因为如果您查询所有字段,则autorun 将在ShareRelations 的任何字段更改时重新运行,而不仅仅是offerId

      【讨论】:

        猜你喜欢
        • 2016-09-22
        • 2023-01-31
        • 1970-01-01
        • 2016-02-22
        • 2015-07-03
        • 1970-01-01
        • 2014-12-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多