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"}}}})

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

Теперь я понимаю из этого ответа, что две публикации должны быть "объединены" на клиенте

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

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

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

2 ответа

Решение

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

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

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

  1. Да, объединение нескольких подписок Meteor работает только с полями верхнего уровня, это упоминается в документации Meteor: Meteor.subscribe

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

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

Коллекция Лиги:

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

Коллекция игроков:

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

League2Player коллекция:

[{
  _id: 'league1palyer1',
  playerId: 'player1',
  leagueId: 'league1',
  secretPrediction: 'abc',
  // ...
}]
Другие вопросы по тегам