流星中的复合集合

时间:2016-01-22 10:24:42

标签: javascript angularjs mongodb meteor ionic-framework

我正在使用this tutorial构建我自己的离子/流星/角度应用程序,我到了删除自动发布和不安全的地步,并进入出版和订阅我的数据。现在我正在努力解决以下问题:

我在lib/collections.js中的Meteor应用程序中有两个Mongo集合:

Players = new Mongo.Collection('players');
Teams = new Mongo.Collection('teams');

玩家有一个_id和一个name,一个团队有一个_id和两个(不再有)玩家:["someplayerId", "someotherPlayerId"]

在服务器上,我目前的出版物中包含以下内容server/publications.js

Meteor.publish('players', function () {
  return Players.find({});
});
Meteor.publish('teams', function() {
    return Teams.find({}, {transform: function(doc) {
        var playerOne = Players.findOne({ _id: doc.players[0]._id });
        var playerTwo = Players.findOne({ _id: doc.players[1]._id });

        doc.playerOne = playerOne;
        doc.playerTwo = playerTwo;

        return doc;
        }
    });
});

在我的client/routes.js中,我订阅了我的一个州的这些出版物,以便我可以在我的客户端代码中使用它们:

.state('tab.settings', {
  url: '/settings',
  views: {
    'tab-settings': {
      templateUrl: 'client/templates/settings.html',
      controller: 'SettingsCtrl as settings',
      resolve: {
        teams() {
          return Meteor.subscribe('teams');
        },
        players() {
          return Meteor.subscribe('players');
        }
      }
    }
  }
});

现在我想在我的代码中使用这些团队,但无论我做什么,我似乎都错过了获取这些复合数据的重点。

这会返回错误,因为变量playerOne和playerTwo未定义:

  this.helpers({
    players: () => {
      return Players.find({});  
    },
    teams: () => {
      return Teams.find({}, {transform: function(doc) {
        var playerOne = Players.findOne({ _id: doc.players[0] });
        var playerTwo = Players.findOne({ _id: doc.players[1] });

        doc.playerOne = playerOne.name;
        doc.playerTwo = playerTwo.name;

        return doc;
        }
      });
    }
  });

我的模板'client/templates/settings.html'中的某处我想使用团队,其中包含已转换的文档。怎么办呢?

2 个答案:

答案 0 :(得分:0)

很可能,您的订阅尚未准备就绪。相反,我建议您使用模板级代码来渲染团队,然后渲染该团队中的每个玩家。所以在你的出版物中:

Meteor.publish('teams', function () {
  return Teams.find({}, {
    transform: function (team) {

      // this will give you access to all the players on this team.
      team.players = Players.find({
        _id: { $in: team.players }
      }).map(player => player.name);

      return team;
    }
  });
});

现在文档将如下所示:

{
  _id: '1234',
  players: ['Jeff', 'Tim', 'Steve']
}

然后在您的模板中,您可以执行以下操作。

{{#if Template.subscriptionsReady}}
  {{#each teams}}
    // now since the team has a player array, you can use that.
    {{#each players}}
      {{this}}
    {{/each}}
  {{/each}}
{{/if}}

答案 1 :(得分:0)

好的,回答我自己的问题,我做了以下似乎按预期工作的。 Serverside我做了以下出版物:

Meteor.publish("players", function () {
  return Players.find({});
});
Meteor.publish("teams", function () {
  return Teams.find({});
});

路由器负责tabs下所有子路由的所有订阅:

  $stateProvider
    .state('tab', {
      url: '/tab',
      abstract: true,
      templateUrl: 'client/templates/tabs.html',
      resolve: {
        players() {
          return Meteor.subscribe('players');
        },
        teams() {
          return Meteor.subscribe('teams');
        }
      }
    })

当涉及客户端数据时会产生相同的“逻辑”,因为autopublish包会这样做,但现在没问题。

客户端我现在可以这样做:

  this.helpers({
    data: () => {
      return Teams.find({}, {transform: function(doc) {
        doc.playerOne = Players.findOne({ _id: doc.players[0]._id });
        doc.playerTwo = Players.findOne({ _id: doc.players[1]._id });
        return doc;
        }
      });
    }
  });

在我的模板中使用data

  <ion-item ng-repeat="team in teams.data">
    {{ team.players[0] | player_name }} and {{ team.players[1] | player_name }}
  </ion-item>

player_name是一个简单的角度滤镜:

angular
  .module('PLeague')
  .filter('player_name', player_name);

function player_name () {
  return function (player) {
    if (!player) return;
    return player.name;
  };
}

从我的问题代码改变的是Teams集合的出版物以及客户端代码处理团队的方式,即findOne获取玩家[x] ._ id。

也许这是缺失的链接。