4

I have a document that looks like this:

{
    "_id" : ObjectId("5bd37e0128f41363c0006ac2"),
    "source" : "Forge",
    "data" : [ 
        {
            "symbol" : "EURUSD",
            "bid" : 1.14021,
            "ask" : 1.14024,
            "price" : 1.14023,
            "timestamp" : 1540587008
        }
    ]
}

I want to get the data part out of the bson document, which I'm doing by this code:

auto dataDocument = view["data"].get_value().get_document();
auto textMessage = bsoncxx::to_json(dataDocument);

However the output when field data is an array as in the example is this:

{
    "0": {
        "symbol": "EURUSD",
        "bid": 1.1405199999999999783,
        "ask": 1.1405300000000000438,
        "price": 1.1405300000000000438,
        "timestamp": 1540580136
    }
}

Instead of this (correct):

[{
        "symbol": "EURUSD",
        "bid": 1.14056,
        "ask": 1.14057,
        "price": 1.14057,
        "timestamp": 1540580927
    }
]

How come the brackets are removed and instead a "0" field is put there instead?

If I do a to_json on the whole document the array is kept, its only when I do to_json on the field data which is an array the error happens.

Any ideas?

Update, here's a working example which reproduce my issue:

#include <mongocxx/instance.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>

int main()
{
    mongocxx::instance inst{};
    auto conn = mongocxx::client{ mongocxx::uri{} };
    auto collection = conn["QuantBot"]["test"];

    auto jsonDoc = R"(    
    {
        "source" : "Forge",
        "data" : [ 
            {
                "symbol" : "EURUSD",
                "bid" : 1.13875,
                "ask" : 1.13925,
                "price" : 1.139,
                "timestamp" : 1540758149
            }
        ]
    }
    )";

    auto bsonDocument = bsoncxx::from_json(jsonDoc);
    collection.insert_one(bsonDocument.view());

    auto cursor = std::make_unique<mongocxx::cursor>(collection.find({}));
    auto cursorIt = std::make_unique<mongocxx::cursor::iterator>(cursor->begin());
    auto view = bsoncxx::document::view(**cursorIt);
    auto dataDocument = view["data"].get_value().get_document();
    auto textMessage = bsoncxx::to_json(dataDocument);
}
Zeiko
  • 41
  • 4

1 Answers1

2

I believe the problem is here: get_value().get_document(). Try making that say get_value().get_array() instead. Also note that you should be checking the type of the value returned by get_value before calling any methods on it. This is working more by good luck than by good design. The reason that you are seeing a literal zero there is because BSON arrays are represented as documents with integral keys. You have, effectively, cast an array to a document, so it is printing as a document with numeric keys, instead of an array as intended.

acm
  • 12,183
  • 5
  • 39
  • 68
  • Thanks for feedback, unfortunately does get_value().get_array().value and get_array().value produce the same output as before. – Zeiko Oct 30 '18 at 19:47
  • 1
    @Zeiko - Could you post a complete compilable example that demo's the problem. That will make it a lot easier for me to try out on my side and see what is happening. – acm Oct 31 '18 at 13:12
  • Of course, thank for helping out, here's an complete example thats reproduces my issue: – Zeiko Nov 02 '18 at 00:02
  • 3
    @Zeiko - Sorry for the delay getting back to you. You are correct. There does not appear to be an overload of `to_json` that accepts an `array::view`, which is what would be required. I think this is an oversight. Could you please file a ticket at https://jira.mongodb.org/projects/CXX requesting the addition of this feature? It should be easy to add since the C driver offers http://mongoc.org/libbson/current/bson_array_as_json.html, which I believe would do what you want. We just need to expose the C++ driver level wrapper around it. – acm Nov 07 '18 at 19:11
  • Thanks for helping out, I'll create a ticket! – Zeiko Dec 20 '18 at 22:23