Docs 菜单
Docs 主页
/ / /
C++ 驱动程序

使用 BSON

在此页面上

  • 文档生成器
  • 列表生成器
  • “一次性”构建器函数
  • 基本生成器
  • 在循环中构建数组
  • 拥有 BSON 文档
  • 非拥有 BSON 文档(视图)
  • 可选拥有的 BSON 文档 (view_or_value)
  • BSON 文档生命周期
  • 打印 BSON 文档
  • 从 BSON 文档中获取字段
  • BSON类型

mongocxx驾驶员附带一个新的库 bsoncxx。 本文将Go此库中的一些不同类型,以及如何以及何时使用每种类型。 有关更多信息和示例代码,请参阅我们的 示例。

  1. 文档生成器

  2. 拥有 BSON 文档(值)

  3. 非拥有 BSON 文档(视图)

  4. 可选拥有的 BSON 文档 (view_or_value)

  5. BSON 文档生命周期

  6. 打印 BSON 文档

  7. 从 BSON 文档中获取字段

  8. BSON类型

bsoncxx 库提供了四个用于构建 BSON 的接口:一次性函数、基本构建器、列表构建器和基于流的构建器。

bsoncxx::builder::basic::document bsoncxx::builder::stream::document

创建 BSON 文档和数组的各种方法都是等效的。 所有接口都将提供相同的结果,使用哪个接口的选择完全取决于美观。

创建 BSON 文档或数组的最简单方法是使用类似 JSON 的列表构建器:

// { "hello": "world" }
bsoncxx::builder::list list_builder = {"hello", "world"};
bsoncxx::document::view document = list_builder.view().get_document();

此示例显示了列表生成器的更高级用法。

“一次性”构建器在单次调用中创建文档和数组。 当不需要使用其他逻辑(例如条件或循环)来创建对象时,可以使用这些对象:

using bsoncxx::builder::basic::kvp;
// { "hello": "world" }
bsoncxx::document::value document = bsoncxx::builder::basic::make_document(kvp("hello", "world"));
using bsoncxx::builder::basic::kvp;
// { "hello" : "world" }
bsoncxx::builder::basic::document basic_builder{};
basic_builder.append(kvp("hello", "world"));
bsoncxx::document::value document = basic_builder.extract();

此示例展示了基本构建器的更高级用法。

// { "hello" : "world" }
using bsoncxx::builder::stream;
bsoncxx::document::value document = stream::document{} << "hello" << "world" << stream::finalize;

此示例 显示了流构建器的更高级用法。

注意

为了正确附加每个新值,流构建器需要跟踪当前文档的状态,包括嵌套级别和附加到构建器的最新值的类型。 在此状态更改后,不得重复使用初始流构建器,这意味着如果使用流构建器跨多个语句构建文档,则必须将中间值存储在新变量中。 由于正确执行此操作很困难,并且编译器错误消息可能会令人困惑,因此不鼓励使用流构建器。 我们建议改用基本构建器或一次性构建器函数。

有时需要使用循环来构建数组。 使用基本构建器,只需在循环内调用 append即可构建顶层数组:

// [ 1, 2, 3 ]
const auto elements = {1, 2, 3};
auto array_builder = bsoncxx::builder::basic::array{};
for (const auto& element : elements) {
array_builder.append(element);
}

要在循环中构建子数组,请将Lambda传递给 append(如果子数组包含在文档而不是数组中,则作为 kvp 的第二个参数):

// { "foo" : [ 1, 2, 3 ] }
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::sub_array;
const auto elements = {1, 2, 3};
auto doc = bsoncxx::builder::basic::document{};
doc.append(kvp("foo", [&elements](sub_array child) {
for (const auto& element : elements) {
child.append(element);
}
}));

使用流构建器构建数组时,请务必注意在流构建器上使用<<操作符的返回类型并不统一。 要在循环中正确构建数组,当类型更改时,应将流构建器返回的中间值存储在变量中。 使用循环从流构建器构建数组的一次尝试可能如下所示:

// { "subdocs" : [ { "key" : 1 }, { "key" : 2 }, { "key" : 3 } ], "another_key" : 42 }
using namespace bsoncxx;
builder::stream::document builder{};
auto in_array = builder << "subdocs" << builder::stream::open_array;
for (auto&& e : {1, 2, 3}) {
in_array = in_array << builder::stream::open_document << "key" << e
<< builder::stream::close_document;
}
auto after_array = in_array << builder::stream::close_array;
after_array << "another_key" << 42;
document::value doc = after_array << builder::stream::finalize;
std::cout << to_json(doc) << std::endl;

注意

任何流操作的结果都应该被捕获,因此,如果您想将上述 for 循环中的单个语句拆分为多个语句,则必须捕获每个中间结果。 此外,循环体内的最后一条语句应将其结果赋回 in_array 对象,以便循环以一致的状态重新启动:

