移动复制 and/or 分配一个 mongodb cxx 游标

move copy and/or assign a mongodb cxx cursor

我正在编写一系列 classes 环绕 mongodb-cxx classes 以使它们符合 API 的存储我的应用程序的其余部分是用 Qt 编写的。

我不需要Mongo的完整功能集,基本上只是CRUD:创建、读取、更新、删除和查找,也许还有一些更高级的参数传入(read/write 担忧等)。

我想在 mongocxx::cursor 周围创建一个包装器 class,这样可以迭代 find() 的结果 "later",存储 "later" 使用的数据格式 API。 "later" 我的意思是(包装的)游标被 returned 到一个抽象 class 可以迭代结果并根据模式验证数据,或者可以跳过条目,或者结果可以成组(异步)发送给最终客户端等

例如,如果我有:(为了这个例子,这被简化了一点)

using namespace mongocxx;

class QMongoClient
{
    static instance _instance;

    QMongoClient(QString url) : _client( uri( qPrintable(url) ) );  
    client _client;
    QMongoDatabase operator[](QString d);
};

class QMongoDatabase
{
    QMongoDatabase(database db) : _database(db);
    database _database;
    QMongoCollection operator [](QString c);
};

class QMongoCollection
{
    QMongoCollection(collection c) : _collection(c);
    collection _collection;
    //create... same as insert()
    //read... same as find_one()
    //update... same as upsert() or update()
    //delete...
    //find... a query will be provided
    QMongoCursor findAll() { cursor c = _collection.find({}); return QMongoCursor(c); };
};

class QMongoCursor
{
    QMongoCursor(cursor c) : _cursor(c);
    //copy/move/assign constructors needed, probably

    cursor _cursor;

    QString data(); //return document contents as JSON string, for instance

    //begin() <-- iterator
    //end() <-- iterator
};

我曾希望这种方法能奏效,而且它确实奏效了,直到出现游标,这会引发编译器错误:

error: call to implicitly-deleted copy constructor of 'mongocxx::v_noabi::cursor'

我的想法是做这样的事情:

QMongoClient client("mongodb://url...");
QMongoDatabase db = client["somedbname"];
QMongoCollection coll = db["somecollection"];
QMongoCursor c = coll.findAll();

//or more abbreviated:
QMongoCursor c = client["somedbname"]["somecollection"].findAll();

//iterate over c here as needed, or send it to another abstraction layer...

我认为这是因为 mongocxx::cursor 对象不应该被传递,当它们超出范围时它们就会被销毁。

例如,当 QMongoCursor::findAll() 完成时,returned 游标将被销毁,并且不能在 QMongoCursor 构造函数中复制。

findAll() 函数在那一刻检索所有文档并 return 它们(结果集的大小可能未知)似乎非常低效。例如,我希望能够一次检索 10 个结果,并通过网络将它们异步分组发送到最终客户端。

所以问题is/are:

我想我缺少一些 C++ 语法或机制,比如移动分配或类似的东西。

有什么想法吗?

好吧,mongocxx::cursor objects 可移动的,但您没有要求移动它,您是要一份副本。尝试:

QMongoCursor(cursor c) : _cursor(std::move(c));

您可能也想为您的 QDatabase 和 QCollection 构造函数执行此操作。

你还应该考虑的一件事是,如果你正在构建更高级别的工具包,你需要密切注意与 clientdatabase、[=14= 相关的生命周期规则],以及 cursor objects。您可能会发现构建类似 shared_ptr 的抽象以确保类型系统强制执行适当的生命周期对您的 usec-case.

是有利的

我们没有让 driver 那样工作,因为我们不想将这个决定强加于人。相反,我们认为它可以而且应该委托给更高级别的抽象,可能就像您正在构建的那样。