Meteor-publish возвращает больше строк, чем требуется от MongoDB

У меня есть коллекция:

{
    "_id" : "SeGtBvCT7ojF2v5x9",
    "teamId" : "d74JJ9s5k6tijeQaz",
    "userScores" : [ 
        {
            "userId" : "6ghphqzx9GFnvKYKY",
            "scores" : 10,
            "addedAt" : ISODate("2019-02-04T06:37:06.387Z")
        }, 
        {
            "userId" : "56ghp45hqzx9G2dda",
            "scores" : 1,
            "addedAt" : ISODate("2019-02-04T06:37:19.105Z")
        }, 
        {
            "userId" : "wrr3422fwefx6fFGs",
            "scores" : 4,
            "addedAt" : ISODate("2019-02-04T06:37:44.005Z")
        }
    ]
}

Мне нужно вернуть «userScores» для одного teamId и текущего идентификатора пользователя (this.userId). Поэтому я сделал этот метод публикации.

Meteor.publish('scoresTeamByUser', function(teamId) {
  return Scores.find(
      { teamId }, 
      { userScores: { $elemMatch: { userId: this.userId } } }
  );
});

Но в приложении meteor/react я получаю (this.props.receivedScores) весь документ со всеми строками в «userScores».

export default withTracker(props => {
    const scoresSubscription = Meteor.subscribe('scoresTeamByUser', props.teamId);
    return {
        receivedScores: Scores.findOne(),
        scoresLoaded: scoresSubscription.ready()
    };
})(GiveScores);

Как получить только данные для одной команды и одного пользователя, который поставил оценку? Спасибо :)


person podeig    schedule 04.02.2019    source источник


Ответы (2)


Я проверил ваш запрос, и он работает нормально и возвращает только один объект массива userScores, который соответствует userId.

Вам нужно использовать fields для фильтрации полей, которые вы хотите опубликовать.

Meteor.publish('scoresTeamByUser', function(teamId) {
  return Scores.find(
      { teamId }, 
      { fields: { userScores: { $elemMatch: { userId: this.userId }}} }
  );
});

Причина, по которой вы получаете все объекты в массиве userScores, заключается в том, что у вас должна быть другая подписка, которая публикует всю запись. Вы можете проверить это по console.log(Scores.findOne({ props.teamId})) перед тем, как подписаться на scoresTeamByUser публикацию.

Таким образом, вам нужно либо найти эту публикацию и ограничить ее публикацией только оценок текущего пользователя, либо в вашей текущей подписке вы должны отфильтровать данные по запросу на стороне клиента, как показано ниже.

export default withTracker(props => {
    const scoresSubscription = Meteor.subscribe('scoresTeamByUser', props.teamId);
    return {
        receivedScores: Scores.findOne({ teamId: props.teamId }, 
  { userScores: { $elemMatch: { userId: Meteor.userId() } }),
        scoresLoaded: scoresSubscription.ready()
    };
})(GiveScores);

person Sudheer Jami    schedule 07.02.2019
comment
Я это попробую! Вернусь с результатами. Спасибо! :) - person podeig; 07.02.2019
comment
Привет еще раз. Я не публикую коллекцию Scores в других местах. Поэтому я не понимаю, почему это работает так. ??? Любые идеи? - person podeig; 12.02.2019
comment
Подобный пример я нахожу здесь docs.mongodb.com/manual/reference/ operator/projection/elemMatch но почему я работаю в Robo 3T, а не в Meteor? - person podeig; 12.02.2019
comment
Извини, друг, мой плохой. Обновить ответ - person Sudheer Jami; 13.02.2019
comment
Да! Это было именно то, что я искал. Meteor добавляет «поля» перед $elemMatch. Теперь это работает. Спасибо! :) - person podeig; 13.02.2019

Похоже, вы хотите что-то вроде этого.

Meteor.publish('scoresTeamByUser', function(teamId) {

    const teamScores = Scores.find({ teamId: teamId });

    const userScore = Scores.find(
    {'userScores.userId': this.userId}, {'userScores.$': 1});

    return [teamScores, userScore];
});
person Derrick Gremillion    schedule 04.02.2019
comment
На самом деле я не вижу, как это может помочь. - person podeig; 07.02.2019