Колекциите, публикациите и абонаментите са сложна област на Meteor, която документацията може да обсъди по-подробно, за да се избегне често объркване, което понякога се задълбочава от объркваща терминология.
Ето Sacha Greif (съавтор на DiscoverMeteor), който обяснява публикациите и абонаментите в един слайд:
За да разберете правилно защо трябва да извикате find()
повече от веднъж, трябва да разберете как работят колекции, публикации и абонаменти в Meteor:
-
Вие дефинирате колекции в MongoDB. Все още няма замесен Метеор. Тези колекции съдържат записи на база данни (наричани още „документи“ както от Mongo, така и от Meteor, но „документът“ е по-общ от запис в базата данни; например, спецификация за актуализиране или селектор на заявка също са документи – JavaScript обекти, съдържащи
поле:стойносткод> двойки).
-
След това дефинирате колекции на сървъра на Meteor с
MyCollection = new Mongo.Collection('collection-name-in-mongo')
Тези колекции съдържатвсички данните от колекциите на MongoDB и можете да стартирате
MyCollection.find({...})
върху тях, което ще върне курсора (набор от записи, с методи за итерация през тях и връщането им). -
Този курсор (през повечето време) се използва за публикуване (изпращане) набор от записи (наречен "набор от записи" ). По избор можете да публикувате само някои полета от тези записи. Това са набори от записи (не колекции), за които клиентите се абонират да се. Публикуването се извършва от функция за публикуване, която се извиква всеки път, когато нов клиент се абонира, и която може да приема параметри, за да управлява кои записи да върне (например потребителски идентификатор, за да върне само документите на този потребител).
-
На клиента , имате колекции Minimongo, които частично огледален някои на записите от сървъра. „Частично“, защото може да съдържат само някои от полетата, и „някои от записите“, защото обикновено искате да изпратите на клиента само записите, от които се нуждае, за да ускорите зареждането на страницата, и само тези, от които се нуждае и има разрешение за достъп.
Minimongo е по същество непостоянна реализация на Mongo в паметта в чист JavaScript. Той служи като локален кеш, който съхранява само подмножеството на базата данни, с която работи този клиент. Заявките към клиента (find) се обслужват директно от този кеш, без да се говори със сървъра.
Тези колекции Minimongo първоначално са празни. Те се попълват от
Meteor.subscribe('record-set-name')
обаждания. Имайте предвид, че параметърът за абониране не е име на колекция; това е името на набор от записи че сървърът, използван в
публикуването
обадете се.абониране()
call абонира клиента за набор от записи - подмножество от записи от колекцията на сървъра (напр. последните 100 публикации в блог), с всички или подмножество от полета във всеки запис (напр. самоtitle
идата
). Как Minimongo знае в коя колекция да постави входящите записи? Името на колекцията ще бъдеколекция
аргумент, използван вдобавено
на манипулатора на публикуване ,променен
ипремахнати
обратни извиквания или ако липсват (което е така през повечето време), това ще бъде името на колекцията MongoDB на сървъра.
Промяна на записи
Това е мястото, където Meteor прави нещата много удобни:когато промените запис (документ) в колекцията Minimongo на клиента, Meteor незабавно ще актуализира всички шаблони, които зависят от него, и също така ще изпрати промените обратно на сървъра, който от своя страна ще съхранява промените в MongoDB и ще ги изпрати до съответните клиенти, които са се абонирали за набор от записи, включващ този документ. Това се нарича компенсация на латентността и е един от седемте основни принципа на Meteor.
Множество абонамента
Можете да имате куп абонаменти, които изтеглят различни записи, но всички те ще се озоват в една и съща колекция на клиента, ако идват от същата колекция на сървъра, въз основа на техния _id
. Това не е обяснено ясно, но се подразбира от документите на Meteor:
Когато се абонирате за набор от записи, той казва на сървъра да изпрати записи на клиента. Клиентът съхранява тези записи в локални колекции Minimongo, със същото име като
колекция
аргумент, използван вдобавено
на манипулатора на публикуване ,променен
ипремахнати
обратни повиквания. Meteor ще постави в опашка входящи атрибути, докато не декларирате Mongo.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);
-
абонамент за най-популярните публикации
- и др.
Всички тези документи идват от posts
колекция в MongoDB, чрез BlogPosts
колекция на сървъра и се озовават в BlogPosts
събиране на клиента.
Сега можем да разберем защо трябва да извикате find()
повече от веднъж - вторият път е на клиента, защото документите от всички абонаменти ще попаднат в една и съща колекция и трябва да извлечете само тези, които ви интересуват. Например, за да получите най-новите публикации на клиента, просто отразявате заявката от сървъра:
var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});
Това ще върне курсора към всички документи/записи, които клиентът е получил до момента, както на горните публикации, така и на публикациите на потребителя. (благодаря Джефри).