Капли в MongoCxx - PullRequest
       32

Капли в MongoCxx

0 голосов
/ 14 апреля 2020

В настоящее время я пытаюсь написать функции C ++, которые позволяют мне помещать и получать большие двоичные объекты (большие двоичные объекты) в базу данных MongoDB и из нее.
Конечная цель состоит в том, чтобы иметь две функции, подобные этой:

QString store_blob(const QString& mongodb_uri, const QByteArray& blob, const QString& target_id = "");
QByteArray retrieve_blob(const QString& mongodb_uri, const QString& id);

(Типы Qt не имеют значения для этого вопроса.)

Сначала рассматриваемые двоичные объекты будут чем-то вроде двоичных данных PNG, но позже мне придется хранить данные большего размера. воксельные изображения (возможно, несколько миллионов ячеек, каждая из которых может содержать блок данных, другими словами, большой файл).
Таким образом, я хочу сделать эти функции эффективными, используя как можно меньше серверного пространства, как можно меньше данных, передаваемых по сети, и в качестве вторичной цели, как можно меньше копируем в моей программе (хотя эта последняя, ​​вероятно, не является критической точкой).

Для этого я использую mongocxx-водитель. Теперь проблема в том, что я ничего не нашел, как конкретно хранить большие двоичные объекты.
Учебники, такие как , или , это , похоже, фокусируются на простых данных, только с небольшими массивами. * К сожалению, большинство записей в документации не предоставляют много информации.

Мои текущие тесты пытаются работать с классом обычного массива:
Тест для записи данных:

bsoncxx::types::b_oid write_blob()
{
    mongocxx::uri uri("mongodb://localhost:27017");
    mongocxx::client client(uri);
    mongocxx::database database = client["test_database"];
    mongocxx::collection collection = database["test_collection"];

    std::vector<uint8_t> elements = {7, 8, 9};
    auto doc = bsoncxx::builder::basic::document{};
    doc.append(bsoncxx::builder::basic::kvp("data", [&elements](bsoncxx::builder::basic::sub_array child) {
        for (const auto& element : elements) {
            child.append(element);
        }
    }));

    bsoncxx::document::value value = doc.extract();

    bsoncxx::stdx::optional<mongocxx::result::insert_one> result =
        collection.insert_one(value.view());

    std::cout << "id is: " << result->inserted_id().get_oid().value.to_string() << std::endl;

    return result->inserted_id().get_oid();
}

Тест для получения данных:

void read_blob(bsoncxx::types::b_oid id)
{
    mongocxx::uri uri("mongodb://localhost:27017");
    mongocxx::client client(uri);
    mongocxx::database database = client["test_database"];
    mongocxx::collection collection = database["test_collection"];

    bsoncxx::stdx::optional<bsoncxx::document::value> value = collection.find_one(
        bsoncxx::builder::stream::document{} << "_id" << id << bsoncxx::builder::stream::finalize);

    for(size_t i=0; i<value->view()["data"].length(); i++)
    {
        if(value->view()["data"][i].type() == bsoncxx::type::k_int32)
        {
            std::cout << value->view()["data"][i].get_int32() << std::endl;
        }
    }
}

Мои проблемы с ними:

  1. Я не уверен, эффективно ли они хранятся и доставляются.
  2. Я не уверен, насколько это близко к наилучшей практике.
  3. Изначально я начинаю с vector над uint8_t, что означает, что я надеюсь напрямую вставить байтовый тип в массив. Однако, как показывает код получающего конца, на самом деле хранятся 32-битные целые числа. Я мог бы упаковать четыре байта в одно такое целое число, но я надеюсь сделать это более напрямую. Кроме того, это потребует от меня дополнительного хранения фактического размера байта в поле, поскольку фактический размер байта может не делиться на четыре.
  4. Код, как он есть, содержит ошибку: итерация в принимающей функции выходит из-под контроля. length() возвращает размер массива, который в моем примере имеет нечетную длину 54 (значение, которое я не могу объяснить, поскольку три целых числа из четырех байтов имели бы 12 байтов = 96 бит, что заставляет меня ожидать массив хранится в ASCII с разделителями). Теперь я могу хранить количество байтов в качестве дополнительного поля, но это выглядит грязно. Есть ли более эффективный способ сделать это? Я не видел ни одного метода, такого как size(), который бы на самом деле возвращал количество записей в документации.

В идеале я надеюсь, что кто-то переписывает мои тестовые функции.
Обратите внимание, что я довольно новичок в работе с драйвером mongocxx или библиотеками баз данных в целом.

Также обратите внимание, что я уже задавал этот вопрос на форумах mongoDB.

...