为什么find_one在MongoDB C ++中不起作用?

时间:2015-11-21 14:00:07

标签: c++ mongodb

我有一个使用mongo shell创建的MongoDB 3.0.7数据库。以下工作正常:

% mongo test
> vs = db.myCollection.findOne({"somefield.subfield": "somevalue"})

但是当我在C ++中这样做时:

    mongocxx::instance inst{};
    mongocxx::client conn{};
    auto db = conn["test"];
    bsoncxx::stdx::optional< bsoncxx::document::value> docObj;

    try {
        docObj =
                db["myCollection"]
                .find_one(document{} <<
                          "somefield.subfield" << "someValue" <<
                          bsoncxx::builder::stream::finalize);
    } catch (mongocxx::exception::operation e) {
        std::cerr << "Retrieval failed (and exception thrown)";
    }

    if (docObj == bsoncxx::stdx::nullopt)
        std::cerr << "Failed to find object";

我得到“找不到对象”。我在这里缺少什么?

更新: 2015年11月23日,10:00

我安装了最新的cxx驱动程序(0.3.0),并进行了以下更改:

    mongocxx::instance inst{};
    mongocxx::client *connPtr;
    bsoncxx::stdx::string_view connectionString("mongodb://localhost");
    connPtr = new mongocxx::client(mongocxx::uri(connectionString));
    auto db = connPtr->database("test");;
    bsoncxx::stdx::optional< bsoncxx::document::value> docObj;

    try {
        docObj =
                db["myCollection"]
                .find_one(document{} <<
                          "somefield.subfield" << "someValue" <<
                          bsoncxx::builder::stream::finalize);
    } catch (mongocxx::exception::operation e) {
        std::cerr << "Retrieval failed (and exception thrown)";
    }

    if (docObj == bsoncxx::stdx::nullopt)
        std::cerr << "Failed to find object";

我回到了完全相同的事情。调用db.list_collections(document{})不会检索到任何结果。

1 个答案:

答案 0 :(得分:1)

bsoncxx库有两种文档类型,视图和值。 document::value包含实际的文档数据,而document::view只是对某些基础value的引用。 Value必须比使用它们的view更长。

新的c ++ 11驱动程序中存在一个错误,其中传递document::value的方式。此代码生成document::value

document{} << "someField" << "someValue" << finalize;

collection.find_one()方法将document::viewdocument::values隐式转换为document::views。不幸的是,这意味着如果您在调用find_one()时动态构建文档,如上所述,您可以自己开枪:

collection.find_one(document{} << "someField" << "someValue" << finalize);

finalize制作一个临时document::value,然后find_one将其转换为document::view。临时的value会被丢弃在地板上,让view value - 更少,就像一个悬垂的指针。

解决方法是在单独的调用中创建您的值,并保留它:

document::value doc = document{} << "someField" << "someValue" << finalize;
collection.find_one(doc.view());

我怀疑这是导致查询失败的原因;如果没有,那么就可以使你的代码具有弹性!

您可以跟踪this ticket以查找此问题的真正修复方法。