2013-08-20 99 views
3

我已經做了收集如何發佈流星中的集合的視圖/變換?

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

發佈了它:

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

,這樣我可以在客戶端上訪問它。問題是,這個集合會變得非常大,我只想發佈它的變換。例如,假設我想發佈一個名爲「num words by length」的摘要,它是一個ints數組,其索引是一個單詞的長度,而item是該長度的單詞數。所以

wordsByLength[5] = 12; 

意味着有長度爲5的12個字SQL中的條款,這是一個簡單的GROUP BY/COUNT在原始數據集。我試圖使客戶端,將這樣說

  • 你有長X

每個長度的N個字上的模板。我的問題歸結爲「我有我的數據在形式A,我想發佈一個轉換的版本,B」。

+0

重複[流星收藏轉換:它是在服務器上還是在客戶端上完成的?或它取決於](http://stackoverflow.com/questions/18093560/meteor-collection-transform-is-it-done-on-the-server-or-on-the-client-or-it-de) –

回答

18

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

}); 
+0

謝謝Akshat,我認爲流星溪將符合這項法案。我真正需要的是一個通用的消息傳遞機制。 –

+0

是否會更改數據庫中的任何數據,還是隻將附加數據發送到客戶端? – pushplaybang

+0

@pushplaybang它不會改變你的數據庫只是讓你定製客戶端看到的東西,你甚至可以從別的地方獲取數據而不是數據庫 – Akshat

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

計數現在是一個集合,只是沒有存儲在Mongo中。

未經測試!

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