Понимание Метеор Публикация / Подписка
у меня есть простое приложение, которое показывает список 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>