Метеоритные стратегии публикации / подписки для уникальных коллекций на стороне клиента

Используя 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}})
  }
})

Это кажется правдоподобным решением, но не оптимальным. Что если я захочу создать новую коллекцию на стороне клиента, состоящую из результатов поиска из нескольких коллекций на стороне сервера?

3 ответа

Решение

В общей зоне:

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 записей соответственно.

Я немного опоздал на вечеринку, но есть способ на самом деле иметь отдельные коллекции на клиенте для подмножеств одной коллекции серверов. В этом примере у меня есть коллекция серверов под названием 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/

Использовать публиковать-композитный пакет

// 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

Другие вопросы по тегам