2012-09-01 7 views
21

Mit Meteor frage ich mich, wie man am besten mit verschiedenen clientseitigen Sammlungen umgehen kann, die dieselbe serverseitige Datenbanksammlung haben. Betrachten Sie das folgende Beispiel: Ich habe eine User Sammlung, und auf meiner Client-Seite habe ich eine Liste der Benutzer, die Freunde sind und ich habe eine Suchfunktion, die eine Abfrage für die gesamte Benutzerdatenbank durchführt und eine Liste der Benutzernamen zurückgibt das entspricht der Abfrage.Meteor Publish/Subscribe Strategien für einzigartige clientseitige Sammlungen

Bei der serverseitigen Publish-Methode habe ich zwei Abfragen für die gleiche Sammlung, die unterschiedliche Sätze von Dokumenten zurückgeben. Sollten diese Daten auf der Client-Seite in zwei separate Sammlungen gehen? Oder sollten alle Benutzerdokumente, die mit beiden Abfragen übereinstimmen, in derselben Sammlung landen? Wenn das letztere, würde ich dann Code für die serverseitige und clientseitige Abfrage verwendet werden?

Auf dem Server:

Meteor.publish('searchResults', function(query){ 
    var re = new RegExp(query, 'i') 
    return Users.find({ 'name' : {$regex: re}}) 
}) 

Auf dem Client:

Session.set('searchQuery', null) 

Meteor.autosubscribe(function(){ 
    Meteor.subscribe('searchResults', Session.get('searchQuery')) 
}) 

Template.search.events = { 
    'keyup #user-search' : function(e){ 
    Session.set('searchQuery', e.target.value) 
    } 
} 

_.extend(Template.search, { 

    searchResults: function() { 
    var re = new RegExp(Session.get('searchQuery'), 'i') 
    return Users.find({ 'name' : {$regex: re}}) 
    } 
}) 

Dies scheint eine plausible Lösung, aber keine optimale ein. Was wäre, wenn ich eine neue clientseitige Sammlung erstellen möchte, die aus Suchergebnissen mehrerer serverseitiger Sammlungen besteht?

Antwort

24

In einem gemeinsamen Bereich:

function getSearchUsers(query) { 
    var re = new RegExp(query, "i"); 
    return Users.find({name: {$regex: re}}); 
} 

function getFriendUsers() { 
    return Users.find({friend: true}); // or however you want this to work 
} 

Auf dem Server:

Meteor.publish("searchUsers", getSearchUsers); 
Meteor.publish("friendUsers", getFriendUsers); 

Auf dem Client:

Template.search.onCreated(function() { 
    var self = this; 
    self.autorun(function() { 
    self.subscribe("searchUsers", Session.get("searchQuery")); 
    }); 
}); 

Template.friends.onCreated(function() { 
    this.subscribe("friendUsers"); 
}); 

Template.search.helpers({ 
    searchResults: function() { 
    return getSearchUsers(Session.get("searchQuery")); 
    } 
}); 

Template.friends.helpers({ 
    results: function() { 
    return getFriendUsers(); 
    } 
}); 

Der Schlüssel zum Mitnehmen aus dieser ist das, was hinter den Kulissen passiert, wenn die Daten über die Leitung übertragen wird, ist nicht offensichtlich. Meteor erscheint kombinieren die Datensätze, die in den verschiedenen Abfragen auf dem Server übereinstimmten und senden Sie diese an den Client. Es ist dann auf dem Client, die gleiche Abfrage erneut auszuführen, um sie voneinander zu trennen.

Angenommen, Sie haben 20 Datensätze in einer serverseitigen Sammlung. Sie haben dann zwei veröffentlicht: der erste Treffer 5 Datensätze, der zweite Treffer 6, von denen 2 sind gleich. Meteor wird 9 Datensätze senden. Auf dem Client führen Sie dann die gleichen gleichen Abfragen, die Sie auf dem Server durchgeführt haben, aus, und Sie sollten mit 5 und 6 Datensätze enden.

+0

