Meteor.publish: опубликовать коллекцию, которая зависит от другой коллекции.

У меня есть функция публикации следующим образом:

Meteor.publish('tasks', function (name) {
    var project = Projects.findOne({name: name});

    return Tasks.find({projectId: project._id});
});

Теперь предположим, что в какой-то момент в проекты были внесены изменения, в результате чего приведенный выше Projects.findOne возвращает другой проект, и поэтому Tasks.find вернет другие задачи. Однако изменения, внесенные в проекты, не приводят к повторной публикации задач.

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


person Jeanluca Scaljeri    schedule 16.10.2014    source источник
comment
Почему вы должны переиздавать его? Курсор, который вы возвращаете, — это Задачи. Если ваши Задачи изменены, они должны быть автоматически опубликованы.   -  person waitingkuo    schedule 16.10.2014
comment
На самом деле я искал ответ без использования какого-либо плагина. Например, ответ в другом посте предлагает использовать meteor-publish-with-relations Последний раз этот проект модифицировался год назад. Вероятно, в какой-то момент это вызовет у меня те же проблемы, что и сейчас с reactivePublish.   -  person Jeanluca Scaljeri    schedule 16.10.2014
comment
на что подписываешься? Меняется ли имя реактивно в вашей подписке?   -  person Christian Fritz    schedule 16.10.2014
comment
хороший момент, это было не очень ясно. Я улучшил вопрос   -  person Jeanluca Scaljeri    schedule 16.10.2014
comment
Я не уверен, что это сработает (поэтому я не публикую его как ответ), но вы пытались обернуть findOne в Tracker.autorun?   -  person Christian Fritz    schedule 16.10.2014
comment
Никогда не слышал о Tracker, кажется, это замена Deps, не так ли? Кроме того, Трекер работает только на клиенте!   -  person Jeanluca Scaljeri    schedule 16.10.2014
comment
Вы сможете сделать это, используя добавленный/измененный/удаленный интерфейс для publish. См. второй, длинный пример в документации для publish.   -  person Christian Fritz    schedule 17.10.2014


Ответы (2)


Обзор

На момент написания этой статьи реактивные соединения остаются нерешенной проблемой. Полный обзор см. в реактивных соединениях в Meteor.

Рекомендации

Я настоятельно не рекомендую использовать observeChanges напрямую. Это невероятно сложно сделать правильно, и легко получить утечку памяти. Если вы мне не верите, посмотрите это видео на EventedMind. Это заставит ваши глаза кровоточить.

Для этой проблемы существует несколько пакетных решений. руководство по метеорам рекомендует publish-composite.

Если идея использования пакетного решения кажется вам неприемлемой, внимательно изучите раздел Присоединение к клиенту на странице Реактивные соединения в Meteor. Это чисто, но требует большего ожидания со стороны пользователя. Также см. мой пост о объединениях шаблонов, если вы предпочитаете активировать свои подписки на уровне шаблона.

person David Weldon    schedule 17.10.2014
comment
Проблема с доступными пакетами заключается в том, что у них есть проблемы или нет документации (не говоря уже о модульных тестах). Так что пока это часть метеора буду исправлять на клиенте. Спасибо! - person Jeanluca Scaljeri; 17.10.2014
comment
Код в статье Reactive Joins in Meteor, кажется, устарел из-за изменений в API железного маршрутизатора. Есть ли способ получить фрагмент кода, который работает в текущих версиях? - person RoyalTS; 29.01.2015
comment
Да, я хотел обновить этот ответ. Спасибо, Дэн. - person David Weldon; 19.06.2015

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

Установите пакет, вызвав meteor add peerlibrary:reactive-publish.

С добавленным пакетом вы можете просто сделать:

Meteor.publish('tasks', function (name) {
    this.autorun(function (computation) {
        var project = Projects.findOne({name: name}, {fields: {_id: 1}});

        return Tasks.find({projectId: project._id});
    });
});

Именно так, как вы ожидаете. :-)

Важная часть — ограничить поля в первом запросе только _id, иначе autorun будет перезапускаться каждый раз при изменении любого поля документа проекта. Вы этого не хотите.

person Mitar    schedule 03.10.2015
comment
Большое спасибо, что поделились! - person Jeanluca Scaljeri; 05.10.2015
comment
у меня не работает, возможно в Meteor 1.3 его убрали - person Ziarno; 08.04.2016
comment
Вы должны использовать пакет, указанный выше. - person Mitar; 09.04.2016