Как получить имена пользователей, не вошедших в систему, в помощниках по сбору?

У меня есть коллекция Questions, которую я определил с помощью SimpleSchema в файле collections.js, который находится в вопросах > lib.

В этой коллекции есть поле askedBy. Это массив строк, в котором хранятся идентификаторы пользователей людей, задавших вопросы.

askedBy: {
  type: [String],
  optional: true
},

В другом файле, вопросы> сервер> publish.js, у меня есть:

Meteor.publish("questions", function () {
  questionList = Questions.find(
    {},
    {
      fields: {
        "_id": 1,
        "questiontext": 1,
        "createdAt": 1,
        "askedBy": 1,
        "slug": 1
      }
    }
  );
  return questionList;
});

Моя цель — сделать доступными имена пользователей, задавших вопрос, т. е. имена пользователей, соответствующие идентификаторам в массиве «askedBy».

Как мне это сделать?

Вещи, которые я пробовал до сих пор:

В collections.js:

Questions.helpers({
  askedByUsers: function() {
    console.log("askedBy:"); 
    console.log(Meteor.users.findOne(this.askedBy[0]));
    return Meteor.users.findOne(this.askedBy[0]);
  },

Это не удается, потому что Meteor.users, по-видимому, имеет доступ только к данным текущего пользователя, вошедшего в систему. Для всех вопросов, заданных другими пользователями, возвращается нулевое значение.

Итак, я попытался добавить это в publish.js:

Meteor.publish("allUsers", function () {
  return Meteor.users.find({},
  {
    "name": 1,
  });
});

и Meteor.subscribe("allUsers"); как для collections.js, так и для вопросов.js (у которых есть все мои помощники по шаблонам и обработчики событий). Я также изменил помощника по сбору на:

Questions.helpers({
  askedByUsers: function() {
    console.log("askedBy:"); 
    console.log(allUsers.findOne(this.askedBy[0]));
    return allUsers.findOne(this.askedBy[0]);
  },

Но даже это не работает.

Что я делаю неправильно, и как я могу получить имена пользователей, не вошедших в систему?

редактировать: на всякий случай это важно - структура папок

├── client
├── modules
│   ├── admin
└── questions
    ├── client
    │   ├── questions.html
    │   └── questions.js
    ├── lib
    │   ├── collections.js
    │   └── methods.js
    └── server
        └── publish.js
...

person Samudra    schedule 28.02.2016    source источник


Ответы (1)


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

Один из подходов заключается в том, чтобы подписаться на всех пользователей. Это не будет масштабироваться, но должно дать вам результат. Давайте исправим приведенный выше код, чтобы он работал.

Когда вы публикуете allUsers, он публикует пользовательские документы в Meteor.users на клиенте, а не в коллекции под названием allUsers. Кроме того, я предполагаю, что askedByUsers должен возвращать массив или курсор пользователей, а не только одного пользователя. Вы можете переписать свой помощник следующим образом:

Questions.helpers({
  askedByUsers: function () {
    return Meteor.users.find({ _id: { $in: this.askedBy } });
  },
});

Затем в шаблоне вы можете сделать что-то вроде:

<template name='question'>
  <ul>
  {{#each askedByUsers}}
    <li>{{name}}</li>
  {{/each}}
  </ul>
</template>

Хорошо, что вы применили filter к своему allUsers издателю. Я собираюсь предположить, что у пользователей на самом деле есть поле name, а не profile.name или что-то еще. При необходимости исправьте код.

Как только вы заработаете, ознакомьтесь с моим ответом на этот вопрос, чтобы узнать, как опубликовать соединение (реактивное или иное), чтобы избежать публикации всех пользователей на клиенте.

person David Weldon    schedule 28.02.2016
comment
Я попробовал это, но это вернуло меня к моей первоначальной проблеме возможности доступа только к пользователю, который вошел в систему, а не к другим идентификаторам пользователей в массиве. Проблема в том, что я определяю этот хелпер коллекции в папке lib › collections.js? Публикация.js находится в папке сервера, а collections.js, похоже, не знает об опубликованных «allUsers»? Как подписаться в collections.js на опубликованных allUsers? - person Samudra; 29.02.2016
comment
Убедитесь, что вызов Meteor.subscribe находится где-то в каталоге client. В качестве альтернативы вы можете заменить Meteor.publish("allUsers", function () { на Meteor.publish(null, function () {, и это автоматически подпишется для всех ваших пользователей без необходимости вызова Meteor.subscribe. - person David Weldon; 29.02.2016
comment
Это решило это! (Я не знаю, когда я это закомментировал - это было глупо с моей стороны :) ) Я не уверен, что ясно понял, что раньше делал неправильно - не могли бы вы помочь, если я понял неправильно? Прямо сейчас я создаю новую публикацию «allUsers», а затем подписываюсь на нее на клиенте. Это открывает большую версию Meteor.users для всего моего приложения? Затем, когда я вызываю Meteor.users.find в моем помощнике askByUsers, он может получить доступ ко всему этому расширенному набору? Я уверен, что это создаст проблемы позже, когда у меня будут настоящие пользователи - это лучший подход для этого? - person Samudra; 29.02.2016
comment
Или мне следует более серьезно взглянуть на Publish-Composite? - person Samudra; 29.02.2016
comment
Btw, большое спасибо за вашу помощь! Искренне оцените это! - person Samudra; 29.02.2016
comment
Ваше резюме точно. Когда вы подписываетесь на какой-то набор документов, сервер передает документы клиенту (которые затем кэшируются в minimongo). Как только это произойдет, клиент сможет получить доступ к документам локально. Теперь, когда у вас что-то работает, вам следует подумать об использовании другого подхода, потому что публикация имен всех ваших пользователей не будет масштабироваться (если у вас много пользователей). Альтернативы включают широкий спектр реактивных и нереактивных решений с различными характеристиками производительности. На данный момент я бы выбрал публикацию-композит и вернусь позже, если это необходимо. - person David Weldon; 29.02.2016
comment
Большое спасибо за Вашу помощь! Глядя на Publish-Composite сейчас. Хорошего дня! - person Samudra; 29.02.2016