for (auto && e : {1, 2, 3}) {
auto open_state = in_array << builder::stream::open_document;
auto temp_state = open_state << "key" << e;
in_array = temp_state << builder::stream::close_document;
}

bsoncxx::document::value

该类型表示实际的 BSON 文档,即拥有数据缓冲区的文档。 可以通过调用extract()从构建器构建这些文档:

bsoncxx::document::value basic_doc{basic_builder.extract()};
bsoncxx::document::value stream_doc{stream_builder.extract()};

调用extract()后,该构建器处于移出状态,不应使用。

可以使用流构建器接口和finalize令牌在一行中创建bsoncxx::document::valuefinalize从临时流构建器返回document::value

// { "finalize" : "is nifty" }
bsoncxx::document::value one_line = bsoncxx::builder::stream::document{} << "finalize" << "is nifty" << bsoncxx::builder::stream::finalize;

bsoncxx::document::view

该类型是所属bsoncxx::document::value的视图。

bsoncxx::document::view document_view{document_value.view()};

document::value也会隐式转换为document::view

bsoncxx::document::view document_view{document_value};

在性能关键型代码中,传递视图比使用值更可取,因为可以避免过多的复制。 此外,通过传递文档视图,我们还可以多次使用该文档:

// { "copies" : { "$gt" : 100 } }
auto query_value = document{} << "copies" << open_document << "$gt" << 100 << close_document << finalize;
// Run the same query across different collections
auto collection1 = db["science_fiction"];
auto cursor1 = collection1.find(query_value.view());
auto collection2 = db["cookbooks"];
auto cursor2 = collection2.find(query_value.view());

许多驾驶员方法都采用document::view_or_value 参数,示例 run_command:

bsoncxx::document::value run_command(bsoncxx::document::view_or_value command);

此类方法可以采用document::viewdocument::value 。 如果传入document::value ,则必须通过右值引用传递,以便将文档的所有权转移给该方法。

document::value ping = document{} << "ping" << 1 << finalize;
// You can pass a document::view into run_command()
db.run_command(ping.view());
// Or you can move in a document::value
db.run_command(std::move(ping));

您不需要为了使用驱动程序而直接创建view_or_value类型。 它们是作为一种便捷方法提供的,允许驱动程序方法以拥有或非拥有的方式获取文档。 view_or_value类型还有助于缓解下一节中讨论的一些生命周期问题。

document::value类型的寿命必须比使用它们的任何document::view类型的寿命长。 如果底层值被清理,视图将留下一个悬空指针。 考虑一个返回新建文档视图的方法:

bsoncxx::document::view make_a_dangling_view() {
bsoncxx::builder::basic::document builder{};
builder.append(kvp("hello", "world"));
// This creates a document::value on the stack that will disappear when we return.
bsoncxx::document::value stack_value{builder.extract()};
// We're returning a view of the local value
return stack_value.view(); // Bad!!
}

此方法会返回不应使用的悬空视图:

// This view contains a dangling pointer
bsoncxx::document::view dangling_view = make_a_dangling_view(); // Warning!!

尝试通过构建器创建视图同样会创建危险的视图对象,因为不会捕获从extract()返回的临时值:

bsoncxx::builder::stream::document temp_builder{};
temp_builder << "oh" << "no";
bsoncxx::document::view dangling_view = temp_builder.extract().view(); // Bad!!

bsoncxx::to_json()

bsoncxx 库提供了一种将 BSON 文档转换为字符串以便于检查的便捷方法:

bsoncxx::document::value = document{} << "I am" << "a BSON document" << finalize;
std::cout << bsoncxx::to_json(doc.view()) << std::endl;

有一个类似的方法 from_json() ,从现有JSON字符串构建文档::values。

[ ] 操作符进入 BSON 文档以检索值:

// doc_view = { "store" : "Key Foods", "fruits" : [ "apple", "banana" ] }
auto store = doc_view["store"];
auto first_fruit = doc_view["fruits"][0];

此操作会返回一个bsoncxx::document::element ,其中包含实际所需的值:

document::element store_ele{doc_view["store"]};
if (store_ele) {
// this block will only execute if "store" was found in the document
std::cout << "Examining inventory at " << to_json(store_ele.get_value()) << std::endl;
}

此 示例 更详细地展示了此功能 和 此示例。

BSON规范 提供了支持的类型列表。这些在C++中使用 b_xxx 表示 类型包装器。

某些BSON types不一定有要包装的原生表示形式,而是通过特殊类实现的。

bsoncxx::decimal128类表示128位 IEEE 754 - 2008十进制浮点值。 我们希望用户能够将这些值与字符串相互转换,但如果用户需要转换为原生十进制128类型,则可以访问低位和高位64位值。

您可以在bsoncxx::decimal128 此示例 中了解如何使用 。

后退

连接池