Meteor публикует/подписывает стратегии для уникальных коллекций на стороне клиента
Используя Meteor, мне интересно, как лучше обращаться с различными коллекциями на стороне клиента, которые используют одну и ту же коллекцию базы данных на стороне сервера. Рассмотрим следующий пример: у меня есть коллекция User
, и на моей стороне клиента у меня есть список пользователей, которые являются друзьями, и у меня есть функция поиска, которая выполняет запрос во всей базе данных пользователей, возвращая список имен пользователей, которые соответствует запросу.
В методе публикации на стороне сервера у меня есть два запроса к одной коллекции, которые возвращают разные наборы документов. Должны ли эти данные входить в две отдельные коллекции на стороне клиента? Или все документы пользователя, соответствующие обоим запросам, попадают в одну коллекцию? Если последний, я бы дублировал код, используемый как для серверной, так и для клиентской стороны?
На сервере:
Meteor.publish('searchResults', function(query){
var re = new RegExp(query, 'i')
return Users.find({ 'name' : {$regex: re}})
})
На клиенте:
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}})
}
})
Это кажется правдоподобным решением, но не оптимальным. Что делать, если я хотел создать новую коллекцию на стороне клиента, состоящую из результатов поиска из нескольких коллекций на стороне сервера?
Ответы
Ответ 1
В общей области:
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
}
На сервере:
Meteor.publish("searchUsers", getSearchUsers);
Meteor.publish("friendUsers", getFriendUsers);
На клиенте:
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();
}
});
Ключевым выводом из этого является то, что происходит за кулисами, когда данные
становится переданным по проводу, не очевидно. Метеор объединяется
записи, которые были сопоставлены в различных запросах на сервере и отправили это
вплоть до клиента. Затем клиент должен снова запустить тот же запрос, чтобы разделить
их друг от друга.
Например, скажем, у вас есть 20 записей в сборе на стороне сервера. Затем у вас есть
два публикует: первые матчи 5 записей, во втором - 6, из которых 2
тоже самое. Метеор отправит 9 записей. На клиенте вы запускаете точное
те же запросы, которые вы выполняли на сервере, и вы должны получить 5 и 6
соответственно.
Ответ 2
Я немного опаздываю на вечеринку, но есть способ фактически иметь отдельные коллекции на клиенте для подмножеств одной серверной коллекции.
В этом примере у меня есть серверный набор под названием entities
, который содержит информацию о polygons
и rectangles
.
Общий код (папка lib):
// 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');
Клиентский код:
// this will fill your collections with entries from the Entities collection
Meteor.subscribe('rectEntities');
Meteor.subscribe('polyEntities');
Помните, что имя подписки должно соответствовать имени публикации (но не самому имени самой коллекции)
Код сервера:
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();
});
Благодаря user728291 для гораздо более простого решения с помощью _publishCursor()
!
Третий аргумент функции _publishCursor()
- это имя вашей новой коллекции.
Источник: http://docs.meteor.com/#/full/publish_added
Ответ 3
использовать publish-composite пакет
// 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: []
});
источник: http://braindump.io/meteor/2014/09/20/publishing-to-an-alternative-clientside-collection-in-meteor.html