How to publish a view/transform of a collection in Meteor?

前端 未结 3 482
没有蜡笔的小新
没有蜡笔的小新 2020-12-03 02:39

I have made a collection

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

and published it:

Meteor.publish(\"words\", functio         


        
相关标签:
3条回答
  • 2020-12-03 02:49

    You could assemble the counts by going through each document in Words, (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);
    });
    

    create a local collection,

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

    and insert your answers

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

    Counts is now a collection, just not stored in Mongo.

    Not tested!

    0 讨论(0)
  • 2020-12-03 03:00

    To wrap transformations mentioned in other answers, you could use the package I developed, meteor-middleware. It provides a nice pluggable API for this. So instead of just providing a transform, you can stack them one on another. This allows for code reuse, permissions checks (like removing or aggregating fields based on permissions), etc. So you could create a class which allows you to aggregate documents in the way you want.

    But for your particular case you might want to look into MongoDB aggregation pipeline. If there is really a lot of words you probably do not want to transfer all of them from the MongoDB server to the Meteor server side. On the other hand, aggregation pipeline lacks the reactivity you might want to have. So that published documents change counts as words come in and go.

    To address that you could use another package I developed, PeerDB. It allows you to specify triggers which would be reactively called as data changes, and stored in the database. Then you could simply use normal publishing to send counts to the client. The downside is that all users should be interested in the same collection. It works globally, not per user. But if you are interested in counts of words per whole collection, you could do something like (in 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
    

    And then you could simply publish WordCounts documents:

    Meteor.publish 'counts', ->
      WordCounts.documents.find()
    
    0 讨论(0)
  • 2020-12-03 03:02

    UPDATE You can transform a collection on the server like this:

    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();
    
    });
    
    0 讨论(0)
提交回复
热议问题