2016-11-30 15 views
1

Я делаю игру; игроки формируют лиги и делают конкурирующие прогнозы. Лига, выглядит следующим образом:Meteor/Mongodb - массивы, субдокументы и перекрывающиеся подписки

{ leagueName: "Premier League", 
players:[ 
     {name: "Goodie", secretPrediction: "abc"}, 
     {name: "Baddie", secretPrediction: "def"} 
     ] } 

Для каждого игрока, я должен опубликовать клиенту имена всех игроков в лиге, но только их собственный секрет предсказания. Так сверху, если Goodie авторизован, документ по мини-Монго должно быть:

{ leagueName: "Premier League", 
    players:[ 
      {name: "Goodie", secretPrediction: "abc"}, 
      {name: "Baddie"} 
      ] } 

Чтобы сделать это, у меня есть два издания - один, чтобы получить весь документ Лиги, но исключая все тайные предсказания, и один чтобы получить поддоку текущего игрока в массиве игроков , включая ее секретное предсказание. Мои публикации:

// Publish whole players array excluding secretPrediction 
Leagues.find({"players.name": "Goodie"}, {fields: {"players.secretPrediction": 0}}) 

// Publish the whole Goodie item in the players array and nothing else 
Leagues.find({"players.name": "Goodie"}, {fields: {players: {$elemMatch: {name: "Goodie"}}}}) 

Проблема заключается в том, что, когда я подписываюсь на как вышеуказанные публикации, я не получаю документ, который я хочу - секрет предсказания исключается даже со второй публикации. (Самостоятельно, публикации ведут себя, как и ожидалось, это только тогда, когда я подписываюсь на обоих.)

Теперь я понимаю, из this answer, что две публикации должны быть «слиты» на клиенте

Дауна уровень полей верхнего уровня, Meteor позаботится о том, чтобы выполнить объединение между документами, так что подписки могут перекрываться - публиковать функции, которые отправляют разные поля верхнего уровня для работы клиента бок о бок и на клиенте, документ в коллекция будет объединением двух наборов полей.

Поэтому у меня есть два главных вопроса (и хорошо сделано/спасибо за то, что это далеко!):

  1. Является ли объединение документов не происходит, потому что я не имеем дело с полей верхнего уровня? Есть ли способ обойти это?
  2. Я об этом совершенно неправильно? Есть ли лучший способ получить результаты, которые я хочу?
+1

1. Правильно. 2. Вы можете попытаться опубликовать его в виртуальную коллекцию только для клиента. – MasterAM

ответ

2

Не могли бы вы перестроить документ данных, чтобы вы могли использовать один запрос, например.

{ leagueName: "Premier League", 
players:[ 
     {name: "Goodie"}, 
     {name: "Baddie"} 
     ] 
playerPredictions:[ 
     {name: "Goodie", secretPrediction: "abc"}, 
     {name: "Baddie", secretPrediction: "def"} 
     ] 
} 

Таким образом, можно было бы в одном запросе, чтобы вернуть все игроки и только playerPrediction для данного человека.

+0

Принимая это как ответ, потому что я думаю, что это самый простой и быстрый способ получить результат Мне нужно – rubie

3
  1. Да, сливающиеся несколько подписок метеора работает только с полями верхнего уровня, он упоминается в Метеор документы: Meteor.subscribe

  2. Я не могу сказать, что вы направляетесь в неправильном направлении, это действительно зависит от вашей ситуации, какие функции вы хотите помочь. Только говорить о себе, я бы отделил вышеупомянутую сборку от двух отдельных коллекций. Потому что игроки могут присоединиться к многим лигам, а в лигах может быть много игроков, поэтому их отношение - many-to-many (n-n).Для такого рода отношения, мы должны разделить их на две коллекции и использовать associative table, чтобы отразить их отношение

Так что в вашем случае, я бы:

коллекция

лиги:

[{ 
    _id: 'league1', 
    name: 'League 1', 
    // ... 
}] 

коллекция игрока:

[{ 
    _id: 'player1', 
    name: 'Player 1', 
    // ... 
}] 

коллекция League2Player:

[{ 
    _id: 'league1palyer1', 
    playerId: 'player1', 
    leagueId: 'league1', 
    secretPrediction: 'abc', 
    // ... 
}] 
+0

Хорошее место в документах - я не видел этого комментария. И - «Мы надеемся снять это ограничение в будущем выпуске». - надеюсь скоро... – rubie