2014-02-21 23 views
2

我有一個集合使用transform來實例化類中的文檔。然後這些實例設置了新的屬性,從第三方apis獲取數據並作出反應。對變換後的集合進行排序

現在,我需要根據檢索反應數據的方法對這些對象進行排序。但是我不能做一個集合find.sort,或者使用collection-hooks,因爲它在對文檔進行轉換之前對其進行操作,因此該方法不可用。

因此,在我看來,基於不在mongo中的數據對該集合進行排序的唯一方法是重寫UI.each元素並在其中添加排序。但是我對流星很陌生,並不知道UI.each是如何工作的,以及如何覆蓋它來實現這種排序方法。

下面從我的代碼一個簡單的例子:

模式

class @BaseCrypto 

    constructor: (@address) -> 
    @keys = 
     balance: "Processing..." 
    @deps = {} 

    ensureDeps: (key) -> 
    if not @deps[key] 
     @deps[key] = new Deps.Dependency() 
     @set_balance() 

    get_balance: -> 
    """Retrieve value set from @set_balance()""" 
    @ensureDeps "balance" 
    @deps.balance.depend() 
    return @keys.balance 

    set_balance: (url, lambda_balance) -> 
    cls = this 
    Meteor.call "call_url", url, (err, result) -> 
     if err 
     throw new Meteor.Error err.error, err.reason 
     else 
     cls.keys.balance = lambda_balance result 
     cls.deps.balance.changed() 

收集

@Addresses = new Meteor.Collection "addresses", 
    transform: (doc) -> 
     doc = BaseCrypto doc.address 
     doc.set_balance url, lambda_balance 
    return doc 

幫手

Template.coinsManager.helpers 
    donationAddresses: -> 
     Addresses.find {} 

模板

