Понимание Метеор Публикация / Подписка
у меня есть простое приложение, которое показывает список Projects. Я удалил autopublish пакет, так что я не посылаю все клиенту.
<template name="projectsIndex">
{{#each projects}}
{{name}}
{{/each}}
</template>
, когда autopublish был включен, это будет отображать все проекты:
if Meteor.isClient
Template.projectsIndex.projects = Projects.find()
С его удалением, я должен дополнительно сделать:
if Meteor.isServer
Meteor.publish "projects", ->
Projects.find()
if Meteor.isClient
Meteor.subscribe "projects"
Template.projectsIndex.projects = Projects.find()
Итак, правильно ли говорить, что клиентская сторона find() метод поиска записей, которые были опубликованы на стороне сервера? Это было спотыкание я встал, потому что я чувствовал, что я должен только звонить find() раз.
4 ответа:
коллекции, публикации и подписки-это сложная область Meteor, которую документация может обсудить более подробно, чтобы избежать частопутаница, которые иногда усиливаются путаешь терминологию.
здесь Саша Грейф (соавтор DiscoverMeteor) объяснение публикаций и подписок в одном слайде:
To правильно понимаю, почему нужно звонить
find()несколько раз вам нужно понять, как работают коллекции, публикации и подписки в Meteor:
вы определяете коллекции в MongoDB. Метеорит пока не пострадал. Эти коллекции содержат записей базы данных (также называется "документы" обоими Монго Метеор, но "документ" является более общим, чем запись базы данных; например, спецификация обновления или a селектор запросов-это документы слишком - объекты JavaScript, содержащие
field: valueпар).затем вы определяете коллекциина сервере Метеор с
MyCollection = new Mongo.Collection('collection-name-in-mongo')эти сборники содержат все данные из коллекций MongoDB, и вы можете запустить
MyCollection.find({...})на них, которые вернут a курсор (набор записей, с методами для их перебора и вернуть их).этот курсор (большую часть времени) используется для публикации (отправить) набор записей (называется a "рекорд"). Вы можете дополнительно опубликовать только некоторые полей этих записей. Это рекордные наборы (не коллекции), что клиенты подписаться для. Публикация осуществляется с помощью публикации функция, который вызывается каждый раз, когда новый клиент подписывается, и который может принимать параметры для управления возвращаемыми записями (например, идентификатор пользователя, чтобы возвращать только документы этого пользователя).
на клиенте, вы Minimongo коллекции частично зеркала некоторые записей с сервера. "Частично", потому что они могут содержать только некоторые поля, и "записи", потому что вы обычно хотите отправить клиенту нужны только записи, чтобы ускорить загрузку страницы, и только те, которые ему нужны и имеет разрешение на доступ.
Minimongo по существу является в памяти, непостоянной реализацией Mongo в чистом JavaScript. Он служит в качестве локального кэша, который хранит только подмножество базы данных, с которой работает этот клиент. Запросы на клиенте (find) подаются непосредственно из этого кэша, не обращаясь к сервер.
эти коллекции Minimongo изначально пусты. Они заполнены
Meteor.subscribe('record-set-name')звонки. Обратите внимание, что параметр подписаться это не имя коллекции; это имя рекорд что сервер используется в
publishзвонок. Элементsubscribe()вызов подписывает клиента на рекорд - подмножество записей из коллекции сервера (например, последние 100 записей в блоге), со всеми или подмножеством поля в каждой записи (например, толькоtitleиdate). Как Minimongo знает, в какую коллекцию поместить входящие записи? Имя коллекции будетcollectionаргумент, используемый в обработчике публикацииadded,changedиremovedобратные вызовы, или если они отсутствуют (что имеет место большую часть времени), это будет имя коллекции MongoDB на сервере.изменение записи
вот где Метеор делает вещи очень удобными: когда вы изменяете запись (документ) в коллекции Minimongo на клиенте, Meteor мгновенно обновит все шаблоны, которые зависят от него, а также отправит изменения обратно на сервер, который, в свою очередь, сохранит изменения в MongoDB и отправит их соответствующим клиентам, которые подписались на набор записей, включая этот документ. Это называется компенсации задержки и является одним из семь основных принципов Метеор.
несколько подписок
вы можете иметь кучу подписок, которые вытаскивают разные записи, но все они окажутся в одной коллекции на клиенте, если они пришли из одной коллекции на сервере, на основе их
_id. Это не объясняется ясно, но подразумевается в документах Meteor:когда вы подписываетесь на набор записей, он сообщает серверу отправлять записи клиенту. Клиент хранит их записи в местных коллекциях Minimongo, с тем же именем, что и
collectionаргумент, используемый в обработчике публикацииadded,changedиremovedобратные вызовы. Метеор будет стоять в очереди входящих атрибутов, пока вы не объявите Монго.Коллекция на клиенте, с соответствующим именем коллекции.то, что не объясняется, это то, что происходит, когда вы не явно использовать
added,changedиremoved, или публиковать обработчики вообще-что в большинстве случаев. В в этом наиболее распространенном случае аргумент collection (неудивительно) берется из имени коллекции MongoDB, объявленной на сервере на шаге 1. Но это означает, что у вас могут быть разные публикации и подписки с разными именами, и все записи окажутся в одной коллекции на клиенте. Вплоть до уровня поля верхнего уровня, Meteor заботится о выполнении объединения набора документов, чтобы подписки могли перекрывать функции публикации что корабль различных полей верхнего уровня для работы клиента бок о бок и на клиенте, документ в коллекции будет объединение двух наборов полей.пример: несколько подписок, заполняющих одну и ту же коллекцию на клиенте
у вас есть коллекция BlogPosts, которую вы объявляете одинаково как на сервере, так и на клиенте, хотя она делает разные вещи:
BlogPosts = new Mongo.Collection('posts');на клиенте
BlogPostsможно сделать записи:
подписка на самые последние 10 сообщений в блоге
// server Meteor.publish('posts-recent', function publishFunction() { return BlogPosts.find({}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe('posts-recent');подписка на сообщения текущего пользователя
// server Meteor.publish('posts-current-user', function publishFunction() { return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10}); // this.userId is provided by Meteor - http://docs.meteor.com/#publish_userId } Meteor.publish('posts-by-user', function publishFunction(who) { return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe('posts-current-user'); Meteor.subscribe('posts-by-user', someUser);подписка на самые популярные должности
- etc.
все эти документы исходят от
postsколлекция в MongoDB, черезBlogPostsколлекция на сервере, и в конечном итоге вBlogPostsколлекция на клиент.теперь мы можем понять, почему нужно называть
find()более одного раза-второй раз на клиенте, потому что документы из всех подписок будут в конечном итоге в той же коллекции, и вам нужно получить только те, о которых вы заботитесь. Например, чтобы получить самые последние сообщения на клиенте, вы просто зеркально отображаете запрос с сервера:var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});это вернет курсор ко всем документам / записям, которые клиент получил до сих пор, как верхние сообщения и посты пользователей. (спасибо Джеффри).
да, функция поиска на стороне клиента () возвращает только те документы, которые находятся на клиенте в Minimongo. От docs:
на клиенте создается экземпляр Minimongo. Minimongo по существу является в памяти, непостоянной реализацией Mongo в чистом JavaScript. Он служит в качестве локального кэша, который хранит только подмножество базы данных, с которой работает этот клиент. Запросы на клиенте (find) подаются непосредственно из этого кэша, не обращаясь к сервер.
Как вы говорите, publish () указывает, какие документы будут у клиента.
основное правило большого пальца вот
publishиsubscribedимена переменных должны быть одинаковыми на стороне клиента и сервера.имена коллекций на Mongo DB и стороне клиента должны быть одинаковыми.
предположим, что я использую publish и subscribe для моей коллекции с именем
employeesтогда код будет выглядеть так
сервер
здесь использование
varключевое слово является необязательным (используйте это ключевое слово, чтобы сделать коллекцию локальной для этого папка.)CollectionNameOnServerSide = new Mongo.Collection('employees'); Meteor.publish('employeesPubSub', function() { return CollectionNameOnServerSide.find({}); });
на стороне клиента .js file
CollectionNameOnClientSide = new Mongo.Collection('employees'); var employeesData = Meteor.subscribe('employeesPubSub'); Template.templateName.helpers({ 'subcribedDataNotAvailable' : function(){ return !employeesData.ready(); }, 'employeeNumbers' : () =>{ CollectionNameOnClientSide.find({'empId':1}); } });
на стороне клиента .html файл
здесь мы можем использовать
subcribedDataNotAvailableвспомогательный метод, чтобы узнать, если данные готовы на стороне клиента, если данные готовы, то распечатать номера сотрудников с помощьюemployeeNumbersвспомогательный метод.<TEMPLATE name="templateName"> {{#if subcribedDataNotAvailable}} <h1> data loading ... </h1> {{else}} {{#each employeeNumbers }} {{this}} {{/each}} {{/if}} <TEMPLATE>
