流星订阅异常“必须使用有序观察”

时间:2016-01-05 14:56:02

标签: node.js mongodb meteor

我在尝试查询具有索引的mongo集合时遇到此错误。

Exception from sub articles id SW67ztza4q2xnWtT7 Error: must use ordered observe (ie, 'addedBefore' instead of 'added') with skip or limit
    at [object Object]._.extend.observeChanges (packages/minimongo/minimongo.js:325:1)
    at Function.Mongo.Collection._publishCursor (packages/mongo/collection.js:312:1)
    at [object Object].LocalCollection.Cursor._publishCursor (packages/minimongo/minimongo.js:245:1)
    at [object Object]._.extend._publishHandlerResult (livedata_server.js:1065:13)
    at [object Object]._.extend._runHandler (livedata_server.js:1038:10)
    at [object Object]._.extend._startSubscription (livedata_server.js:842:9)
    at [object Object]._.extend.protocol_handlers.sub (livedata_server.js:614:12)
    at livedata_server.js:548:43

我的问题是我在代码中的任何地方都没有使用articles.observearticles.observeChanges

我对这个感到难过。

这是我在集合上创建的索引:

db.articles.createIndex({'refIds':1, 'date.published':1})

其中refIds是一组mongo id字符串。

我的查询是:

Articles.find({refIds: refId},{
      fields: {
        refIds: 1,
        title: 1,
        author: 1,
        description: 1,
        url: 1,
        date: 1,
        thumbnail: 1
      },
      limit: 20,
      sort: {'date.published':-1}
    })

1 个答案:

答案 0 :(得分:0)

我能够找出问题所在。

当我将订阅从一个服务器发送到另一个服务器然后再转发到客户端时,发生了竞争情况。像这样:

collection owner
     |
subscribing server
     |
client browser

Meteor.publish上的subscribing server函数发生了异常。像这样:

Meteor.publish('myRefs', function(refId){
  CollectionServer.subscribe('myRefs', {refId})
  return Articles.find({refIds: refId},{
      fields: {
        refIds: 1,
        title: 1,
        author: 1,
        description: 1,
        url: 1,
        date: 1,
        thumbnail: 1
      },
      limit: 20,
      sort: {'date.published':-1}
    })
})

这是一个错误,但只是最近 - 并且只是在刺激。我终于发现有一个竞争条件正在发生,这就是为什么我没有在开发中看到这个问题。 dev中的集合远不及prod集合中的1M文档。

为了对抗竞争条件,我将回报投入到服务器订阅的onReady中,它似乎已经解决了我遇到的异常。

const Future = Npm.require('fibers/future')
Meteor.publish('myrefs', function(refId){
  let future = new Future()
  CollectionServer.subscribe('myRefs', {refId}, {
    onReady(){
      future.return(Articles.find({refIds: refId}))
    },
    onError(err){
      future.throw(err)
    }
  })
  return future.wait()
})