1

I have the following function that gets a value out of a BSON document when given a sequence of keys:

bsoncxx::document::element deepFieldAccess(bsoncxx::document::view bsonObj, const std::vector<std::string>& path) {

    if (path.empty())
        return {};

    auto keysIter = path.begin();
    const auto keysEnd = path.end();

    auto currElement = bsonObj[*(keysIter++)];
    while (currElement && (keysIter != keysEnd))
        currElement = currElement[*(keysIter++)];

    return currElement;
}

The returned bsoncxx::document::element can hold a value of any type (int32, document, array, utf8, etc). How can I write this element to the console via std::cout?

Ideally, I would just have to do:

bsoncxx::document::element myElement = deepFieldAccess(bsonObjView, currQuery);
std::cout << myElement << std::endl;
PlsWork
  • 1,958
  • 1
  • 19
  • 31

3 Answers3

1

We can't print bsoncxx::document::element, but we can print bsoncxx::document::view. So just convert one into the other and clean up the resulting string. It's ugly and inefficient but works for quickly looking up the value of a bsoncxx::document::element.

std::string turnQueryResultIntoString(bsoncxx::document::element queryResult) {

    // check if no result for this query was found
    if (!queryResult) {
        return "[NO QUERY RESULT]";
    }

    // hax
    bsoncxx::builder::basic::document basic_builder{};
    basic_builder.append(bsoncxx::builder::basic::kvp("Your Query Result is the following value ", queryResult.get_value()));

    // clean up resulting string
    std::string rawResult = bsoncxx::to_json(basic_builder.view());
    std::string frontPartRemoved = rawResult.substr(rawResult.find(":") + 2);
    std::string backPartRemoved = frontPartRemoved.substr(0, frontPartRemoved.size() - 2);

    return backPartRemoved;
}
PlsWork
  • 1,958
  • 1
  • 19
  • 31
1

maybe you mean like this ?

bsoncxx::document::element myElement = deepFieldAccess(bsonObjView, currQuery);
std::cout << myElement.get_utf8().value.to_string() << std::endl;
Edo Sulai
  • 9
  • 3
0

The bsoncxx::document::view type has a defined conversion to JSON, represented as a std::string by way of the function bsoncxx::to_json in the bsoncxx/json.hpp header. The individual b_xyz types do not offer such a conversion, because elements not contained within a document or array structure aren't necessarily JSON. You are free though to form your own to_string function, and define it for each of the declared BSON types.

acm
  • 12,183
  • 5
  • 39
  • 68
  • So we can print views (as shown for example [here](https://github.com/mongodb/mongo-cxx-driver/blob/fc9a44325e03bb8bb166e814caeb23413b4ba7af/examples/bsoncxx/view_and_value.cpp#L56)). Is it possible to convert the bsoncxx::document::element to a view and then print it? All I want is to inspect what the above function returns, is there some other built in way to do it? – PlsWork Dec 04 '19 at 12:39
  • Could you elaborate on what you mean by "because elements not contained within a document or array structure aren't necessarily JSON"? As far as I understand, all the elements I want to print are contained in a document (the above function gets the elements out of a `bsoncxx::document::view`). – PlsWork Dec 04 '19 at 12:48
  • @AnnaVopureta - The point is that perhaps only documents and arrays have a valid representation as JSON. It isn't clear, for instance, that a raw string not contained within `{ ... }` or `[ ... ]` is actually JSON. Opinions differ. So how should the `to_json` function handle the `b_utf8` type, for instance? The driver takes a conservative approach and declares that only `document` like types have a canonical transformation to JSON. If you want to write your own `to_string` function, just provide an overload for each `b_` type and make it do whatever you like. – acm Dec 04 '19 at 15:46
  • So after I overload each `b_` type `to_string` function, I can just do `std::cout << myElement;` where `bsoncxx::document::element myElement = deepFieldAccess(bsonObjView, currQuery);` ? I updated the question with an example. – PlsWork Dec 04 '19 at 16:30
  • Well, for that exact syntax you would need to write overloads for `std::ostream`. Like `std::ostream& operator<<(std::ostream& stream, const bsoncxx::b_double& value)` and `std::ostream& opoerator<<(std::ostream& stream, const bsoncxx::b_utf8& value)`, etc. Then that would work as written. – acm Dec 04 '19 at 16:32
  • What do you think about the solution I posted, do you see any issues with it? Can you imagine some case where it could fail? – PlsWork Dec 04 '19 at 18:27