如何在Meteor中发布集合的视图/转换?

时间:2013-08-20 19:32:26

标签: meteor

我制作了一个集合

var Words = new Meteor.Collection("words");

并发布:

Meteor.publish("words", function() {
    return Words.find();
});

以便我可以在客户端上访问它。问题是,这个集合会变得非常大,我只想发布它的变换。例如,假设我想发布一个名为“num words by length”的摘要,这是一个int数组,其中索引是单词的长度,item是该长度的单词数。所以

wordsByLength[5] = 12;

表示有12个长度为5的单词。在SQL术语中,它比原始数据集简单的GROUP BY / COUNT。我正在尝试在客户端上创建一个类似

的模板
  • 你有N个长度为X的单词

每个长度。我的问题归结为“我的表格A中有我的数据,我想发布一个转换后的版本,B”。

3 个答案:

答案 0 :(得分:21)

UPDATE 您可以在服务器上转换集合,如下所示:

Words = new Mongo.Collection("collection_name"); 

Meteor.publish("yourRecordSet", function() {

  //Transform function
  var transform = function(doc) {
    doc.date = new Date();
    return doc;
  }

  var self = this;

  var observer = Words.find().observe({
      added: function (document) {
      self.added('collection_name', document._id, transform(document));
    },
    changed: function (newDocument, oldDocument) {
      self.changed('collection_name', oldDocument._id, transform(newDocument));
    },
    removed: function (oldDocument) {
      self.removed('collection_name', oldDocument._id);
    }
  });

  self.onStop(function () {
    observer.stop();
  });

  self.ready();

});

答案 1 :(得分:1)

要包装其他答案中提到的转换,您可以使用我开发的包meteor-middleware。它为此提供了一个很好的可插拔API。因此,您可以将它们堆叠在另一个上,而不仅仅是提供转换。这允许代码重用,权限检查(比如根据权限删除或聚合字段)等。因此,您可以创建一个类,允许您以您希望的方式聚合文档。

但是对于您的特定情况,您可能需要查看MongoDB aggregation pipeline。如果确实有很多单词,您可能不希望将所有单词从MongoDB服务器传输到Meteor服务器端。另一方面,聚合管道缺乏您可能想要的反应性。因此,发布的文档会随着单词的进入而改变计数。

要解决这个问题,你可以使用我开发的另一个软件包PeerDB。它允许您指定将被动态调用为数据更改并存储在数据库中的触发器。然后,您可以简单地使用普通发布将计数发送到客户端。缺点是所有用户都应该对同一个集合感兴趣。它适用于全球,而非每个用户。但如果你对整个集合中的单词数量感兴趣,你可以做一些像(在CoffeesScript中):

class WordCounts extends Document
  @Meta
    name: 'WordCounts'

class Words extends Document
  @Meta
    name: 'Words'
    triggers: =>
      countWords: @Trigger ['word'], (newDocument, oldDocument) ->
        # Document has been removed.
        if not newDocument._id
          WordCounts.update
            length: oldDocument.word.length
          ,
            $inc:
              count: -1
        # Document has been added.
        else if not oldDocument._id
          WordCounts.update
            length: newDocument.word.length
          ,
            $inc:
              count: 1
        # Word length has changed.
        else if newDocument.word.length isnt oldDocument.word.length
          WordCounts.update
            length: oldDocument.word.length
          ,
            $inc:
              count: -1
          WordCounts.update
            length: newDocument.word.length
          ,
            $inc:
              count: 1

然后你可以简单地发布WordCounts个文件:

Meteor.publish 'counts', ->
  WordCounts.documents.find()

答案 2 :(得分:0)

您可以通过单词(cursor for each

遍历每个文档来汇总计数
var countingCursor = Words.find({});
var wordCounts = {};

countingCursor.forEach(function (word) {
  wordCounts[word.length].count += 1;
  wordCounts[word.length].words = wordCounts[word.length].words || []
  wordCounts[word.length].words.push(word);
});

创建一个本地集合,

var counts = new Meteor.Collection('local-counts-collection', {connection: null});

并插入您的答案

var key, value;

for (key in wordCounts) {
  value = object[key];
  counts.insert({
    length: key,
    count: value.count,
    members: value.words
  });
}

Counts现在是一个集合,只是没有存储在Mongo中。

未经测试!