转换后对集合进行排序

时间:2014-02-21 10:18:18

标签: mongodb coffeescript meteor

我有一个集合,它使用transform来实例化类中的文档。然后,这些实例设置了新属性,从第3部分apis获取的数据并使其成为被动的。

现在,我需要根据检索被动数据的方法对这些对象进行排序。但是我不能做一个集合find.sort,或者使用collection-hooks,因为它在转换之前对文档进行操作,因此该方法不可用。

因此,在我看来,基于不在mongo中的数据对该集合进行排序的唯一方法是覆盖UI.each元素并在那里添加排序。但我对Meteor很新,并且不知道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}}

如何根据方法 get_balance(){{#each}}对我的地址进行排序?

修改

我们可以在模板中对集合查询执行fetch()以检索已转换的元素。在这种情况下你如何使用observe()?因为在这种情况下,反应性会丢失并且地址不会更新。

之前的

no sorting

donationAddresses: ->
  coinsManager = Meteor.users.findOne
    "emails.address": "coinsmanager@gmail.com"
  if coinsManager
    Addresses.find
      userId: coinsManager._id

sorting

donationAddresses: ->
  coinsManager = Meteor.users.findOne
    "emails.address": "coinsmanager@gmail.com"
  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

3 个答案:

答案 0 :(得分:1)

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

你可以fetch()收集的find()结果并对数组进行排序吗?为了保持反应性,您可以observe()并重新创建阵列。在Meteor实现该功能之前,速度很慢但可能是一个权宜之计。

答案 1 :(得分: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检查特定字段是否已更新 -

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']})

答案 2 :(得分:0)

我终于开始工作了!

success

以下是代码:

code

基本上,

  • 我将集合光标的初始化从模板移动到路由器,然后返回获取的集合(数组)
  • 我在模板帮助器中检索该集合,并对阵列执行排序。
  • 我将已排序的数组传递给UI.each。

我不知道如何在没有观察或者观察手柄的情况下设法处理反应性......但它确实有效。可能魔术是从Iron路由器处理来保持数据被动反应:)