doufeng3602
doufeng3602
2018-07-03 11:55

如何编码/解码mongodb游标?

已采纳

I need to build a list of "pages" so part of this there will be a cursor. The issue is that I can't find a way to encode(to string) and decode the cursor. Any idea? The Cursor interface has no "encoding" method(there is ID, though undocumented) and there is no way to create a new cursor from a string(or int).

type Cursor interface {

    // Get the ID of the cursor.
    ID() int64

    // Get the next result from the cursor.
    // Returns true if there were no errors and there is a next result.
    Next(context.Context) bool

    Decode(interface{}) error

    DecodeBytes() (bson.Reader, error)

    // Returns the error status of the cursor
    Err() error

    // Close the cursor.
    Close(context.Context) error
}

Why do I need the cursor encoded?

To provide pagination to the end client through a html or JSON API.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dow58115 dow58115 3年前

    MongoDB does not provide a serializable cursor. Cursor is not serializable. The recommended workaround is to use a range query and sort on a field that generally changes in a consistent direction over time such _id.

    function printStudents(startValue, nPerPage) {
      let endValue = null;
      db.students.find( { _id: { $lt: startValue } } )
                 .sort( { _id: -1 } )
                 .limit( nPerPage )
                 .forEach( student => {
                   print( student.name );
                   endValue = student._id;
                 } );
    
      return endValue;
    }
    

    There is a go package minquery that tries to make the cursor query/serialization more convenient. You may find it helpful.

    点赞 评论 复制链接分享
  • duanbin198788 duanbin198788 3年前

    A mongo.Cursor object isn't something you can encode and put away for later use, like what you intend to use it for.

    A mongo.Cursor is something you use to iterate over a "live query", a stream of documents. You can't use it to return a batch of documents which you send to your client, and when the client requests more documents (the next page), you decode the stored cursor and continue where you left off. A cursor have a server side resource under the hood, which is kept for 10 minutes (configurable, see cursorTimeoutMillis) or until you close the cursor implicitly. You do not want to keep the cursor "alive" while waiting for the client if he / she needs more documents, especially in an application with large traffic. Your MongoDB would quickly run out of resources. If cursor is closed by timeout, any attempt to read from the cursor will result with error "Cursor not found, cursor id: #####"

    The Cursor.Decode() method is not to decode a cursor from some encoded form. It is to decode the next document the cursor designates into a Go value.

    That's why there is no magic mongo.NewCursor() or mongo.ParseCursor() or mongo.DecodeCursor() function. A mongo.Cursor is handed to you by executing queries, e.g. with Collection.Find():

    func (coll *Collection) Find(ctx context.Context, filter interface{},
        opts ...findopt.Find) (Cursor, error)
    
    点赞 评论 复制链接分享

为你推荐