sql >> Databasteknik >  >> NoSQL >> MongoDB

Förstå Meteor Publicera / Prenumerera

Samlingar, publikationer och prenumerationer är ett knepigt område av Meteor, som dokumentationen skulle kunna diskutera mer i detalj, för att undvika frekvent förvirring, som ibland förstärks av förvirrande terminologi.

Här är Sacha Greif (medförfattare till DiscoverMeteor) som förklarar publikationer och prenumerationer i en bild:

För att riktigt förstå varför du behöver anropa find() mer än en gång måste du förstå hur samlingar, publikationer och prenumerationer fungerar i Meteor:

  1. Du definierar samlingar i MongoDB. Ingen Meteor inblandad än. Dessa samlingar innehåller databasposter (kallas även "dokument" av både Mongo och Meteor, men ett "dokument" är mer allmänt än en databaspost; till exempel är en uppdateringsspecifikation eller en frågeväljare dokument också - JavaScript-objekt som innehåller field:value par).

  2. Sedan definierar du samlingar på Meteor-servern med

    MyCollection = new Mongo.Collection('collection-name-in-mongo')
    

    Dessa samlingar innehåller alla data från MongoDB-samlingarna, och du kan köra MyCollection.find({...}) på dem, vilket returnerar en markör (en uppsättning poster, med metoder för att iterera igenom dem och returnera dem).

  3. Den här markören används (för det mesta) för att publicera (skicka) en uppsättning poster (kallas en "rekorduppsättning" ). Du kan valfritt publicera endast en del fält från dessa poster. Det är rekorduppsättningar (inte samlingar) som kunder prenumererar på till. Publicering görs av en publiceringsfunktion, som anropas varje gång en ny klient prenumererar, och som kan ta parametrar för att hantera vilka poster som ska returneras (t.ex. ett användar-ID, för att endast returnera den användarens dokument).

  4. På klienten , du har Minimongo-samlingar som delvis spegla några av posterna från servern. "Delvis" eftersom de bara kan innehålla några av fälten och "några av posterna" eftersom du vanligtvis bara vill skicka till klienten de poster som den behöver, för att påskynda sidladdningen, och bara de som den behöver och har åtkomstbehörighet.

    Minimongo är i huvudsak en i minnet, icke-beständig implementering av Mongo i ren JavaScript. Den fungerar som en lokal cache som bara lagrar delmängden av databasen som den här klienten arbetar med. Frågor på klienten (hitta) serveras direkt från denna cache, utan att prata med servern.

    Dessa Minimongo-samlingar är till en början tomma. De fylls av

    Meteor.subscribe('record-set-name')
    

    samtal. Observera att parametern att prenumerera på inte är ett samlingsnamn; det är namnet på en rekorduppsättning att servern som används i publicering ringa upp. subscribe() call prenumererar klienten på en postuppsättning - en delmängd av poster från serversamlingen (t.ex. de senaste 100 blogginläggen), med alla eller en delmängd av fälten i varje post (t.ex. endast titel och datum ). Hur vet Minimongo i vilken samling de inkommande posterna ska placeras? Namnet på samlingen kommer att vara samlingen argument som används i publiceringshanterarens added , ändrat , och borttagen återuppringningar, eller om de saknas (vilket är fallet för det mesta), kommer det att vara namnet på MongoDB-samlingen på servern.

Ändra poster

Det är här Meteor gör saker väldigt bekväma:när du ändrar en post (dokument) i Minimongo-samlingen på klienten kommer Meteor omedelbart att uppdatera alla mallar som är beroende av den, och skickar även ändringarna tillbaka till servern, vilket i sin tur kommer att lagra ändringarna i MongoDB och skicka dem till lämpliga kunder som har prenumererat på en postuppsättning inklusive det dokumentet. Detta kallas latenskompensation och är en av de sju kärnprinciperna för Meteor.

Flera prenumerationer

Du kan ha ett gäng prenumerationer som drar in olika poster, men de kommer alla att hamna i samma samling på klienten om de kom från samma samling på servern, baserat på deras _id . Detta förklaras inte tydligt, utan antyds av Meteor-dokumenten:

När du prenumererar på en postuppsättning säger den åt servern att skicka poster till klienten. Klienten lagrar dessa poster i lokala Minimongo-samlingar, med samma namn som samlingen argument som används i publiceringshanterarens added , ändrat , och borttagen återuppringningar. Meteor kommer att köa inkommande attribut tills du deklarerar Mongo.Collection på klienten med det matchande samlingsnamnet.

Det som inte förklaras är vad som händer när du inte gör det använd uttryckligen added , ändrat och borttagen , eller publicera hanterare överhuvudtaget - vilket är för det mesta. I det här vanligaste fallet är insamlingsargumentet (föga förvånande) hämtat från namnet på MongoDB-samlingen du deklarerade på servern vid steg 1. Men vad detta betyder är att du kan ha olika publikationer och prenumerationer med olika namn, och alla poster kommer att hamna i samma samling på klienten. Ner till nivån för toppnivåfält , Meteor ser till att utföra en uppsättning förening mellan dokument, så att prenumerationer kan överlappa - publicera funktioner som skickar olika toppnivåfält till klienten arbete sida vid sida och på klienten, dokumentet i samlingen kommer att vara föreningen av de två uppsättningar av fält.

Exempel:flera prenumerationer som fyller samma samling på klienten

Du har en BlogPosts-samling, som du deklarerar på samma sätt på både servern och klienten, även om den gör olika saker:

BlogPosts = new Mongo.Collection('posts');

På klienten, Blogginlägg kan hämta poster från:

  1. en prenumeration på de senaste 10 blogginläggen

    // server
    Meteor.publish('posts-recent', function publishFunction() {
      return BlogPosts.find({}, {sort: {date: -1}, limit: 10});
    }
    // client
    Meteor.subscribe('posts-recent');
    
  2. en prenumeration på den aktuella användarens inlägg

    // 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);
    
  3. en prenumeration på de mest populära inläggen

  4. osv.

Alla dessa dokument kommer från inläggen samling i MongoDB, via BlogPosts samling på servern och hamnar i Blogginlägg insamling på klienten.

Nu kan vi förstå varför du behöver anropa find() mer än en gång - andra gången på klienten, eftersom dokument från alla prenumerationer kommer att hamna i samma samling, och du behöver bara hämta dem du bryr dig om. Till exempel, för att få de senaste inläggen på klienten, speglar du helt enkelt frågan från servern:

var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});

Detta kommer att returnera en markör till alla dokument/poster som klienten har fått hittills, både de översta inläggen och användarens inlägg. (tack Geoffrey).



  1. Inuti Santander's Near Real-Time Data Ingest Architecture

  2. Redis + Node.js - hur hämtar jag värdena

  3. Kan inte ansluta till redis med jedis

  4. Använd mer än ett schema per samling på mongodb