BSON との連携
項目一覧
mongocx ドライバーには新しいライブラリ bsoncx が付属します。 この記事では、このライブラリにあるさまざまな型の一部と、それぞれを使用する方法とタイミングについて説明しGo 。 詳細とサンプル コードについては、 の例を参照してください。
ドキュメント ビルダ
bsoncx ライブラリは、BSON を構築するための 4 つのインターフェースを提供します。いずれも、ワンオフ関数、基本ビルダ、リスト ビルダ、ストリームベースのビルダです。
bsoncx::Builder::basic::document bsoncx::Builder::stream::document
BSON ドキュメントと配列を作成するさまざまな方法はすべて同等です。 すべてのインターフェースは同じ結果を提供します。使用するインターフェースの選択は完全に存在します。
リストビルダ
BSON ドキュメントまたは配列を作成する最も簡単な方法は、JSON のようなリスト ビルダを使用することです。
// { "hello": "world" } bsoncxx::builder::list list_builder = {"hello", "world"}; bsoncxx::document::view document = list_builder.view().get_document();
「ワンオフ」ビルダ関数
「One-OFF」ビルダは、1 回の呼び出しでドキュメントと配列を作成します。 これらは、オブジェクトを作成するために追加のロジック(条件やループなど)を使用する必要がない場合に使用できます。
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
の 2 番目の引数として):
// { "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 ループ内の 1 つのステートメントを複数のステートメントに分割する場合は、それぞれの中間結果をキャプチャする必要があります。 さらに、ループ本体内の最後のステートメントは、その結果を 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; }
BSON ドキュメントの所有
このタイプは、データのバッファを所有する実際の BSON ドキュメントを表します。 これらのドキュメントは、 extract()
を呼び出してビルダから構築できます。
bsoncxx::document::value basic_doc{basic_builder.extract()}; bsoncxx::document::value stream_doc{stream_builder.extract()};
extract()
を呼び出した後、ビルダは移動済み状態になるため、使用しないでください。
ストリーム ビルダ インターフェースとfinalize
トークンを使用して、1 行でbsoncxx::document::value
を作成できます。 finalize
は一時ストリーム ビルダからdocument::value
を返します。
// { "finalize" : "is nifty" } bsoncxx::document::value one_line = bsoncxx::builder::stream::document{} << "finalize" << "is nifty" << bsoncxx::builder::stream::finalize;
所有権のない BSON ドキュメント(ビュー)
このタイプは、所有する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());
任意に所有できる BSON ドキュメント(view_or_value)
多くのドライバー メソッドはdocument::view_or_value
パラメーターを受け取ります。たとえば、 run_command は次のようになります。
bsoncxx::document::value run_command(bsoncxx::document::view_or_value command);
このようなメソッドでは、 document::view
またはdocument::value
のいずれかが含まれます。 document::value
が渡される場合、r 値参照によって渡される必要があるため、ドキュメントの所有権は メソッドに転送されます。
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
タイプは、次のセクションで説明するライフタイムの問題の一部を軽減するのにも役立ちます。
BSON ドキュメントの有効期間
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!!
BSON ドキュメントの印刷
bsoncx ライブラリには、BSON ドキュメントを簡単に検査できるように string に変換する便利なメソッドが付属しています。
bsoncxx::document::value = document{} << "I am" << "a BSON document" << finalize; std::cout << bsoncxx::to_json(doc.view()) << std::endl;
from_json() という類似メソッドもあります。 、既存の JSON string からドキュメント:: 値を構築します。
BSON ドキュメントからのフィールドの取得
[ ] 演算子は、値を検索するために 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 types
BSON 仕様 サポートされているタイプのリストを提供します。これらは b_XX を使用して C++ では表されます 型ラッパー。
一部の BSON types は必ずしもラップするネイティブ表現を持つ必要はなく、特殊なクラス経由で実装されます。
Decimal128
bsoncxx::decimal128
クラスは、 128ビット IEEE 754 - 2008の 10 進数浮動小数点値を表します。 ユーザーはこれらを string に変換したり、string から変換したりすることを想定していますが、ユーザーがネイティブ 10 進数128型に変換する必要がある場合は、64 ビットの低値と高値のビット値にアクセスできます。
bsoncxx::decimal128
この例 では、 との連携方法がわかります。