2012-09-01 11 views
21

Usando Meteor, me pregunto cuál es la mejor forma de manejar diferentes colecciones del lado del cliente que comparten la misma colección de bases de datos del lado del servidor. Considere el siguiente ejemplo: Tengo una colección User, y en mi lado del cliente tengo una lista de usuarios que son amigos y tengo una función de búsqueda que realiza una consulta en toda la base de datos de usuarios, devolviendo una lista de nombres de usuario que coincide con la consulta.Estrategias de publicación/suscripción de Meteor para colecciones únicas del lado del cliente

En el método Publicar del lado del servidor, tengo dos consultas en la misma colección que devuelven diferentes conjuntos de documentos. ¿Deberían estos datos entrar en dos colecciones separadas en el lado del cliente? ¿O deberían todos los documentos del Usuario que coinciden con ambas consultas terminar en la misma colección? En este último caso, ¿podría duplicar el código utilizado tanto para la consulta del lado del servidor como para la del lado del cliente?

En el servidor:

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

En el cliente:

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}}) 
    } 
}) 

esto parece una solución plausible, pero no una óptima uno. ¿Qué ocurre si quiero crear una nueva colección del lado del cliente que consista en resultados de búsqueda de varias colecciones del lado del servidor?

Respuesta

24

En una zona compartida:

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 
} 

En el servidor:

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

En el cliente:

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(); 
    } 
}); 

La conclusión clave de esto es que lo que sucede detrás de las escenas cuando los datos se transfieren por el cable no es obvio. Meteor aparece en combine los registros que coinciden en las diversas consultas en el servidor y envíe este al cliente. A continuación, el cliente volverá a ejecutar la misma consulta para dividirlos en .

Por ejemplo, supongamos que tiene 20 registros en una colección del lado del servidor. A continuación, tiene dos publica: el primero coincide con 5 registros, el segundo coincide con 6, de los cuales 2 son lo mismo. Meteor enviará 9 registros. En el cliente, luego ejecuta exactamente las mismas consultas que realizó en el servidor y debe terminar con 5 y 6 registros respectivamente.

+0

sólo quieren hacer una nota que mi información sobre cómo "combina" Meteor los registros no puede ser exacta o verdadero. Si un desarrollador de Meteor o alguien que sabe mejor puede confirmar, por favor hazlo. Mi suposición se basa en mis propias observaciones personales. – matb33

+0

Parece que mis observaciones fueron correctas con respecto a la combinación. Consulte la sección "Fusionar cuadro" en esta respuesta: http://stackoverflow.com/a/13867122/962223 – matb33

+1

Cuando coloco las funciones de búsqueda en una carpeta compartida, p. lib las funciones de publicación pueden encontrarlos. Cuando los coloco en el mismo archivo que las funciones de publicación, los encuentran las funciones de publicación, pero no están visibles en el cliente. Ideas? – cramhead

10

Llego un poco tarde a la fiesta, pero hay una manera de tener realmente colecciones separadas en el cliente para subconjuntos de una colección de servidores. En este ejemplo, tengo una colección de servidores llamada entities que contiene información sobre polygons y rectangles.
código compartido (carpeta lib): Código

// 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'); 

Cliente:

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

Recuerde que el nombre de la suscripción debe coincidir con el nombre de la publicación (pero no el nombre de la propia colección) código de
servidor:

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(); 
}); 

Gracias a user728291 para el usin solución mucho más simple g _publishCursor()!
El tercer argumento de la función _publishCursor() es el nombre de su nueva colección.
Fuente: http://docs.meteor.com/#/full/publish_added

+0

Su código puede ser mucho más corto usando el [_publishCursor] no documentado (https: // github. com/meteoro/meteoro/blob/0d33cbbfca6cc769ef6c634ca249ca40a1be6e52/packages/mongo/collection.js # L301). Por ejemplo 'Meteor.publish ('polyEntities', function() {Mongo.Collection._publishCursor (Entities.find ({shapeType: 'polygon'}), this, 'polyEntities'); this.ready();}); ' – user728291

+0

guau gran solución gracias! – PhilippSpo

+0

@ user728291 ¿cómo manejaría las actualizaciones en la colección PolyEntities? – PhilippSpo

0

uso publish-composite paquete

// 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: [] 
}); 

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

Cuestiones relacionadas