EDIT: этот вопрос, некоторые ответы и некоторые комментарии содержат много дезинформации. См. как работают коллекции, публикации и подписки Meteor для точного понимания публикации и подписки на несколько подмножеств одной и той же серверной коллекции.
Как можно публиковать разные подмножества (или "представления" ) одной коллекции на сервере как несколько коллекций на клиенте?
Вот какой-то псевдокод, который поможет проиллюстрировать мой вопрос:
items
коллекция на сервере
Предположим, что у меня есть коллекция items
на сервере с миллионами записей. Пусть также предположим, что:
- 50 записей имеют свойство
enabled
, установленное наtrue
, и; - 100 записей имеют свойство
processed
, установленное наtrue
.
Все остальные установлены на false
.
items:
{
"_id": "uniqueid1",
"title": "item #1",
"enabled": false,
"processed": false
},
{
"_id": "uniqueid2",
"title": "item #2",
"enabled": false,
"processed": true
},
...
{
"_id": "uniqueid458734958",
"title": "item #458734958",
"enabled": true,
"processed": true
}
Код сервера
Публикуйте два "представления" одного и того же набора серверов. Один отправит курсор с 50 записями, а другой отправит курсор со 100 записями. В этой фиктивной серверной базе данных содержится более 458 миллионов записей, и клиенту не нужно знать обо всех этих (фактически, отправка их всех вниз, вероятно, займет несколько часов в этом примере):
var Items = new Meteor.Collection("items");
Meteor.publish("enabled_items", function () {
// Only 50 "Items" have enabled set to true
return Items.find({enabled: true});
});
Meteor.publish("processed_items", function () {
// Only 100 "Items" have processed set to true
return Items.find({processed: true});
});
Клиентский код
Чтобы поддержать метод компенсации латентности, мы вынуждены объявлять на клиенте единую коллекцию items
. Становится очевидным, где этот недостаток: как дифференцировать между items
для enabled_items
и items
для processed_items
?
var Items = new Meteor.Collection("items");
Meteor.subscribe("enabled_items", function () {
// This will output 50, fine
console.log(Items.find().count());
});
Meteor.subscribe("processed_items", function () {
// This will also output 50, since we have no choice but to use
// the same "Items" collection.
console.log(Items.find().count());
});
Мое текущее решение включает в себя обезглавливание _publishCursor, позволяющее использовать имя подписки вместо имени коллекции. Но это не будет компенсировать латентность. Каждая запись должна совершать кругооборот на сервер:
// On the client:
var EnabledItems = new Meteor.Collection("enabled_items");
var ProcessedItems = new Meteor.Collection("processed_items");
С помощью патча обезьяны это будет работать. Но перейдите в автономный режим, и изменения сразу не появятся на клиенте - нам нужно будет подключиться к серверу, чтобы увидеть изменения.
Какой правильный подход?
EDIT: Я только что просмотрел эту тему, и я понимаю, что, поскольку это так, мои вопросы и ответы и множество комментариев содержат много дезинформации.
Что происходит, так это то, что я неправильно понял отношения публикации-подписки. Я думал, что когда вы опубликуете курсор, он приземлится на клиенте как отдельная коллекция из других опубликованных курсоров, которые возникли из той же коллекции серверов. Это просто не так, как это работает. Идея состоит в том, что и клиент, и сервер имеют одни и те же коллекции, но это то, что находится в коллекциях, которые отличаются. Контракты pub-sub согласовывают, какие документы заканчиваются на клиенте. Ответ Тома технически правилен, но не хватает нескольких деталей, чтобы повернуть мои предположения. Я ответил на аналогичный вопрос на мой вопрос в другом SO-потоке, основанном на объяснении Тома, но имея в виду мое первоначальное непонимание Meteor pub-sub: Meteor публикует/подписывает стратегии для уникальных коллекций на стороне клиента
Надеюсь, это поможет тем, кто сталкивается с этой нитью и уходит больше, чем что-то путать!