Meteor发布:子文档的秘密字段

时间:2014-08-06 19:28:15

标签: mongodb meteor

我有以下带有子文档数组的集合:

{
_id: 
players: [
 {
 _id: 1
 answer
 score:
 }, 
 {
 _id: 2
 answer:
 score:
 }]
}

我想执行发布功能,以便排除其他玩家的现场回答。即玩家1应该在他的本地最小的这个文档:

{
_id: 
players: [
 {
 _id: 1
 answer
 score:
 }, 
 {
 _id: 2
 score:
 }]
} 

我试过这样的事情:

Meteor.publish('game', function (id) {
return Game.find({_id: id}, {players.player_id: 0});
 });

但我不知道如何只删除特定玩家的现场答案。

2 个答案:

答案 0 :(得分:1)

我讨厌在MongoDB中使用这样的数组。就个人而言,我会使用另一个集合GamePlayers为每个游戏中的每个玩家提供一个文档,例如

Game ({ _id: g1 })

GamePlayers ({ _id: 0, gameId: g1, playerId: p1, answer: x, score: 0 });
GamePlayers ({ _id: 1, gameId: g1, playerId: p2, answer: y, score: 5 });

这会让事情变得更容易。

但实际上在这里回答你的问题是一种方法。我确信有一种更优雅的方式可以做到这一点,但我再次在MongoDB中使用数组,所以我想不到它。

由于meteor发布了有效的observeChanges函数,我们可以做到这一点:

注意:这假设player数组中每个玩家的_id等于用户的Meteor.userId(),如果不是那么你将需要提供playerId作为发布的另一个参数以及gameId和更改作为适当的。

我还假设您的游戏集合被称为“游戏” Games = new Meteor.Collection("games")

Meteor.publish('game', function(gameId) {
  var self = this;

  var handle = Games.find(gameId).observeChanges({
    added: function(id, fields) {
      self.added("games", id, removeSecretPlayerInfo(fields, self.userId));
    },
    changed: function(id, fields) {
      self.changed("games", id, removeSecretPlayerInfo(fields, self.userId));
    },
    removed: function(id) {
      self.removed("games", id);
    }
  });

  self.ready();

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

//this function takes all the fields that would be sent to the client,
//goes through the player array and if the player's id _id is not equal to
//the id of the user making the subscription we remove the answer from the array
//before sending it to them
var removeSecretPlayerInfo = function(fields, playerId) {
  if (fields.players) {
    for (var i = 0; i < fields.players.length; i++) {
      if (fields.players[i]._id !== playerId)
        delete fields.players[i].answer;
    }
  }
  return fields;
}

答案 1 :(得分:0)

查询子字段时需要使用引号。另请注意,要查找的第二个参数位于options对象上,该对象应具有属性fields

return Game.find({_id: id}, {fields: {'players.answer': 0}});