template(name="coinsManager") 

    div 
     div.addresses 
      {{#each donationAddresses}} 
      {{> addressItem}} 
      {{/each}} 

我怎樣才能得到{{#each}}到我的地址排序取決於它們的方法get_balance()

編輯

我們可以在集合查詢做fetch()在模板中檢索已變換元素。你如何在這種情況下使用observe()?因爲在這種情況下,反應性會丟失,地址不會更新。

以前

no sorting

donationAddresses: -> 
    coinsManager = Meteor.users.findOne 
    "emails.address": "[email protected]" 
    if coinsManager 
    Addresses.find 
     userId: coinsManager._id 

sorting

donationAddresses: -> 
    coinsManager = Meteor.users.findOne 
    "emails.address": "[email protected]" 
    if coinsManager 
    addresses = Addresses.find 
     userId: coinsManager._id 
    addresses = addresses.fetch().sort (a, b) -> 
     a = a.get_balance() 
     b = b.get_balance() 
     if not _.isNumber a 
     a = -1 
     if not _.isNumber b 
     b = -1 
     b - a 
    return addresses 
+0

不是超級熟悉API,有沒有一些方法可以將參數放在幫助器中的'.find'中。這樣的排序可以發生在服務器端,而不是可能是一個凌亂的客戶端排序。只要您的模型實現可以通過 –

+0

服務器訪問,我用這種方法看到的最大問題是您的轉換函數執行AJAX調用。每個由遊標返回的文檔都會得到他們自己的AJAX調用,這是非常低效的。你總是可以在你的模板助手中做一個「排序」,這聽起來可能效率低下,但不如AJAX問題。 – sbking

+0

您能否提供更多關於您正在檢索的第三方API數據的信息? – sbking

回答

0

我終於搞定了!

success

這裏是代碼:

code

所以基本上,

  • 我感動集合光標的初始化從模板到路由器,和我退回集合(陣列)
  • 我在模板助手中檢索該集合,並對該數組執行排序。
  • 我將排序後的數組傳遞給UI.each。

不知道如何設法處理的反應沒有觀察或observeHandler ...但它的工作原理。可能這個魔法是從Iron路由器處理的,以保持數據的反應:)

+1

這應該是被動的 - 唯一的問題是,因爲你正在獲取整個結果集,所以對任何結果的更改都會導致整個塊失效/重新呈現。 –

+0

是的,找不到更好的解決方案。從模板中提取顯然會殺死反應性。 如果有人可以通過優化版本去公關CoinsManager,我們將非常感激! – Fandekasp

+1

流星應該[在Minimongo中實現分類轉換](https://github.com/meteor/meteor/issues/1852)< - GitHub問題 –

1

Minimongo doesn't support sorting on virtual fields.,所以Addresses.find({...}, {sort: {balanceVirtualField: 1}}不會」工作。

你能fetch()集合的find()結果和排序數組?要保留反應性,您可以使用它並重新創建數組。在Meteor實現該功能之前,它可能會慢一些,但可能會成爲一項制止措施。

+0

更新了我的帖子,提供了修復反應性的問題。您是正確的,模板中提取的項目已被轉換。 更新了我的帖子,詢問如何在這種情況下使用觀察,因爲反應性丟失 – Fandekasp

+0

找不到在路由器數據中使用觀察我的集合光標的方法,而且我無法在模板幫助器中檢索數據。代碼可以在https:// github上進行測試。com/CoinsManager/CoinsManager/pull/41 – Fandekasp

1

以下代碼會將源集合(myCollection)同步到本地集合(myLocalCollection)中,並對新的/更新的文檔應用轉換。

myCollection = new Meteor.Collection('myCollection') 
myLocalCollection = new Meteor.Collection(null) 

_myTransform = (doc)-> 
    doc.awesome = (doc.someProp > 3) 
    return 

_syncWithTransform = (destination, xform)-> 
    return { 
    added: (doc)-> 
     destination.insert(xform(doc)) 
     return 

    changed: (doc)-> 
     destination.update(id, xform(doc)) 
     return 

    removed: (doc)-> 
     destination.remove(doc._id) 
     return 
    } 

myCollection.find().observe(_syncWithTransform(myLocalCollection, _myTransform)) 

如果你只想要執行您的轉換任務時,特定領域的變化,您可以創建兩個變換函數,並使用observeChanges檢查,如果某一特定領域是updated-

myCollection = new Meteor.Collection('myCollection') 
myLocalCollection = new Meteor.Collection(null) 

_transformNew = (doc)-> 
    doc.awesome = (doc.someProp > 3) 
    return 

_transformUpdate = ($modifier)-> 
    if $modifier.$set?.someProp? 
    $modifier.$set.awesome = ($modifier.$set.someProp > 3) 
    return $modifier 

_syncWithTransform = (destination, xnew, xmod)-> 
    return { 
    added: (id, fields)-> 
     fields._id = id 
     destination.insert(xnew(fields)) 
     return 

    changed: (id, fields)-> 
     $modifier = {} 
     for key, value of fields 
     if value == undefined 
      unless $modifier.$unset? 
      $modifier.$unset = {} 
      $modifier.$unset[key] = true 
     else 
      unless $modifier.$set? 
      $modifier.$set = {} 
      $modifier.$set[key] = value 
     destination.update(id, xmod($modifier)) 
     return 

    removed: (id)-> 
     destination.remove(id) 
     return 
    } 

myCollection.find().observeChanges(_syncWithTransform(myLocalCollection, _transformNew, _transformUpdate())) 

一旦你有單獨的集合充滿了轉換後的文檔 - 您可以執行常規的反應性排序查詢,例如。 myLocalCollection.find({},{sort:['a','b','c']})

+0

聽起來像一個很好的解決方案:)將測試它。 爲什麼我們通過觀察使用變換,而不是集合中的正常變換? – Fandekasp

+0

對不起,但這不符合我的要求。 我希望我的集合被轉換,然後按照轉換中添加的新參數進行排序,並保持反應。您的解決方案仍在觀察原始集合中哪些文檔沒有方法get_balance和get_value。代碼可以在https://github.com/CoinsManager/CoinsManager/pull/41進行測試(請參閱https://www.youtube.com/watch?v=XxjvJjltHYo安裝和運行應用程序) – Fandekasp

+1

您應該使用鏡像因爲你已經鏡像了原始的集合,但是在應用了變換的情況下,它將包含你需要排序的所有字段等等,並且仍然被動地鏈接到變化的​​模板助手('myLocalCollection')中。原始數據。 - 但屬性應該是VALUES而不是函數。 –

相關問題