mongodb - 变换后对集合进行排序

标签 mongodb coffeescript meteor

我有一个集合,它使用转换来实例化类中的文档。然后,这些实例设置新属性、从第三部分 api 获取的数据并使其成为响应式。

现在,我需要根据检索 react 数据的方法对这些对象进行排序。但我无法执行集合 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

helper

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

模板

template(name="coinsManager")

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

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

编辑

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

之前:

no sorting

donationAddresses: ->
  coinsManager = Meteor.users.findOne
    "emails.address": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dab9b5b3b4a9b7bbb4bbbdbfa89abdb7bbb3b6f4b9b5b7" rel="noreferrer noopener nofollow">[email protected]</a>"
  if coinsManager
    Addresses.find
      userId: coinsManager._id

之后: sorting

donationAddresses: ->
  coinsManager = Meteor.users.findOne
    "emails.address": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ceada1a7a0bda3afa0afa9abbc8ea9a3afa7a2e0ada1a3" rel="noreferrer noopener nofollow">[email protected]</a>"
  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

最佳答案

以下代码会将源集合 (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()))

一旦您拥有填充了转换后的文档的单独集合 - 您就可以执行常规的响应式(Reactive)和排序查询,例如。 myLocalCollection.find({},{sort:['a','b','c']})

关于mongodb - 变换后对集合进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21931461/

相关文章:

mongodb - AWS CLI 的细微差别

javascript - 如何连接该 mongodb 集合中的所有成员 ID?

coffeescript - 如何使用 Coffeescript 和 Rails 3.1 定义回调函数?

javascript - 在 Meteor.js 中基于 URL 发布集合

javascript - Hapi.js 身份验证不工作

node.js - Can't query date from MongoDB(Mlab) -- 如此简单却无法解决

javascript - 如何在 coffeescript 中执行 "if undefined"?

javascript - "object is not a function"错误?

heroku - 加密 key 未经授权用于持续部署 Travis → Heroku

authentication - Meteor 帐户获取 SAML 响应(登录后的 token /用户)