How to create and use BSON documents.
Create a Document
From a JSON String
Basic Example
void example() {
{
"a": 1,
"b": 2.0,
"c": "three"
}
)");
EXPECT(doc["a"].get_int32().value == 1);
EXPECT(doc["b"].get_double().value == 2.0);
EXPECT(doc["c"].get_string().value == "three");
}
With Extended JSON
void example() {
{
"a": {"$numberInt": "1"},
"b": {"$numberLong": "2"},
"c": {"$numberDouble": "3"}
}
)");
EXPECT(doc["a"].get_int32().value == 1);
EXPECT(doc["b"].get_int64().value == 2);
EXPECT(doc["c"].get_double().value == 3.0);
}
With a Sub-Document
void example() {
{
"v": {"key": "value"}
}
)");
}
With a Sub-Array
void example() {
{
"v": [1, 2]
}
)");
}
With a User-Defined Literal
void example() {
EXPECT(a == b);
}
Using the Basic Builder
Basic Example
void example() {
builder.append(
kvp(
"a", std::int32_t{1}),
kvp(
"b", 2.0),
kvp(
"c",
"three"));
}
With make_document
void example() {
kvp(
"a", std::int32_t{1}),
kvp(
"b", 2.0),
kvp(
"c",
"three"));
}
With concatenate
With Multiple Appends
void example() {
builder.append(
kvp(
"a", std::int32_t{1}));
builder.append(
kvp(
"b", 2.0));
builder.append(
kvp(
"c",
"three"));
}
To Create Multiple Documents
void example() {
builder.append(
kvp(
"a", 1));
builder.clear();
builder.append(
kvp(
"b", 2));
}
With a Value Type
void example() {
kvp(
"a", std::int32_t{1}),
kvp(
"b", 2.0),
kvp(
"c",
"three"));
}
With a BSON Type
With a BSON Value
void example() {
std::int32_t{1},
2.0,
"three",
};
kvp(
"a", values[0]),
kvp(
"b", values[1]),
kvp(
"c", values[2]));
}
With a Sub-Document
void example() {
EXPECT(v == subdoc.view());
}
With Multiple Sub-Document Appends
void example() {
std::string keys[] = {"a", "b", "c"};
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
doc.append(
kvp(keys[i], values[i]));
}
}));
}
With a Sub-Array
void example() {
EXPECT(v == subarr.view());
}
With Multiple Sub-Array Appends
void example() {
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
arr.append(values[i]);
}
}));
}
From Raw Bytes
As a View
void example(const std::uint8_t* data, std::size_t length) {
}
As a Value
void example(const std::uint8_t* data, std::size_t length) {
using deleter_type = bsoncxx::document::value::deleter_type;
std::uint8_t* raw = new std::uint8_t[length];
std::copy_n(data, length, raw);
deleter_type deleter = [](std::uint8_t* data) { delete[] data; };
}
Create an Array
From a JSON String
Basic Example
void example() {
[1, 2.0, "three"]
)");
EXPECT(doc["0"].get_int32().value == 1);
EXPECT(doc["1"].get_double().value == 2.0);
EXPECT(doc["2"].get_string().value == "three");
}
With Extended JSON
void example() {
[
{"$numberInt": "1"},
{"$numberLong": "2"},
{"$numberDouble": "3"}
]
)");
EXPECT(doc["0"].get_int32().value == 1);
EXPECT(doc["1"].get_int64().value == 2);
EXPECT(doc["2"].get_double().value == 3.0);
}
With a Sub-Document
void example() {
[
{"key": "value"}
]
)");
}
With a Sub-Array
void example() {
[
[1, 2.0, "three"]
]
)");
}
With a User-Defined Literal
void example() {
EXPECT(a == b);
}
Using the Basic Builder
Basic Example
void example() {
builder.append(std::int32_t{1}, 2.0, "three");
}
With make_document
void example() {
EXPECT(arr[0].get_int32().value == 1);
EXPECT(arr[1].get_double().value == 2.0);
EXPECT(arr[2].get_string().value == "three");
}
With concatenate
With Multiple Appends
void example() {
builder.append(std::int32_t{1});
builder.append(2.0);
builder.append("three");
}
To Create Multiple Documents
void example() {
builder.append(std::int32_t{1});
builder.clear();
builder.append(std::int64_t{2});
EXPECT(a[0].
type() == bsoncxx::type::k_int32);
EXPECT(b[0].
type() == bsoncxx::type::k_int64);
EXPECT(a[0].get_int32().value == 1);
EXPECT(b[0].get_int64().value == 2);
}
With a Value Type
void example() {
EXPECT(arr[0].
type() == bsoncxx::type::k_int32);
EXPECT(arr[1].
type() == bsoncxx::type::k_double);
EXPECT(arr[2].
type() == bsoncxx::type::k_string);
EXPECT(arr[0].get_int32().value == 1);
EXPECT(arr[1].get_double().value == 2.0);
EXPECT(arr[2].get_string().value == "three");
}
With a BSON Type
With a BSON Value
void example() {
std::int32_t{1},
2.0,
"three",
};
}
With a Sub-Document
void example() {
EXPECT(v == subdoc.view());
}
With Multiple Sub-Document Appends
void example() {
std::string keys[] = {"a", "b", "c"};
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
doc.append(
kvp(keys[i], values[i]));
}
});
}
With a Sub-Array
void example() {
EXPECT(v == arr.view());
}
With Multiple Sub-Array Appends
void example() {
std::int32_t values[] = {1, 2, 3};
for (int i = 0; i < 3; ++i) {
arr.append(values[i]);
}
});
}
From Raw Bytes
As a View
void example(const std::uint8_t* data, std::size_t length) {
}
As a Value
void example(const std::uint8_t* data, std::size_t length) {
using deleter_type = bsoncxx::array::value::deleter_type;
std::uint8_t* raw = new std::uint8_t[length];
std::copy_n(data, length, raw);
deleter_type deleter = [](std::uint8_t* data) { delete[] data; };
}
Access a Document Element
By Iteration
Basic Example
switch (e.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "a");
EXPECT(e.get_int32().value == 1);
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "b");
EXPECT(e.get_double().value == 2.0);
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "c");
EXPECT(e.get_string().value == "three");
break;
}
}
}
Using Iterators
EXPECT(doc.begin() != doc.end());
auto iter = doc.begin();
EXPECT(iter == doc.begin());
{
EXPECT(e.key() == "a");
EXPECT(e.get_int32().value == 1);
}
++iter;
EXPECT(iter->key() == "b");
EXPECT(iter->get_int32().value == 2);
{
auto iter_copy = iter++;
EXPECT(iter_copy != iter);
EXPECT(iter_copy->key() == "b");
EXPECT(iter_copy->get_int32() == 2);
}
EXPECT(iter == doc.end());
}
Using Algorithms
EXPECT(std::distance(doc.begin(), doc.end()) == 3);
std::vector<bsoncxx::document::element> elements;
std::copy_if(doc.begin(),
doc.end(),
std::back_inserter(elements),
return e.key() == "a" || e.type() == bsoncxx::type::k_string;
});
EXPECT(elements.size() == 2u);
EXPECT(elements[0].key() == "a");
EXPECT(elements[1].key() == "c");
}
By Key
Using find()
EXPECT(doc.find("a") == doc.begin());
{
auto iter = doc.find("b");
EXPECT(iter != doc.end());
EXPECT(iter->key() == "b");
EXPECT(iter->get_int32().value == 2);
}
EXPECT(doc.find("x") == doc.end());
}
Using the Subscript Operator
EXPECT(doc["a"]);
{
EXPECT(e.key() == "b");
EXPECT(e.get_int32().value == 2);
}
EXPECT(!doc["c"]);
}
Access an Array Element
By Iteration
Basic Example
switch (e.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "0");
EXPECT(e.get_int32().value == 1);
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "1");
EXPECT(e.get_double().value == 2.0);
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "2");
EXPECT(e.get_string().value == "three");
break;
}
}
}
Using Iterators
EXPECT(arr.begin() != arr.end());
auto iter = arr.begin();
EXPECT(iter == arr.begin());
{
EXPECT(e.key() == "0");
EXPECT(e.get_int32().value == 1);
}
++iter;
EXPECT(iter->key() == "1");
EXPECT(iter->get_int32().value == 2);
{
auto iter_copy = iter++;
EXPECT(iter_copy != iter);
EXPECT(iter_copy->key() == "1");
EXPECT(iter_copy->get_int32() == 2);
}
EXPECT(iter == arr.end());
}
Using Algorithms
EXPECT(std::distance(arr.begin(), arr.end()) == 3);
std::vector<bsoncxx::array::element> elements;
std::copy_if(
return e.key() == "0" || e.type() == bsoncxx::type::k_string;
});
EXPECT(elements.size() == 2u);
EXPECT(elements[0].key() == "0");
EXPECT(elements[1].key() == "2");
}
By Key
Using find()
EXPECT(arr.find(0) == arr.begin());
{
auto iter = arr.find(1);
EXPECT(iter != arr.end());
EXPECT(iter->key() == "1");
EXPECT(iter->get_int32().value == 2);
}
EXPECT(arr.find(2) == arr.end());
}
Using the Subscript Operator
EXPECT(arr[0]);
{
EXPECT(e.key() == "1");
EXPECT(e.get_int32().value == 2);
}
EXPECT(!arr[2]);
}
Query an Element
In a Document
For a Single Type
if (e.type() == bsoncxx::type::k_int32) {
EXPECT(e.key() == "a");
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
} else {
EXPECT(e.key() != "a");
}
}
For Multiple Types
switch (e.type()) {
case bsoncxx::type::k_int32: {
EXPECT(e.key() == "a");
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
break;
}
case bsoncxx::type::k_double: {
EXPECT(e.key() == "b");
EXPECT(v.type_id == bsoncxx::type::k_double);
EXPECT(v.value == 2.0);
break;
}
case bsoncxx::type::k_string: {
EXPECT(e.key() == "c");
EXPECT(v.type_id == bsoncxx::type::k_string);
EXPECT(v.value == "three");
break;
}
}
}
In an Array
For Single Type
if (e.type() == bsoncxx::type::k_int32) {
EXPECT(e.key() == "0");
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
} else {
EXPECT(e.key() != "0");
}
}
For Multiple Types
switch (e.type()) {
case bsoncxx::type::k_int32: {
EXPECT(e.key() == "0");
EXPECT(v.type_id == bsoncxx::type::k_int32);
EXPECT(v.value == 1);
break;
}
case bsoncxx::type::k_double: {
EXPECT(e.key() == "1");
EXPECT(v.type_id == bsoncxx::type::k_double);
EXPECT(v.value == 2.0);
break;
}
case bsoncxx::type::k_string: {
EXPECT(e.key() == "2");
EXPECT(v.type_id == bsoncxx::type::k_string);
EXPECT(v.value == "three");
break;
}
}
}
Comparison
By Type
std::int32_t a{1};
std::int64_t b{2};
if (e.type() == bsoncxx::type::k_int32) {
EXPECT(e.key() == "a");
EXPECT(e.get_int32().value == a);
} else if (e.type() == bsoncxx::type::k_int64) {
EXPECT(e.key() == "b");
EXPECT(e.get_int64().value == b);
}
}
By BSON Value
if (e.get_value() == a) {
EXPECT(e.key() == "a");
} else if (e.get_value() == b) {
EXPECT(e.key() == "b");
}
if (e == va) {
EXPECT(e.key() == "a");
} else if (e == vb) {
EXPECT(e.key() == "b");
}
}
Obtain a BSON Value
From a BSON Type
As a View
void example() {
view_type v;
EXPECT(v.type() == bsoncxx::type::k_null);
v = view_type(v0);
EXPECT(v.type() == v0.type_id);
EXPECT(v.get_int32() == v0);
v = view_type(v1);
EXPECT(v.type() == v1.type_id);
EXPECT(v.get_double() == v1);
v = view_type(v2);
EXPECT(v.type() == v2.type_id);
EXPECT(v.get_string() == v2);
}
As a Value
void example() {
EXPECT(v.view().type() == bsoncxx::type::k_null);
EXPECT(v.view().type() == bsoncxx::type::k_int32);
EXPECT(v.view().get_int32().value == 1);
EXPECT(v.view().type() == bsoncxx::type::k_double);
EXPECT(v.view().get_double().value == 2.0);
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "three");
}
From a Document Element
As a View
EXPECT(v.type() == e.type());
switch (v.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "a");
EXPECT(v.get_int32() == e.get_int32());
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "b");
EXPECT(v.get_double() == e.get_double());
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "c");
EXPECT(v.get_string() == e.get_string());
break;
}
}
As a Value
void example() {
EXPECT(v.view().type() == bsoncxx::type::k_null);
["v"]
.get_owning_value();
EXPECT(v.view().type() == bsoncxx::type::k_document);
v = v.view().get_document().value["key"].get_string();
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "value");
}
From an Array Element
As a View
EXPECT(v.type() == e.type());
switch (v.type()) {
case bsoncxx::type::k_int32:
EXPECT(e.key() == "0");
EXPECT(v.get_int32() == e.get_int32());
break;
case bsoncxx::type::k_double:
EXPECT(e.key() == "1");
EXPECT(v.get_double() == e.get_double());
break;
case bsoncxx::type::k_string:
EXPECT(e.key() == "2");
EXPECT(v.get_string() == e.get_string());
break;
}
}
As a Value
void example() {
EXPECT(v.view().type() == bsoncxx::type::k_null);
["v"]
.get_owning_value();
EXPECT(v.view().type() == bsoncxx::type::k_array);
v = v.view().get_array().value[0].get_string();
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "value");
}
From a Value Type
void example() {
EXPECT(v.view().type() == bsoncxx::type::k_null);
v = std::int32_t{1};
EXPECT(v.view().type() == bsoncxx::type::k_int32);
EXPECT(v.view().get_int32().value == 1);
v = 2.0;
EXPECT(v.view().type() == bsoncxx::type::k_double);
EXPECT(v.view().get_double().value == 2.0);
v = std::string("three");
EXPECT(v.view().type() == bsoncxx::type::k_string);
EXPECT(v.view().get_string().value == "three");
}
With make_value
void example() {
{
view_type v = owner.view();
EXPECT(v.type() == bsoncxx::type::k_int32);
EXPECT(v.get_int32().value == 1);
}
{
view_type v = owner.
view();
EXPECT(v.type() == bsoncxx::type::k_int64);
EXPECT(v.get_int64().value == 2);
}
{
view_type v = owner.view();
EXPECT(v.type() == bsoncxx::type::k_string);
EXPECT(v.get_string().value == "three");
}
}
Convert to a JSON String
From a Document
void example() {
std::uint8_t data[]{"three"};
auto data_len = static_cast<std::uint32_t>(sizeof(data) - 1u);
kvp(
"a", std::int32_t{1}),
kvp(
"b", std::int64_t{2}),
);
{
EXPECT(
json ==
R"({ "a" : { "$numberInt" : "1" }, "b" : { "$numberLong" : "2" }, "c" : { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } })");
}
{
EXPECT(
json ==
R"({ "a" : 1, "b" : 2, "c" : { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } })");
}
{
EXPECT(json == R"({ "a" : 1, "b" : 2, "c" : { "$binary" : "dGhyZWU=", "$type" : "00" } })");
}
{
EXPECT(a == b);
}
}
From an Array
void example() {
std::uint8_t data[]{"three"};
std::uint32_t data_len{5u};
std::int32_t{1},
std::int64_t{2},
binary
);
{
EXPECT(
json ==
R"([ { "$numberInt" : "1" }, { "$numberLong" : "2" }, { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } ])");
}
{
EXPECT(json == R"([ 1, 2, { "$binary" : { "base64" : "dGhyZWU=", "subType" : "00" } } ])");
}
{
EXPECT(json == R"([ 1, 2, { "$binary" : "dGhyZWU=", "$type" : "00" } ])");
}
{
EXPECT(a == b);
}
}