Как кодировать / декодировать курсор Mongodb?
Мне нужно построить список "страниц", поэтому частью этого будет курсор. Проблема в том, что я не могу найти способ кодировать (в строку) и декодировать курсор. Любая идея? Интерфейс Cursor не имеет метода "кодирования" (есть ID, хотя и недокументированный), и нет способа создать новый курсор из строки (или 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
}
Зачем мне нужен кодированный курсор?
Предоставить нумерацию страниц конечному клиенту через HTML или JSON API.
2 ответа
MongoDB не предоставляет сериализуемый курсор. Курсор не сериализуем. Рекомендуемый обходной путь - использовать запрос диапазона и сортировку по полю, которое обычно изменяется в согласованном направлении с течением времени, например _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;
}
Существует мини-запрос пакета go, который пытается сделать запрос / сериализацию курсора более удобными. Вы можете найти это полезным.
mongo.Cursor
объект - это не то, что вы можете закодировать и убрать для дальнейшего использования, например, для чего вы собираетесь его использовать.
mongo.Cursor
это то, что вы используете для перебора "живого запроса", потока документов. Вы не можете использовать его для возврата пакета документов, который вы отправляете своему клиенту, и когда клиент запрашивает больше документов (следующая страница), вы декодируете сохраненный курсор и продолжаете с того места, где остановились. У курсора есть серверный ресурс под капотом, который хранится в течение 10 минут (настраивается, см. CursorTimeoutMillis) или до тех пор, пока вы не закроете курсор неявно. Вы не хотите, чтобы курсор оставался "живым" во время ожидания клиента, если ему нужно больше документов, особенно в приложении с большим трафиком. Ваш MongoDB быстро исчерпает ресурсы. Если курсор закрыт по таймауту, любая попытка чтения с курсора приведет к ошибке "Курсор не найден, идентификатор курсора: #####"
Cursor.Decode()
Метод не для декодирования курсора из какой-либо закодированной формы. Он предназначен для декодирования следующего документа, который курсор назначает в значение Go.
Вот почему нет магии mongo.NewCursor()
или же mongo.ParseCursor()
или же mongo.DecodeCursor()
функция. mongo.Cursor
передается вам путем выполнения запросов, например, с Collection.Find()
:
func (coll *Collection) Find(ctx context.Context, filter interface{},
opts ...findopt.Find) (Cursor, error)