3

我做了一个收藏

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

并发表:

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

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

wordsByLength[5] = 12;

表示有 12 个长度为 5 的词。在 SQL 术语中,它是对原始数据集的简单 GROUP BY/COUNT。我正在尝试在客户端上制作一个模板,上面会说类似

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

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

4

3 回答 3

21

更新您可以像这样转换服务器上的集合:

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

});
于 2013-08-20T20:42:22.253 回答
1

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

但是对于您的特定情况,您可能需要查看MongoDB 聚合管道。如果确实有很多单词,您可能不想将它们全部从 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()
于 2015-02-08T00:28:29.577 回答
0

您可以通过浏览 Words 中的每个文档来汇总计数,(每个的光标

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 中。

未测试!

于 2013-08-23T06:57:19.663 回答