will einfach eine Anmerkung machen, dass meine Informationen darüber, wie Meteor „verbindet“ die Aufzeichnungen nicht richtig oder wahr sein können. Wenn ein Meteor dev oder jemand, der es besser weiß, dies bestätigen kann, bitte. Meine Annahme basiert auf meinen eigenen persönlichen Beobachtungen. – matb33

+0

Es sieht so aus, als ob meine Beobachtungen bezüglich des Kombinierens korrekt waren. Siehe den "Merge Box" Abschnitt in dieser Antwort: http://stackoverflow.com/a/13867122/962223 – matb33

+1

Wenn ich die Suchfunktionen in einem freigegebenen Ordner, z. lib die Veröffentlichungsfunktionen können sie finden. Wenn ich sie in dieselbe Datei wie die Veröffentlichungsfunktionen lege, werden sie von den Veröffentlichungsfunktionen gefunden, sind aber auf dem Client nicht sichtbar. Ideen? – cramhead

10

Ich bin ein bisschen spät auf die Party, aber es gibt eine Möglichkeit, separate Sammlungen auf dem Client für Teilmengen einer Server-Sammlung zu haben. In diesem Beispiel habe ich eine Server-Sammlung namens entities, die Informationen über polygons und rectangles enthält.
Gemeinsamer Code (lib Ordner):

// main collection (in this example only needed on the server 
Entities = new Meteor.Collection('entities'); 
// partial collections 
RectEntities = new Mongo.Collection('rectEntities'); 
PolyEntities = new Mongo.Collection('polyEntities'); 

Code Auftraggeber:

// this will fill your collections with entries from the Entities collection 
Meteor.subscribe('rectEntities'); 
Meteor.subscribe('polyEntities'); 

Denken Sie daran, dass der Name des Abonnements den Namen der Publikation übereinstimmen muss (aber nicht den Namen der Sammlung selbst)
Code Server:

Meteor.publish('rectEntities', function(){ 
    Mongo.Collection._publishCursor(Entities.find({shapeType: 'rectangle'}), this, 'rectEntities'); 
    this.ready(); 
}); 

Meteor.publish('polyEntities', function(){ 
    Mongo.Collection._publishCursor(Entities.find({shapeType: 'polygon'}), this, 'polyEntities'); 
    this.ready(); 
}); 

Vielen Dank für die viel einfachere Lösung usin user728291 g _publishCursor()!
Das dritte Argument der _publishCursor() Funktion ist der Name Ihrer neuen Sammlung.
Quelle: http://docs.meteor.com/#/full/publish_added

+0

Ihr Code kann mit dem undokumentierten [_publishCursor] (https: // github. com/meteor/meteor/blob/0d33cbbfca6cc769ef6c634ca249ca40a1be6e52/packages/mongo/collection.js # L301). Zum Beispiel 'Meteor.publish ('polyEntities', function() {Mongo.Collection._publishCursor (Entities.find ({shapeType: 'polygon'}), dies, 'polyEntities'); this.ready();}); ' – user728291

+0

wow großartige Lösung danke! – PhilippSpo

+0

@ user728291 Wie würden Sie mit Updates für die PolyEntities-Sammlung umgehen? – PhilippSpo

0

Verwendung publish-composite Paket

// main collection 
Entities = new Meteor.Collection('entities'); 

// partial collections only client side 
RectEntities = new Mongo.Collection('rectEntities'); 
PolyEntities = new Mongo.Collection('polyEntities'); 

// server publish 
Meteor.publishComposite("rectEntities", function(someParameter) { 
    return { 
      collectionName:'rectEntities', 
      find: function() { 
       return Entities.find({shapeType: 'rectangle'}); 
      }, 
      children: [] 
    } 
}); 
Meteor.publishComposite("polyEntities", { 
     collectionName:'polyEntities', 
     find: function() { 
      return Entities.find({shapeType: 'polygon'}); 
     }, 
     children: [] 
}); 

Quelle: http://braindump.io/meteor/2014/09/20/publishing-to-an-alternative-clientside-collection-in-meteor.html

Verwandte Themen