.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "MONGOC_TUTORIAL" "3" "May 07, 2024" "1.27.1" "libmongoc" .sp This guide offers a brief introduction to the MongoDB C Driver. .sp For more information on the C API, please refer to the \fI\%API Reference\fP\&. .SH INSTALLING .sp For detailed instructions on installing the MongoDB C Driver on a particular platform, please see the \fI\%installation guide\fP\&. .SH STARTING MONGODB .sp To run the examples in this tutorial, MongoDB must be installed and running on \fBlocalhost\fP on the default port, 27017. To check if it is up and running, connect to it with the MongoDB shell. .INDENT 0.0 .INDENT 3.5 .sp .EX $ mongosh \-\-host localhost \-\-port 27017 \-\-quiet Enterprise rs0 [direct: primary] test> db.version() 7.0.0 > .EE .UNINDENT .UNINDENT .SH INCLUDE AND LINK LIBMONGOC IN YOUR C PROGRAM .SS Include mongoc.h .sp All libmongoc\(aqs functions and types are available in one header file. Simply include \fBmongoc/mongoc.h\fP: .INDENT 0.0 .INDENT 3.5 .sp .EX #include .EE .UNINDENT .UNINDENT .SS CMake .sp The libmongoc installation includes a \fI\%CMake config\-file package\fP, so you can use CMake\(aqs \fI\%find_package\fP command to import libmongoc\(aqs CMake target and link to libmongoc (as a shared library): .sp CMakeLists.txt .INDENT 0.0 .INDENT 3.5 .sp .EX # Specify the minimum version you require. find_package (mongoc\-1.0 1.7 REQUIRED) # The \(dqhello_mongoc.c\(dq sample program is shared among four tests. add_executable (hello_mongoc ../../hello_mongoc.c) target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_shared) .EE .UNINDENT .UNINDENT .sp You can also use libmongoc as a static library instead: Use the \fBmongo::mongoc_static\fP CMake target: .INDENT 0.0 .INDENT 3.5 .sp .EX # Specify the minimum version you require. find_package (mongoc\-1.0 1.7 REQUIRED) # The \(dqhello_mongoc.c\(dq sample program is shared among four tests. add_executable (hello_mongoc ../../hello_mongoc.c) target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_static) .EE .UNINDENT .UNINDENT .SS pkg\-config .sp If you\(aqre not using CMake, use \fI\%pkg\-config\fP on the command line to set header and library paths: .INDENT 0.0 .INDENT 3.5 .sp .EX gcc \-o hello_mongoc hello_mongoc.c $(pkg\-config \-\-libs \-\-cflags libmongoc\-1.0) .EE .UNINDENT .UNINDENT .sp Or to statically link to libmongoc: .INDENT 0.0 .INDENT 3.5 .sp .EX gcc \-o hello_mongoc hello_mongoc.c $(pkg\-config \-\-libs \-\-cflags libmongoc\-static\-1.0) .EE .UNINDENT .UNINDENT .SS Specifying header and include paths manually .sp If you aren\(aqt using CMake or pkg\-config, paths and libraries can be managed manually. .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o hello_mongoc hello_mongoc.c \e \-I/usr/local/include/libbson\-1.0 \-I/usr/local/include/libmongoc\-1.0 \e \-lmongoc\-1.0 \-lbson\-1.0 $ ./hello_mongoc { \(dqok\(dq : 1.000000 } .EE .UNINDENT .UNINDENT .sp For Windows users, the code can be compiled and run with the following commands. (This assumes that the MongoDB C Driver has been installed to \fBC:\emongo\-c\-driver\fP; change the include directory as needed.) .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 hello_mongoc.c C:\e> hello_mongoc { \(dqok\(dq : 1.000000 } .EE .UNINDENT .UNINDENT .SH USE LIBMONGOC IN A MICROSOFT VISUAL STUDIO PROJECT .sp See the \fI\%libmongoc and Visual Studio guide\fP\&. .SH MAKING A CONNECTION .sp Access MongoDB with a \fI\%mongoc_client_t\fP\&. It transparently connects to standalone servers, replica sets and sharded clusters on demand. To perform operations on a database or collection, create a \fI\%mongoc_database_t\fP or \fI\%mongoc_collection_t\fP struct from the \fI\%mongoc_client_t\fP\&. .sp At the start of an application, call \fI\%mongoc_init()\fP before any other libmongoc functions. At the end, call the appropriate destroy function for each collection, database, or client handle, in reverse order from how they were constructed. Call \fI\%mongoc_cleanup()\fP before exiting. .sp The example below establishes a connection to a standalone server on \fBlocalhost\fP, registers the client application as \(dqconnect\-example,\(dq and performs a simple command. .sp More information about database operations can be found in the \fI\%CRUD Operations\fP and \fI\%Executing Commands\fP sections. Examples of connecting to replica sets and sharded clusters can be found in the \fI\%Advanced Connections\fP page, while examples of data compression can be found in the \fI\%Data Compression\fP page. .sp hello_mongoc.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main (int argc, char *argv[]) { const char *uri_string = \(dqmongodb://localhost:27017\(dq; mongoc_uri_t *uri; mongoc_client_t *client; mongoc_database_t *database; mongoc_collection_t *collection; bson_t *command, reply, *insert; bson_error_t error; char *str; bool retval; /* * Required to initialize libmongoc\(aqs internals */ mongoc_init (); /* * Optionally get MongoDB URI from command line */ if (argc > 1) { uri_string = argv[1]; } /* * Safely create a MongoDB URI object from the given string */ uri = mongoc_uri_new_with_error (uri_string, &error); if (!uri) { fprintf (stderr, \(dqfailed to parse URI: %s\en\(dq \(dqerror message: %s\en\(dq, uri_string, error.message); return EXIT_FAILURE; } /* * Create a new client instance */ client = mongoc_client_new_from_uri (uri); if (!client) { return EXIT_FAILURE; } /* * Register the application name so we can track it in the profile logs * on the server. This can also be done from the URI (see other examples). */ mongoc_client_set_appname (client, \(dqconnect\-example\(dq); /* * Get a handle on the database \(dqdb_name\(dq and collection \(dqcoll_name\(dq */ database = mongoc_client_get_database (client, \(dqdb_name\(dq); collection = mongoc_client_get_collection (client, \(dqdb_name\(dq, \(dqcoll_name\(dq); /* * Do work. This example pings the database, prints the result as JSON and * performs an insert */ command = BCON_NEW (\(dqping\(dq, BCON_INT32 (1)); retval = mongoc_client_command_simple (client, \(dqadmin\(dq, command, NULL, &reply, &error); if (!retval) { fprintf (stderr, \(dq%s\en\(dq, error.message); return EXIT_FAILURE; } str = bson_as_json (&reply, NULL); printf (\(dq%s\en\(dq, str); insert = BCON_NEW (\(dqhello\(dq, BCON_UTF8 (\(dqworld\(dq)); if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) { fprintf (stderr, \(dq%s\en\(dq, error.message); } bson_destroy (insert); bson_destroy (&reply); bson_destroy (command); bson_free (str); /* * Release our handles and clean up libmongoc */ mongoc_collection_destroy (collection); mongoc_database_destroy (database); mongoc_uri_destroy (uri); mongoc_client_destroy (client); mongoc_cleanup (); return EXIT_SUCCESS; } .EE .UNINDENT .UNINDENT .SH CREATING BSON DOCUMENTS .sp Documents are stored in MongoDB\(aqs data format, BSON. The C driver uses \fI\%libbson\fP to create BSON documents. There are several ways to construct them: appending key\-value pairs, using BCON, or parsing JSON. .SS Appending BSON .sp A BSON document, represented as a \fI\%bson_t\fP in code, can be constructed one field at a time using libbson\(aqs append functions. .sp For example, to create a document like this: .INDENT 0.0 .INDENT 3.5 .sp .EX { born : ISODate(\(dq1906\-12\-09\(dq), died : ISODate(\(dq1992\-01\-01\(dq), name : { first : \(dqGrace\(dq, last : \(dqHopper\(dq }, languages : [ \(dqMATH\-MATIC\(dq, \(dqFLOW\-MATIC\(dq, \(dqCOBOL\(dq ], degrees: [ { degree: \(dqBA\(dq, school: \(dqVassar\(dq }, { degree: \(dqPhD\(dq, school: \(dqYale\(dq } ] } .EE .UNINDENT .UNINDENT .sp Use the following code: .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main (void) { struct tm born = {0}; struct tm died = {0}; const char *lang_names[] = {\(dqMATH\-MATIC\(dq, \(dqFLOW\-MATIC\(dq, \(dqCOBOL\(dq}; const char *schools[] = {\(dqVassar\(dq, \(dqYale\(dq}; const char *degrees[] = {\(dqBA\(dq, \(dqPhD\(dq}; uint32_t i; bson_t *document; bson_t child; bson_array_builder_t *bab; char *str; document = bson_new (); /* * Append { \(dqborn\(dq : ISODate(\(dq1906\-12\-09\(dq) } to the document. * Passing \-1 for the length argument tells libbson to calculate the * string length. */ born.tm_year = 6; /* years are 1900\-based */ born.tm_mon = 11; /* months are 0\-based */ born.tm_mday = 9; bson_append_date_time (document, \(dqborn\(dq, \-1, mktime (&born) * 1000); /* * Append { \(dqdied\(dq : ISODate(\(dq1992\-01\-01\(dq) } to the document. */ died.tm_year = 92; died.tm_mon = 0; died.tm_mday = 1; /* * For convenience, this macro passes length \-1 by default. */ BSON_APPEND_DATE_TIME (document, \(dqdied\(dq, mktime (&died) * 1000); /* * Append a subdocument. */ BSON_APPEND_DOCUMENT_BEGIN (document, \(dqname\(dq, &child); BSON_APPEND_UTF8 (&child, \(dqfirst\(dq, \(dqGrace\(dq); BSON_APPEND_UTF8 (&child, \(dqlast\(dq, \(dqHopper\(dq); bson_append_document_end (document, &child); /* * Append array of strings. Generate keys \(dq0\(dq, \(dq1\(dq, \(dq2\(dq. */ BSON_APPEND_ARRAY_BUILDER_BEGIN (document, \(dqlanguages\(dq, &bab); for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) { bson_array_builder_append_utf8 (bab, lang_names[i], \-1); } bson_append_array_builder_end (document, bab); /* * Array of subdocuments: * degrees: [ { degree: \(dqBA\(dq, school: \(dqVassar\(dq }, ... ] */ BSON_APPEND_ARRAY_BUILDER_BEGIN (document, \(dqdegrees\(dq, &bab); for (i = 0; i < sizeof degrees / sizeof (char *); ++i) { bson_array_builder_append_document_begin (bab, &child); BSON_APPEND_UTF8 (&child, \(dqdegree\(dq, degrees[i]); BSON_APPEND_UTF8 (&child, \(dqschool\(dq, schools[i]); bson_array_builder_append_document_end (bab, &child); } bson_append_array_builder_end (document, bab); /* * Print the document as a JSON string. */ str = bson_as_canonical_extended_json (document, NULL); printf (\(dq%s\en\(dq, str); bson_free (str); /* * Clean up allocated bson documents. */ bson_destroy (document); return 0; } .EE .UNINDENT .UNINDENT .sp See the \fI\%libbson documentation\fP for all of the types that can be appended to a \fI\%bson_t\fP\&. .SS Using BCON .sp \fIBSON C Object Notation\fP, BCON for short, is an alternative way of constructing BSON documents in a manner closer to the intended format. It has less type\-safety than BSON\(aqs append functions but results in less code. .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main (int argc, char *argv[]) { struct tm born = { 0 }; struct tm died = { 0 }; bson_t *document; char *str; born.tm_year = 6; born.tm_mon = 11; born.tm_mday = 9; died.tm_year = 92; died.tm_mon = 0; died.tm_mday = 1; document = BCON_NEW ( \(dqborn\(dq, BCON_DATE_TIME (mktime (&born) * 1000), \(dqdied\(dq, BCON_DATE_TIME (mktime (&died) * 1000), \(dqname\(dq, \(dq{\(dq, \(dqfirst\(dq, BCON_UTF8 (\(dqGrace\(dq), \(dqlast\(dq, BCON_UTF8 (\(dqHopper\(dq), \(dq}\(dq, \(dqlanguages\(dq, \(dq[\(dq, BCON_UTF8 (\(dqMATH\-MATIC\(dq), BCON_UTF8 (\(dqFLOW\-MATIC\(dq), BCON_UTF8 (\(dqCOBOL\(dq), \(dq]\(dq, \(dqdegrees\(dq, \(dq[\(dq, \(dq{\(dq, \(dqdegree\(dq, BCON_UTF8 (\(dqBA\(dq), \(dqschool\(dq, BCON_UTF8 (\(dqVassar\(dq), \(dq}\(dq, \(dq{\(dq, \(dqdegree\(dq, BCON_UTF8 (\(dqPhD\(dq), \(dqschool\(dq, BCON_UTF8 (\(dqYale\(dq), \(dq}\(dq, \(dq]\(dq); /* * Print the document as a JSON string. */ str = bson_as_canonical_extended_json (document, NULL); printf (\(dq%s\en\(dq, str); bson_free (str); /* * Clean up allocated bson documents. */ bson_destroy (document); return 0; } .EE .UNINDENT .UNINDENT .sp Notice that BCON can create arrays, subdocuments and arbitrary fields. .SS Creating BSON from JSON .sp For \fIsingle\fP documents, BSON can be created from JSON strings via \fI\%bson_new_from_json\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main (int argc, char *argv[]) { bson_error_t error; bson_t *bson; char *string; const char *json = \(dq{\e\(dqname\e\(dq: {\e\(dqfirst\e\(dq:\e\(dqGrace\e\(dq, \e\(dqlast\e\(dq:\e\(dqHopper\e\(dq}}\(dq; bson = bson_new_from_json ((const uint8_t *)json, \-1, &error); if (!bson) { fprintf (stderr, \(dq%s\en\(dq, error.message); return EXIT_FAILURE; } string = bson_as_canonical_extended_json (bson, NULL); printf (\(dq%s\en\(dq, string); bson_free (string); return 0; } .EE .UNINDENT .UNINDENT .sp To initialize BSON from a sequence of JSON documents, use \fI\%bson_json_reader_t\fP\&. .SH BASIC CRUD OPERATIONS .sp This section demonstrates the basics of using the C Driver to interact with MongoDB. .SS Inserting a Document .sp To insert documents into a collection, first obtain a handle to a \fBmongoc_collection_t\fP via a \fBmongoc_client_t\fP\&. Then, use \fI\%mongoc_collection_insert_one()\fP to add BSON documents to the collection. This example inserts into the database \(dqmydb\(dq and collection \(dqmycoll\(dq. .sp When finished, ensure that allocated structures are freed by using their respective destroy functions. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; bson_error_t error; bson_oid_t oid; bson_t *doc; mongoc_init (); client = mongoc_client_new (\(dqmongodb://localhost:27017/?appname=insert\-example\(dq); collection = mongoc_client_get_collection (client, \(dqmydb\(dq, \(dqmycoll\(dq); doc = bson_new (); bson_oid_init (&oid, NULL); BSON_APPEND_OID (doc, \(dq_id\(dq, &oid); BSON_APPEND_UTF8 (doc, \(dqhello\(dq, \(dqworld\(dq); if (!mongoc_collection_insert_one ( collection, doc, NULL, NULL, &error)) { fprintf (stderr, \(dq%s\en\(dq, error.message); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .EE .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o insert insert.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./insert .EE .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 insert.c C:\e> insert .EE .UNINDENT .UNINDENT .sp To verify that the insert succeeded, connect with the MongoDB shell. .INDENT 0.0 .INDENT 3.5 .sp .EX $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.find() { \(dq_id\(dq : ObjectId(\(dq55ef43766cb5f36a3bae6ee4\(dq), \(dqhello\(dq : \(dqworld\(dq } > .EE .UNINDENT .UNINDENT .SS Finding a Document .sp To query a MongoDB collection with the C driver, use the function \fI\%mongoc_collection_find_with_opts()\fP\&. This returns a \fI\%cursor\fP to the matching documents. The following examples iterate through the result cursors and print the matches to \fBstdout\fP as JSON strings. .sp Use a document as a query specifier; for example, .INDENT 0.0 .INDENT 3.5 .sp .EX { \(dqcolor\(dq : \(dqred\(dq } .EE .UNINDENT .UNINDENT .sp will match any document with a field named \(dqcolor\(dq with value \(dqred\(dq. An empty document \fB{}\fP can be used to match all documents. .sp This first example uses an empty query specifier to find all documents in the database \(dqmydb\(dq and collection \(dqmycoll\(dq. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; const bson_t *doc; bson_t *query; char *str; mongoc_init (); client = mongoc_client_new (\(dqmongodb://localhost:27017/?appname=find\-example\(dq); collection = mongoc_client_get_collection (client, \(dqmydb\(dq, \(dqmycoll\(dq); query = bson_new (); cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL); while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_canonical_extended_json (doc, NULL); printf (\(dq%s\en\(dq, str); bson_free (str); } bson_destroy (query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .EE .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o find find.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./find { \(dq_id\(dq : { \(dq$oid\(dq : \(dq55ef43766cb5f36a3bae6ee4\(dq }, \(dqhello\(dq : \(dqworld\(dq } .EE .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 find.c C:\e> find { \(dq_id\(dq : { \(dq$oid\(dq : \(dq55ef43766cb5f36a3bae6ee4\(dq }, \(dqhello\(dq : \(dqworld\(dq } .EE .UNINDENT .UNINDENT .sp To look for a specific document, add a specifier to \fBquery\fP\&. This example adds a call to \fBBSON_APPEND_UTF8()\fP to look for all documents matching \fB{\(dqhello\(dq : \(dqworld\(dq}\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; const bson_t *doc; bson_t *query; char *str; mongoc_init (); client = mongoc_client_new ( \(dqmongodb://localhost:27017/?appname=find\-specific\-example\(dq); collection = mongoc_client_get_collection (client, \(dqmydb\(dq, \(dqmycoll\(dq); query = bson_new (); BSON_APPEND_UTF8 (query, \(dqhello\(dq, \(dqworld\(dq); cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL); while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_canonical_extended_json (doc, NULL); printf (\(dq%s\en\(dq, str); bson_free (str); } bson_destroy (query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o find\-specific find\-specific.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./find\-specific { \(dq_id\(dq : { \(dq$oid\(dq : \(dq55ef43766cb5f36a3bae6ee4\(dq }, \(dqhello\(dq : \(dqworld\(dq } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 find\-specific.c C:\e> find\-specific { \(dq_id\(dq : { \(dq$oid\(dq : \(dq55ef43766cb5f36a3bae6ee4\(dq }, \(dqhello\(dq : \(dqworld\(dq } .EE .UNINDENT .UNINDENT .SS Updating a Document .sp This code snippet gives an example of using \fI\%mongoc_collection_update_one()\fP to update the fields of a document. .sp Using the \(dqmydb\(dq database, the following example inserts an example document into the \(dqmycoll\(dq collection. Then, using its \fB_id\fP field, the document is updated with different values and a new field. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (int argc, char *argv[]) { mongoc_collection_t *collection; mongoc_client_t *client; bson_error_t error; bson_oid_t oid; bson_t *doc = NULL; bson_t *update = NULL; bson_t *query = NULL; mongoc_init (); client = mongoc_client_new (\(dqmongodb://localhost:27017/?appname=update\-example\(dq); collection = mongoc_client_get_collection (client, \(dqmydb\(dq, \(dqmycoll\(dq); bson_oid_init (&oid, NULL); doc = BCON_NEW (\(dq_id\(dq, BCON_OID (&oid), \(dqkey\(dq, BCON_UTF8 (\(dqold_value\(dq)); if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) { fprintf (stderr, \(dq%s\en\(dq, error.message); goto fail; } query = BCON_NEW (\(dq_id\(dq, BCON_OID (&oid)); update = BCON_NEW (\(dq$set\(dq, \(dq{\(dq, \(dqkey\(dq, BCON_UTF8 (\(dqnew_value\(dq), \(dqupdated\(dq, BCON_BOOL (true), \(dq}\(dq); if (!mongoc_collection_update_one ( collection, query, update, NULL, NULL, &error)) { fprintf (stderr, \(dq%s\en\(dq, error.message); goto fail; } fail: if (doc) bson_destroy (doc); if (query) bson_destroy (query); if (update) bson_destroy (update); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .EE .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o update update.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./update .EE .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 update.c C:\e> update { \(dq_id\(dq : { \(dq$oid\(dq : \(dq55ef43766cb5f36a3bae6ee4\(dq }, \(dqhello\(dq : \(dqworld\(dq } .EE .UNINDENT .UNINDENT .sp To verify that the update succeeded, connect with the MongoDB shell. .INDENT 0.0 .INDENT 3.5 .sp .EX $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.find({\(dqupdated\(dq : true}) { \(dq_id\(dq : ObjectId(\(dq55ef549236fe322f9490e17b\(dq), \(dqupdated\(dq : true, \(dqkey\(dq : \(dqnew_value\(dq } > .EE .UNINDENT .UNINDENT .SS Deleting a Document .sp This example illustrates the use of \fI\%mongoc_collection_delete_one()\fP to delete a document. .sp The following code inserts a sample document into the database \(dqmydb\(dq and collection \(dqmycoll\(dq. Then, it deletes all documents matching \fB{\(dqhello\(dq : \(dqworld\(dq}\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; bson_error_t error; bson_oid_t oid; bson_t *doc; mongoc_init (); client = mongoc_client_new (\(dqmongodb://localhost:27017/?appname=delete\-example\(dq); collection = mongoc_client_get_collection (client, \(dqtest\(dq, \(dqtest\(dq); doc = bson_new (); bson_oid_init (&oid, NULL); BSON_APPEND_OID (doc, \(dq_id\(dq, &oid); BSON_APPEND_UTF8 (doc, \(dqhello\(dq, \(dqworld\(dq); if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) { fprintf (stderr, \(dqInsert failed: %s\en\(dq, error.message); } bson_destroy (doc); doc = bson_new (); BSON_APPEND_OID (doc, \(dq_id\(dq, &oid); if (!mongoc_collection_delete_one ( collection, doc, NULL, NULL, &error)) { fprintf (stderr, \(dqDelete failed: %s\en\(dq, error.message); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .EE .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o delete delete.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./delete .EE .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 delete.c C:\e> delete .EE .UNINDENT .UNINDENT .sp Use the MongoDB shell to prove that the documents have been removed successfully. .INDENT 0.0 .INDENT 3.5 .sp .EX $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.count({\(dqhello\(dq : \(dqworld\(dq}) 0 > .EE .UNINDENT .UNINDENT .SS Counting Documents .sp Counting the number of documents in a MongoDB collection is similar to performing a \fI\%find operation\fP\&. This example counts the number of documents matching \fB{\(dqhello\(dq : \(dqworld\(dq}\fP in the database \(dqmydb\(dq and collection \(dqmycoll\(dq. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; bson_error_t error; bson_t *doc; int64_t count; mongoc_init (); client = mongoc_client_new (\(dqmongodb://localhost:27017/?appname=count\-example\(dq); collection = mongoc_client_get_collection (client, \(dqmydb\(dq, \(dqmycoll\(dq); doc = bson_new_from_json ( (const uint8_t *) \(dq{\e\(dqhello\e\(dq : \e\(dqworld\e\(dq}\(dq, \-1, &error); count = mongoc_collection_count ( collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); if (count < 0) { fprintf (stderr, \(dq%s\en\(dq, error.message); } else { printf (\(dq%\(dq PRId64 \(dq\en\(dq, count); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .EE .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o count count.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./count 1 .EE .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 count.c C:\e> count 1 .EE .UNINDENT .UNINDENT .SH EXECUTING COMMANDS .sp The driver provides helper functions for executing MongoDB commands on client, database and collection structures. The \fB_simple\fP variants return booleans indicating success or failure. .sp This example executes the \fI\%ping\fP command against the database \(dqmydb\(dq. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include int main (void) { mongoc_client_t *client; bson_error_t error; bson_t *command; bson_t reply; char *str; mongoc_init (); client = mongoc_client_new (\(dqmongodb://localhost:27017/?appname=executing\-example\(dq); command = BCON_NEW (\(dqping\(dq, BCON_INT32 (1)); if (mongoc_client_command_simple (client, \(dqmydb\(dq, command, NULL, &reply, &error)) { str = bson_as_canonical_extended_json (&reply, NULL); printf (\(dq%s\en\(dq, str); bson_free (str); } else { fprintf (stderr, \(dqFailed to run command: %s\en\(dq, error.message); } bson_destroy (command); bson_destroy (&reply); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .EE .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-o executing executing.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./executing { \(dqok\(dq : { \(dq$numberDouble\(dq : \(dq1.0\(dq }, \(dq$clusterTime\(dq : { \(dqclusterTime\(dq : { \(dq$timestamp\(dq : { \(dqt\(dq : 1682609211, \(dqi\(dq : 1 } }, \(dqsignature\(dq : { \(dqhash\(dq : { \(dq$binary\(dq : { \(dqbase64\(dq : \(dqAAAAAAAAAAAAAAAAAAAAAAAAAAA=\(dq, \(dqsubType\(dq : \(dq00\(dq } }, \(dqkeyId\(dq : { \(dq$numberLong\(dq : \(dq0\(dq } } }, \(dqoperationTime\(dq : { \(dq$timestamp\(dq : { \(dqt\(dq : 1682609211, \(dqi\(dq : 1 } } } .EE .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .EX C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 executing.c C:\e> executing { \(dqok\(dq : { \(dq$numberDouble\(dq : \(dq1.0\(dq }, \(dq$clusterTime\(dq : { \(dqclusterTime\(dq : { \(dq$timestamp\(dq : { \(dqt\(dq : 1682609211, \(dqi\(dq : 1 } }, \(dqsignature\(dq : { \(dqhash\(dq : { \(dq$binary\(dq : { \(dqbase64\(dq : \(dqAAAAAAAAAAAAAAAAAAAAAAAAAAA=\(dq, \(dqsubType\(dq : \(dq00\(dq } }, \(dqkeyId\(dq : { \(dq$numberLong\(dq : \(dq0\(dq } } }, \(dqoperationTime\(dq : { \(dq$timestamp\(dq : { \(dqt\(dq : 1682609211, \(dqi\(dq : 1 } } } .EE .UNINDENT .UNINDENT .SH THREADING .sp The MongoDB C Driver is thread\-unaware in the vast majority of its operations. This means it is up to the programmer to guarantee thread\-safety. .sp However, \fI\%mongoc_client_pool_t\fP is thread\-safe and is used to fetch a \fBmongoc_client_t\fP in a thread\-safe manner. After retrieving a client from the pool, the client structure should be considered owned by the calling thread. When the thread is finished, the client should be placed back into the pool. .sp example\-pool.c .INDENT 0.0 .INDENT 3.5 .sp .EX /* gcc example\-pool.c \-o example\-pool $(pkg\-config \-\-cflags \-\-libs * libmongoc\-1.0) */ /* ./example\-pool [CONNECTION_STRING] */ #include #include #include static pthread_mutex_t mutex; static bool in_shutdown = false; static void * worker (void *data) { mongoc_client_pool_t *pool = data; mongoc_client_t *client; bson_t ping = BSON_INITIALIZER; bson_error_t error; bool r; BSON_APPEND_INT32 (&ping, \(dqping\(dq, 1); while (true) { client = mongoc_client_pool_pop (pool); /* Do something with client. If you are writing an HTTP server, you * probably only want to hold onto the client for the portion of the * request performing database queries. */ r = mongoc_client_command_simple (client, \(dqadmin\(dq, &ping, NULL, NULL, &error); if (!r) { fprintf (stderr, \(dq%s\en\(dq, error.message); } mongoc_client_pool_push (pool, client); pthread_mutex_lock (&mutex); if (in_shutdown || !r) { pthread_mutex_unlock (&mutex); break; } pthread_mutex_unlock (&mutex); } bson_destroy (&ping); return NULL; } int main (int argc, char *argv[]) { const char *uri_string = \(dqmongodb://127.0.0.1/?appname=pool\-example\(dq; mongoc_uri_t *uri; bson_error_t error; mongoc_client_pool_t *pool; pthread_t threads[10]; unsigned i; void *ret; pthread_mutex_init (&mutex, NULL); mongoc_init (); if (argc > 1) { uri_string = argv[1]; } uri = mongoc_uri_new_with_error (uri_string, &error); if (!uri) { fprintf (stderr, \(dqfailed to parse URI: %s\en\(dq \(dqerror message: %s\en\(dq, uri_string, error.message); return EXIT_FAILURE; } pool = mongoc_client_pool_new (uri); mongoc_client_pool_set_error_api (pool, 2); for (i = 0; i < 10; i++) { pthread_create (&threads[i], NULL, worker, pool); } sleep (10); pthread_mutex_lock (&mutex); in_shutdown = true; pthread_mutex_unlock (&mutex); for (i = 0; i < 10; i++) { pthread_join (threads[i], &ret); } mongoc_client_pool_destroy (pool); mongoc_uri_destroy (uri); mongoc_cleanup (); return EXIT_SUCCESS; } .EE .UNINDENT .UNINDENT .SH NEXT STEPS .sp To find information on advanced topics, browse the rest of the \fI\%C driver guide\fP or the \fI\%official MongoDB documentation\fP\&. .sp For help with common issues, consult the \fI\%Troubleshooting\fP page. To report a bug or request a new feature, follow \fI\%these instructions\fP\&. .SH AUTHOR MongoDB, Inc .SH COPYRIGHT 2017-present, MongoDB, Inc .\" Generated by docutils manpage writer. .