Provided by: libmongoc-doc_1.9.2+dfsg-1build1_all
NAME
mongoc_reference - Index
MONGODB C DRIVER
A Cross Platform MongoDB Client Library for C Introduction The MongoDB C Driver, also known as "libmongoc", is a library for using MongoDB from C applications, and for writing MongoDB drivers in higher-level languages. It depends on libbson to generate and parse BSON documents, the native data format of MongoDB. Installing the MongoDB C Driver The following guide will step you through the process of downloading, building, and installing the current release of the MongoDB C Driver. Supported Platforms The MongoDB C Driver is continuously tested on variety of platforms including: • Archlinux • Debian 8.1 • macOS 10.10 • Microsoft Windows Server 2008 • RHEL 7.0, 7.1, 7.2 • SUSE 12 • Ubuntu 12.04, 14.04, 16.04 • Clang 3.4, 3.5, 3.7, 3.8 • GCC 4.6, 4.8, 4.9, 5.3 • MinGW-W64 • Visual Studio 2010, 2013, 2015 • x86, x86_64, ARM (aarch64), Power8 (ppc64le), zSeries (s390x) Install with a Package Manager The libmongoc package is available on recent versions of Debian and Ubuntu. $ apt-get install libmongoc-1.0-0 On Fedora, a mongo-c-driver package is available in the default repositories and can be installed with: $ dnf install mongo-c-driver On recent Red Hat systems, such as CentOS and RHEL 7, a mongo-c-driver package is available in the EPEL repository. To check version available, see https://apps.fedoraproject.org/packages/mongo-c-driver. The package can be installed with: $ yum install mongo-c-driver Building on Unix Prerequisites OpenSSL is required for authentication or for SSL connections to MongoDB. Kerberos or LDAP support requires Cyrus SASL. To install all optional dependencies on RedHat / Fedora: $ sudo yum install pkg-config openssl-devel cyrus-sasl-devel On Debian / Ubuntu: $ sudo apt-get install pkg-config libssl-dev libsasl2-dev On FreeBSD: $ su -c 'pkg install pkgconf openssl cyrus-sasl' Building from a release tarball Unless you intend on contributing to the mongo-c-driver, you will want to build from a release tarball. The most recent release of libmongoc is 1.9.2 and can be downloaded here. The following snippet will download and extract the driver, and configure it: $ wget https://github.com/mongodb/mongo-c-driver/releases/download/1.9.2/mongo-c-driver-1.9.2.tar.gz $ tar xzf mongo-c-driver-1.9.2.tar.gz $ cd mongo-c-driver-1.9.2 $ ./configure --disable-automatic-init-and-cleanup The --disable-automatic-init-and-cleanup option is recommended, see init-cleanup. For a list of all configure options, run ./configure --help. If configure completed successfully, you'll see something like the following describing your build configuration. libmongoc 1.9.2 was configured with the following options: Build configuration: Enable debugging (slow) : no Compile with debug symbols (slow) : no Enable GCC build optimization : yes Enable automatic init and cleanup : no Enable maintainer flags : no Code coverage support : no Cross Compiling : no Fast counters : no Shared memory performance counters : yes SASL : sasl2 SSL : openssl Snappy Compression : no Zlib Compression : bundled Libbson : bundled Documentation: man : no HTML : no mongo-c-driver contains a copy of libbson, in case your system does not already have libbson installed. The configure script will detect if libbson is not installed and use the bundled libbson. $ make $ sudo make install Building from git To build an unreleased version of the driver from git requires additional dependencies. RedHat / Fedora: $ sudo yum install git gcc automake autoconf libtool Debian / Ubuntu: $ sudo apt-get install git gcc automake autoconf libtool FreeBSD: $ su -c 'pkg install git gcc automake autoconf libtool' Once you have the dependencies installed, clone the repository and build the current master or a particular release tag: $ git clone https://github.com/mongodb/mongo-c-driver.git $ cd mongo-c-driver $ git checkout x.y.z # To build a particular release $ ./autogen.sh --with-libbson=bundled $ make $ sudo make install Generating the documentation Install Sphinx, then: $ ./configure --enable-html-docs --enable-man-pages $ make man html Building on Mac OS X Install the XCode Command Line Tools: $ xcode-select --install The pkg-config utility is also required. First install Homebrew according to its instructions, then: $ brew install pkgconfig Download the latest release tarball: $ curl -LO https://github.com/mongodb/mongo-c-driver/releases/download/1.9.2/mongo-c-driver-1.9.2.tar.gz $ tar xzf mongo-c-driver-1.9.2.tar.gz $ cd mongo-c-driver-1.9.2 Build and install the driver: $ ./configure $ make $ sudo make install Native TLS Support on Mac OS X / Darwin (Secure Transport) The MongoDB C Driver supports the Darwin native TLS and crypto libraries. Using the native libraries there is no need to install OpenSSL. By default however, the driver will compile against OpenSSL if it detects it being available. If OpenSSL is not available, it will fallback on the native libraries. To compile against the Darwin native TLS and crypto libraries, even when OpenSSL is available, configure the driver like so: $ ./configure --enable-ssl=darwin OpenSSL support on El Capitan Beginning in OS X 10.11 El Capitan, OS X no longer includes the OpenSSL headers. To build the driver with SSL on El Capitan and later: $ brew install openssl $ export LDFLAGS="-L/usr/local/opt/openssl/lib" $ export CPPFLAGS="-I/usr/local/opt/openssl/include" Building on Windows Building on Windows requires Windows Vista or newer and Visual Studio 2010 or newer. Additionally, cmake is required to generate Visual Studio project files. Let's start by generating Visual Studio project files for libbson, a dependency of the C driver. The following assumes we are compiling for 64-bit Windows using Visual Studio 2015 Express, which can be freely downloaded from Microsoft. cd mongo-c-driver-1.9.2\src\libbson cmake -G "Visual Studio 14 2015 Win64" \ "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \ "-DCMAKE_BUILD_TYPE=Release" # Defaults to debug builds (Run cmake -LH . for a list of other options.) Now that we have project files generated, we can either open the project in Visual Studio or compile from the command line. Let's build using the command line program msbuild.exe msbuild.exe /p:Configuration=Release ALL_BUILD.vcxproj Now that libbson is compiled, let's install it using msbuild. It will be installed to the path specified by CMAKE_INSTALL_PREFIX. msbuild.exe /p:Configuration=Release INSTALL.vcxproj You should now see libbson installed in C:\mongo-c-driver Now let's do the same for the MongoDB C driver. cd mongo-c-driver-1.9.2 cmake -G "Visual Studio 14 2015 Win64" \ "-DENABLE_SSL=WINDOWS" \ "-DENABLE_SASL=SSPI" \ "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \ "-DCMAKE_PREFIX_PATH=C:\mongo-c-driver" \ "-DCMAKE_BUILD_TYPE=Release" # Defaults to debug builds msbuild.exe /p:Configuration=Release ALL_BUILD.vcxproj msbuild.exe /p:Configuration=Release INSTALL.vcxproj All of the MongoDB C Driver's components will now have been build in release mode and can be found in C:\mongo-c-driver. To build and install debug binaries, remove the "-DCMAKE_BUILD_TYPE=Release" argument to cmake and /p:Configuration=Release to msbuild.exe. To use the driver libraries in your program, see visual-studio-guide. Native TLS Support on Windows (Secure Channel) The MongoDB C Driver supports the Windows native TLS and crypto libraries. Using the native libraries there is no need to install OpenSSL. By default however, the driver will compile against OpenSSL if it detects it being available. If OpenSSL is not available, it will fallback on the native libraries. To compile against the Windows native TLS and crypto libraries, even when OpenSSL is available, configure the driver like so: cmake -G "Visual Studio 14 2015 Win64" \ "-DENABLE_SSL=WINDOWS" \ "-DCMAKE_INSTALL_PREFIX=C:\\mongo-c-driver" \ "-DCMAKE_PREFIX_PATH=C:\\mongo-c-driver" Native SASL Support on Windows (SSPI) The MongoDB C Driver supports the Windows native Kerberos and Active Directory interface, SSPI. Using the native libraries there is no need to install any dependencies, such as cyrus-sasl. By default however, the driver will compile against cyrus-sasl. To compile against the Windows native SSPI, configure the driver like so: cmake -G "Visual Studio 14 2015 Win64" \ "-DENABLE_SASL=SSPI" \ "-DCMAKE_INSTALL_PREFIX=C:\\mongo-c-driver" \ "-DCMAKE_PREFIX_PATH=C:\\mongo-c-driver" OpenSSL support on Windows For backwards compatibility CMake will default to OpenSSL support. If not found, it will fallback to native TLS support provided by the platform. OpenSSL 1.1.0 support requires CMake 3.7 or later on Windows. Tutorial This guide offers a brief introduction to the MongoDB C Driver. For more information on the C API, please refer to the api. Contents • Tutorial • Installing • Starting MongoDB • Include and link libmongoc in your C program • Use libmongoc in a Microsoft Visual Studio Project • Making a Connection • Creating BSON Documents • Basic CRUD Operations • Executing Commands • Threading • Next Steps Installing For detailed instructions on installing the MongoDB C Driver on a particular platform, please see the installation guide. Starting MongoDB To run the examples in this tutorial, MongoDB must be installed and running on localhost on the default port, 27017. To check if it is up and running, connect to it with the MongoDB shell. $ mongo --host localhost --port 27017 MongoDB shell version: 3.0.6 connecting to: localhost:27017/test > Include and link libmongoc in your C program Include mongoc.h All libmongoc's functions and types are available in one header file. Simply include mongoc.h: #include <mongoc.h> CMake The libmongoc installation includes a CMake config-file package, so you can use CMake's find_package command to find libmongoc's header and library paths and link to libmongoc: CMakeLists.txt.INDENT 0.0 # Specify the minimum version you require. find_package (libmongoc-1.0 1.7 REQUIRED) message ("-- mongoc found version \"${MONGOC_VERSION}\"") message ("-- mongoc include path \"${MONGOC_INCLUDE_DIRS}\"") message ("-- mongoc libraries \"${MONGOC_LIBRARIES}\"") # The "hello_mongoc.c" sample program is shared among four tests. add_executable (hello_mongoc ../../hello_mongoc.c) target_include_directories (hello_mongoc PRIVATE "${MONGOC_INCLUDE_DIRS}") target_link_libraries (hello_mongoc PRIVATE "${MONGOC_LIBRARIES}") target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_DEFINITIONS}") Use the included libmongoc-static-1.0 config-file package: # Specify the minimum version you require. find_package (libmongoc-static-1.0 1.7 REQUIRED) message ("-- mongoc found version \"${MONGOC_STATIC_VERSION}\"") message ("-- mongoc include path \"${MONGOC_STATIC_INCLUDE_DIRS}\"") message ("-- mongoc libraries \"${MONGOC_STATIC_LIBRARIES}\"") # The "hello_mongoc.c" sample program is shared among four tests. add_executable (hello_mongoc ../../hello_mongoc.c) target_include_directories (hello_mongoc PRIVATE "${MONGOC_STATIC_INCLUDE_DIRS}") target_link_libraries (hello_mongoc PRIVATE "${MONGOC_STATIC_LIBRARIES}") target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_STATIC_DEFINITIONS}") pkg-config If you're not using CMake, use pkg-config on the command line to set header and library paths: gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0) Or to statically link to libmongoc: gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0) Specifying header and include paths manually If you aren't using CMake or pkg-config, paths and libraries can be managed manually. $ gcc -o hello_mongoc hello_mongoc.c \ -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \ -lmongoc-1.0 -lbson-1.0 $ ./hello_mongoc { "ok" : 1.000000 } 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 C:\mongo-c-driver; change the include directory as needed.) C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 hello_mongoc.c C:\> hello_mongoc { "ok" : 1.000000 } Use libmongoc in a Microsoft Visual Studio Project See the libmongoc and Visual Studio guide. Making a Connection Access MongoDB with a mongoc_client_t. It transparently connects to standalone servers, replica sets and sharded clusters on demand. To perform operations on a database or collection, create a mongoc_database_t or mongoc_collection_t struct from the mongoc_client_t. At the start of an application, call mongoc_init 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 mongoc_cleanup before exiting. The example below establishes a connection to a standalone server on localhost, registers the client application as "connect-example," and performs a simple command. More information about database operations can be found in the CRUD Operations and Executing Commands sections. Examples of connecting to replica sets and sharded clusters can be found on the Advanced Connections page. hello_mongoc.c.INDENT 0.0 #include <mongoc.h> int main (int argc, char *argv[]) { const char *uri_str = "mongodb://localhost:27017"; 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's internals */ mongoc_init (); /* * Optionally get MongoDB URI from command line */ if (argc > 1) { uri_str = argv[1]; } /* * Create a new client instance */ client = mongoc_client_new (uri_str); /* * 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, "connect-example"); /* * Get a handle on the database "db_name" and collection "coll_name" */ database = mongoc_client_get_database (client, "db_name"); collection = mongoc_client_get_collection (client, "db_name", "coll_name"); /* * Do work. This example pings the database, prints the result as JSON and * performs an insert */ command = BCON_NEW ("ping", BCON_INT32 (1)); retval = mongoc_client_command_simple ( client, "admin", command, NULL, &reply, &error); if (!retval) { fprintf (stderr, "%s\n", error.message); return EXIT_FAILURE; } str = bson_as_json (&reply, NULL); printf ("%s\n", str); insert = BCON_NEW ("hello", BCON_UTF8 ("world")); if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) { fprintf (stderr, "%s\n", 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_client_destroy (client); mongoc_cleanup (); return 0; } Creating BSON Documents Documents are stored in MongoDB's data format, BSON. The C driver uses libbson to create BSON documents. There are several ways to construct them: appending key-value pairs, using BCON, or parsing JSON. Appending BSON A BSON document, represented as a bson_t in code, can be constructed one field at a time using libbson's append functions. For example, to create a document like this: { born : ISODate("1906-12-09"), died : ISODate("1992-01-01"), name : { first : "Grace", last : "Hopper" }, languages : [ "MATH-MATIC", "FLOW-MATIC", "COBOL" ], degrees: [ { degree: "BA", school: "Vassar" }, { degree: "PhD", school: "Yale" } ] } Use the following code: #include <bson.h> int main (int argc, char *argv[]) { struct tm born = { 0 }; struct tm died = { 0 }; const char *lang_names[] = {"MATH-MATIC", "FLOW-MATIC", "COBOL"}; const char *schools[] = {"Vassar", "Yale"}; const char *degrees[] = {"BA", "PhD"}; uint32_t i; char buf[16]; const char *key; size_t keylen; bson_t *document; bson_t child; bson_t child2; char *str; document = bson_new (); /* * Append { "born" : ISODate("1906-12-09") } 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, "born", -1, mktime (&born) * 1000); /* * Append { "died" : ISODate("1992-01-01") } 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, "died", mktime (&died) * 1000); /* * Append a subdocument. */ BSON_APPEND_DOCUMENT_BEGIN (document, "name", &child); BSON_APPEND_UTF8 (&child, "first", "Grace"); BSON_APPEND_UTF8 (&child, "last", "Hopper"); bson_append_document_end (document, &child); /* * Append array of strings. Generate keys "0", "1", "2". */ BSON_APPEND_ARRAY_BEGIN (document, "languages", &child); for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) { keylen = bson_uint32_to_string (i, &key, buf, sizeof buf); bson_append_utf8 (&child, key, (int) keylen, lang_names[i], -1); } bson_append_array_end (document, &child); /* * Array of subdocuments: * degrees: [ { degree: "BA", school: "Vassar" }, ... ] */ BSON_APPEND_ARRAY_BEGIN (document, "degrees", &child); for (i = 0; i < sizeof degrees / sizeof (char *); ++i) { keylen = bson_uint32_to_string (i, &key, buf, sizeof buf); bson_append_document_begin (&child, key, (int) keylen, &child2); BSON_APPEND_UTF8 (&child2, "degree", degrees[i]); BSON_APPEND_UTF8 (&child2, "school", schools[i]); bson_append_document_end (&child, &child2); } bson_append_array_end (document, &child); /* * Print the document as a JSON string. */ str = bson_as_canonical_extended_json (document, NULL); printf ("%s\n", str); bson_free (str); /* * Clean up allocated bson documents. */ bson_destroy (document); return 0; } See the libbson documentation for all of the types that can be appended to a bson_t. Using BCON BSON C Object Notation, 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's append functions but results in less code. #include <bson.h> 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 ( "born", BCON_DATE_TIME (mktime (&born) * 1000), "died", BCON_DATE_TIME (mktime (&died) * 1000), "name", "{", "first", BCON_UTF8 ("Grace"), "last", BCON_UTF8 ("Hopper"), "}", "languages", "[", BCON_UTF8 ("MATH-MATIC"), BCON_UTF8 ("FLOW-MATIC"), BCON_UTF8 ("COBOL"), "]", "degrees", "[", "{", "degree", BCON_UTF8 ("BA"), "school", BCON_UTF8 ("Vassar"), "}", "{", "degree", BCON_UTF8 ("PhD"), "school", BCON_UTF8 ("Yale"), "}", "]"); /* * Print the document as a JSON string. */ str = bson_as_canonical_extended_json (document, NULL); printf ("%s\n", str); bson_free (str); /* * Clean up allocated bson documents. */ bson_destroy (document); return 0; } Notice that BCON can create arrays, subdocuments and arbitrary fields. Creating BSON from JSON For single documents, BSON can be created from JSON strings via bson_new_from_json. #include <bson.h> int main (int argc, char *argv[]) { bson_error_t error; bson_t *bson; char *string; const char *json = "{\"name\": {\"first\":\"Grace\", \"last\":\"Hopper\"}}"; bson = bson_new_from_json ((const uint8_t *)json, -1, &error); if (!bson) { fprintf (stderr, "%s\n", error.message); return EXIT_FAILURE; } string = bson_as_canonical_extended_json (bson, NULL); printf ("%s\n", string); bson_free (string); return 0; } To initialize BSON from a sequence of JSON documents, use bson_json_reader_t. Basic CRUD Operations This section demonstrates the basics of using the C Driver to interact with MongoDB. Inserting a Document To insert documents into a collection, first obtain a handle to a mongoc_collection_t via a mongoc_client_t. Then, use mongoc_collection_insert_one to add BSON documents to the collection. This example inserts into the database "mydb" and collection "mycoll". When finished, ensure that allocated structures are freed by using their respective destroy functions. #include <bson.h> #include <mongoc.h> #include <stdio.h> 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 ("mongodb://localhost:27017/?appname=insert-example"); collection = mongoc_client_get_collection (client, "mydb", "mycoll"); doc = bson_new (); bson_oid_init (&oid, NULL); BSON_APPEND_OID (doc, "_id", &oid); BSON_APPEND_UTF8 (doc, "hello", "world"); if (!mongoc_collection_insert_one ( collection, doc, NULL, NULL, &error)) { fprintf (stderr, "%s\n", error.message); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Compile the code and run it: $ gcc -o insert insert.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./insert On Windows: C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 insert.c C:\> insert To verify that the insert succeeded, connect with the MongoDB shell. $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.find() { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" } > Finding a Document To query a MongoDB collection with the C driver, use the function mongoc_collection_find_with_opts(). This returns a cursor to the matching documents. The following examples iterate through the result cursors and print the matches to stdout as JSON strings. Use a document as a query specifier; for example, { "color" : "red" } will match any document with a field named "color" with value "red". An empty document {} can be used to match all documents. This first example uses an empty query specifier to find all documents in the database "mydb" and collection "mycoll". #include <bson.h> #include <mongoc.h> #include <stdio.h> 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 ("mongodb://localhost:27017/?appname=find-example"); collection = mongoc_client_get_collection (client, "mydb", "mycoll"); 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 ("%s\n", str); bson_free (str); } bson_destroy (query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Compile the code and run it: $ gcc -o find find.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./find { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } On Windows: C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find.c C:\> find { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } To look for a specific document, add a specifier to query. This example adds a call to BSON_APPEND_UTF8() to look for all documents matching {"hello" : "world"}. #include <bson.h> #include <mongoc.h> #include <stdio.h> 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 ( "mongodb://localhost:27017/?appname=find-specific-example"); collection = mongoc_client_get_collection (client, "mydb", "mycoll"); query = bson_new (); BSON_APPEND_UTF8 (query, "hello", "world"); 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 ("%s\n", str); bson_free (str); } bson_destroy (query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } $ gcc -o find-specific find-specific.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./find-specific { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find-specific.c C:\> find-specific { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } Updating a Document This code snippet gives an example of using mongoc_collection_update_one() to update the fields of a document. Using the "mydb" database, the following example inserts an example document into the "mycoll" collection. Then, using its _id field, the document is updated with different values and a new field. #include <bcon.h> #include <bson.h> #include <mongoc.h> #include <stdio.h> 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 ("mongodb://localhost:27017/?appname=update-example"); collection = mongoc_client_get_collection (client, "mydb", "mycoll"); bson_oid_init (&oid, NULL); doc = BCON_NEW ("_id", BCON_OID (&oid), "key", BCON_UTF8 ("old_value")); if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) { fprintf (stderr, "%s\n", error.message); goto fail; } query = BCON_NEW ("_id", BCON_OID (&oid)); update = BCON_NEW ("$set", "{", "key", BCON_UTF8 ("new_value"), "updated", BCON_BOOL (true), "}"); if (!mongoc_collection_update_one ( collection, query, update, NULL, NULL, &error)) { fprintf (stderr, "%s\n", 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; } Compile the code and run it: $ gcc -o update update.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./update On Windows: C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 update.c C:\> update { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } To verify that the update succeeded, connect with the MongoDB shell. $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.find({"updated" : true}) { "_id" : ObjectId("55ef549236fe322f9490e17b"), "updated" : true, "key" : "new_value" } > Deleting a Document This example illustrates the use of mongoc_collection_delete_one() to delete a document. The following code inserts a sample document into the database "mydb" and collection "mycoll". Then, it deletes all documents matching {"hello" : "world"}. #include <bson.h> #include <mongoc.h> #include <stdio.h> 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 ("mongodb://localhost:27017/?appname=delete-example"); collection = mongoc_client_get_collection (client, "test", "test"); doc = bson_new (); bson_oid_init (&oid, NULL); BSON_APPEND_OID (doc, "_id", &oid); BSON_APPEND_UTF8 (doc, "hello", "world"); if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) { fprintf (stderr, "Insert failed: %s\n", error.message); } bson_destroy (doc); doc = bson_new (); BSON_APPEND_OID (doc, "_id", &oid); if (!mongoc_collection_delete_one ( collection, doc, NULL, NULL, &error)) { fprintf (stderr, "Delete failed: %s\n", error.message); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Compile the code and run it: $ gcc -o delete delete.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./delete On Windows: C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 delete.c C:\> delete Use the MongoDB shell to prove that the documents have been removed successfully. $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.count({"hello" : "world"}) 0 > Counting Documents Counting the number of documents in a MongoDB collection is similar to performing a find operation. This example counts the number of documents matching {"hello" : "world"} in the database "mydb" and collection "mycoll". #include <bson.h> #include <mongoc.h> #include <stdio.h> 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 ("mongodb://localhost:27017/?appname=count-example"); collection = mongoc_client_get_collection (client, "mydb", "mycoll"); doc = bson_new_from_json ( (const uint8_t *) "{\"hello\" : \"world\"}", -1, &error); count = mongoc_collection_count ( collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); if (count < 0) { fprintf (stderr, "%s\n", error.message); } else { printf ("%" PRId64 "\n", count); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Compile the code and run it: $ gcc -o count count.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./count 1 On Windows: C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 count.c C:\> count 1 Executing Commands The driver provides helper functions for executing MongoDB commands on client, database and collection structures. These functions return cursors; the _simple variants return booleans indicating success or failure. This example executes the collStats command against the collection "mycoll" in database "mydb". #include <bson.h> #include <bcon.h> #include <mongoc.h> #include <stdio.h> int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; bson_error_t error; bson_t *command; bson_t reply; char *str; mongoc_init (); client = mongoc_client_new ( "mongodb://localhost:27017/?appname=executing-example"); collection = mongoc_client_get_collection (client, "mydb", "mycoll"); command = BCON_NEW ("collStats", BCON_UTF8 ("mycoll")); if (mongoc_collection_command_simple ( collection, command, NULL, &reply, &error)) { str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); } else { fprintf (stderr, "Failed to run command: %s\n", error.message); } bson_destroy (command); bson_destroy (&reply); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Compile the code and run it: $ gcc -o executing executing.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./executing { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192, "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1, "indexDetails" : { }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 } On Windows: C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 executing.c C:\> executing { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192, "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1, "indexDetails" : { }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 } Threading 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. However, mongoc_client_pool_t is thread-safe and is used to fetch a mongoc_client_t 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. example-pool.c.INDENT 0.0 /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs * libmongoc-1.0) */ /* ./example-pool [CONNECTION_STRING] */ #include <mongoc.h> #include <pthread.h> #include <stdio.h> 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, "ping", 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, "admin", &ping, NULL, NULL, &error); if (!r) { fprintf (stderr, "%s\n", 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 *uristr = "mongodb://127.0.0.1/?appname=pool-example"; mongoc_uri_t *uri; mongoc_client_pool_t *pool; pthread_t threads[10]; unsigned i; void *ret; pthread_mutex_init (&mutex, NULL); mongoc_init (); if (argc > 1) { uristr = argv[1]; } uri = mongoc_uri_new (uristr); if (!uri) { fprintf (stderr, "Failed to parse URI: \"%s\".\n", uristr); 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 0; } Next Steps To find information on advanced topics, browse the rest of the C driver guide or the official MongoDB documentation. For help with common issues, consult the Troubleshooting page. To report a bug or request a new feature, follow these instructions. Authentication This guide covers the use of authentication options with the MongoDB C Driver. Ensure that the MongoDB server is also properly configured for authentication before making a connection. For more information, see the MongoDB security documentation. The MongoDB C driver supports several authentication mechanisms through the use of MongoDB connection URIs. By default, if a username and password are provided as part of the connection string (and an optional authentication database), they are used to connect via the default authentication mechanism of the server. To select a specific authentication mechanism other than the default, see the list of supported mechanism below. mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb"); Currently supported values for the authMechanism connection string option are: • SCRAM-SHA-1 • MONGODB-CR • GSSAPI • PLAIN • X509 Basic Authentication (SCRAM-SHA-1) The default authentication mechanism when talking to MongoDB 3.0 and later is SCRAM-SHA-1 (RFC 5802). Using this authentication mechanism means that the password is never actually sent over the wire when authenticating, but rather a computed proof that the client password is the same as the password the server knows. mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1&authSource=mydb"); NOTE: SCRAM-SHA-1 authenticates against the admin database by default. If the user is created in another database, then specifying the authSource is required. Legacy Authentication (MONGODB-CR) The MONGODB-CR authMechanism is a challenge response authentication mechanism. It was the default mechanism until MongoDB 3.0 and is being phased out. It is strongly suggested that users upgrade to SCRAM-SHA-1. NOTE: MONGODB-CR authenticates against the admin database by default. If the user is created in another database, then specifying the authSource is required. GSSAPI (Kerberos) Authentication NOTE: Kerberos support requires compiling the driver against cyrus-sasl on UNIX-like environments. On Windows, configure the driver to build against the Windows Native SSPI. GSSAPI (Kerberos) authentication is available in the Enterprise Edition of MongoDB. To authenticate using GSSAPI, the MongoDB C driver must be installed with SASL support. On UNIX-like environments, run the kinit command before using the following authentication methods: $ kinit mongodbuser@EXAMPLE.COM mongodbuser@EXAMPLE.COM's Password: $ klistCredentials cache: FILE:/tmp/krb5cc_1000 Principal: mongodbuser@EXAMPLE.COM Issued Expires Principal Feb 9 13:48:51 2013 Feb 9 23:48:51 2013 krbtgt/EXAMPLE.COM@EXAMPLE.COM Now authenticate using the MongoDB URI. GSSAPI authenticates against the $external virtual database, so a database does not need to be specified in the URI. Note that the Kerberos principal must be URL-encoded: mongoc_client_t *client; client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI"); NOTE: GSSAPI authenticates against the $external database, so specifying the authSource database is not required. The driver supports these GSSAPI properties: • CANONICALIZE_HOST_NAME: This might be required with Cyrus-SASL when the hosts report different hostnames than what is used in the Kerberos database. The default is "false". • SERVICE_NAME: Use a different service name than the default, "mongodb". Set properties in the URL: mongoc_client_t *client; client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&" "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true"); If you encounter errors such as Invalid net address, check if the application is behind a NAT (Network Address Translation) firewall. If so, create a ticket that uses forwardable and addressless Kerberos tickets. This can be done by passing -f -A to kinit. $ kinit -f -A mongodbuser@EXAMPLE.COM SASL Plain Authentication NOTE: The MongoDB C Driver must be compiled with SASL support in order to use SASL PLAIN authentication. MongoDB Enterprise Edition supports the SASL PLAIN authentication mechanism, initially intended for delegating authentication to an LDAP server. Using the SASL PLAIN mechanism is very similar to the challenge response mechanism with usernames and passwords. This authentication mechanism uses the $external virtual database for LDAP support: NOTE: SASL PLAIN is a clear-text authentication mechanism. It is strongly recommended to connect to MongoDB using SSL with certificate validation when using the PLAIN mechanism. mongoc_client_t *client; client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN"); PLAIN authenticates against the $external database, so specifying the authSource database is not required. X.509 Certificate Authentication NOTE: The MongoDB C Driver must be compiled with SSL support for X.509 authentication support. Once this is done, start a server with the following options: $ mongod --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem The MONGODB-X509 mechanism authenticates a username derived from the distinguished subject name of the X.509 certificate presented by the driver during SSL negotiation. This authentication method requires the use of SSL connections with certificate validation. mongoc_client_t *client; mongoc_ssl_opt_t ssl_opts = { 0 }; ssl_opts.pem_file = "mycert.pem"; ssl_opts.pem_pwd = "mycertpassword"; ssl_opts.ca_file = "myca.pem"; ssl_opts.ca_dir = "trust_dir"; ssl_opts.weak_cert_validation = false; client = mongoc_client_new ("mongodb://x509_derived_username@localhost/?authMechanism=MONGODB-X509"); mongoc_client_set_ssl_opts (client, &ssl_opts); MONGODB-X509 authenticates against the $external database, so specifying the authSource database is not required. For more information on the x509_derived_username, see the MongoDB server x.509 tutorial. NOTE: The MongoDB C Driver will attempt to determine the x509 derived username when none is provided, and as of MongoDB 3.4 providing the username is not required at all. Basic Troubleshooting Troubleshooting Checklist The following is a short list of things to check when you have a problem. • Did you call mongoc_init() in main()? If not, you will likely see a segfault. • Have you leaked any clients or cursors as can be found with mongoc-stat <PID>? • Have packets been delivered to the server? See egress bytes from mongoc-stat <PID>. • Does valgrind show any leaks? Ensure you call mongoc_cleanup() at the end of your process to cleanup lingering allocations from the MongoDB C driver. • If compiling your own copy of MongoDB C driver, consider configuring with --enable-tracing to enable function tracing and hex dumps of network packets to STDERR and STDOUT. Performance Counters The MongoDB C driver comes with a unique feature to help developers and sysadmins troubleshoot problems in production. Performance counters are available for each process using the driver. The counters can be accessed outside of the application process via a shared memory segment. This means that you can graph statistics about your application process easily from tools like Munin or Nagios. Your author often uses watch --interval=0.5 -d mongoc-stat $PID to monitor an application. Counters are currently available on UNIX-like platforms that support shared memory segments. • Active and Disposed Cursors • Active and Disposed Clients, Client Pools, and Socket Streams. • Number of operations sent and received, by type. • Bytes transferred and received. • Authentication successes and failures. • Number of wire protocol errors. To access counters for a given process, simply provide the process id to the mongoc-stat program installed with the MongoDB C Driver. $ mongoc-stat 22203 Operations : Egress Total : The number of sent operations. : 13247 Operations : Ingress Total : The number of received operations. : 13246 Operations : Egress Queries : The number of sent Query operations. : 13247 Operations : Ingress Queries : The number of received Query operations. : 0 Operations : Egress GetMore : The number of sent GetMore operations. : 0 Operations : Ingress GetMore : The number of received GetMore operations. : 0 Operations : Egress Insert : The number of sent Insert operations. : 0 Operations : Ingress Insert : The number of received Insert operations. : 0 Operations : Egress Delete : The number of sent Delete operations. : 0 Operations : Ingress Delete : The number of received Delete operations. : 0 Operations : Egress Update : The number of sent Update operations. : 0 Operations : Ingress Update : The number of received Update operations. : 0 Operations : Egress KillCursors : The number of sent KillCursors operations. : 0 Operations : Ingress KillCursors : The number of received KillCursors operations. : 0 Operations : Egress Msg : The number of sent Msg operations. : 0 Operations : Ingress Msg : The number of received Msg operations. : 0 Operations : Egress Reply : The number of sent Reply operations. : 0 Operations : Ingress Reply : The number of received Reply operations. : 13246 Cursors : Active : The number of active cursors. : 1 Cursors : Disposed : The number of disposed cursors. : 13246 Clients : Active : The number of active clients. : 1 Clients : Disposed : The number of disposed clients. : 0 Streams : Active : The number of active streams. : 1 Streams : Disposed : The number of disposed streams. : 0 Streams : Egress Bytes : The number of bytes sent. : 794931 Streams : Ingress Bytes : The number of bytes received. : 589694 Streams : N Socket Timeouts : The number of socket timeouts. : 0 Client Pools : Active : The number of active client pools. : 1 Client Pools : Disposed : The number of disposed client pools. : 0 Protocol : Ingress Errors : The number of protocol errors on ingress. : 0 Auth : Failures : The number of failed authentication requests. : 0 Auth : Success : The number of successful authentication requests. : 0 Submitting a Bug Report Think you've found a bug? Want to see a new feature in the MongoDB C driver? Please open a case in our issue management tool, JIRA: • Create an account and login. • Navigate to the CDRIVER project. • Click Create Issue - Please provide as much information as possible about the issue type and how to reproduce it. Bug reports in JIRA for all driver projects (i.e. CDRIVER, CSHARP, JAVA) and the Core Server (i.e. SERVER) project are public. Guides Common Tasks Drivers for some other languages provide helper functions to perform certain common tasks. In the C Driver we must explicitly build commands to send to the server. This snippet contains example code for the explain, copydb and cloneCollection commands. Setup First we'll write some code to insert sample data: doc-common-insert.c.INDENT 0.0 /* Don't try to compile this file on its own. It's meant to be #included by example code */ /* Insert some sample data */ bool insert_data (mongoc_collection_t *collection) { mongoc_bulk_operation_t *bulk; enum N { ndocs = 4 }; bson_t *docs[ndocs]; bson_error_t error; int i = 0; bool ret; bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL); docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]"); docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]"); docs[2] = BCON_NEW ( "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]"); docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]"); for (i = 0; i < ndocs; i++) { mongoc_bulk_operation_insert (bulk, docs[i]); bson_destroy (docs[i]); docs[i] = NULL; } ret = mongoc_bulk_operation_execute (bulk, NULL, &error); if (!ret) { fprintf (stderr, "Error inserting data: %s\n", error.message); } mongoc_bulk_operation_destroy (bulk); return ret; } /* A helper which we'll use a lot later on */ void print_res (const bson_t *reply) { BSON_ASSERT (reply); char *str = bson_as_canonical_extended_json (reply, NULL); printf ("%s\n", str); bson_free (str); } explain Command This is how to use the explain command in MongoDB 3.2+: explain.c.INDENT 0.0 bool explain (mongoc_collection_t *collection) { bson_t *command; bson_t reply; bson_error_t error; bool res; command = BCON_NEW ("explain", "{", "find", BCON_UTF8 (COLLECTION_NAME), "filter", "{", "x", BCON_INT32 (1), "}", "}"); res = mongoc_collection_command_simple ( collection, command, NULL, &reply, &error); if (!res) { fprintf (stderr, "Error with explain: %s\n", error.message); goto cleanup; } /* Do something with the reply */ print_res (&reply); cleanup: bson_destroy (&reply); bson_destroy (command); return res; } copydb Command This example requires two instances of mongo to be running. Here's how to use the copydb command to copy a database from another instance of MongoDB: copydb.c.INDENT 0.0 bool copydb (mongoc_client_t *client, const char *other_host_and_port) { mongoc_database_t *admindb; bson_t *command; bson_t reply; bson_error_t error; bool res; BSON_ASSERT (other_host_and_port); /* Must do this from the admin db */ admindb = mongoc_client_get_database (client, "admin"); command = BCON_NEW ("copydb", BCON_INT32 (1), "fromdb", BCON_UTF8 ("test"), "todb", BCON_UTF8 ("test2"), /* If you want from a different host */ "fromhost", BCON_UTF8 (other_host_and_port)); res = mongoc_database_command_simple (admindb, command, NULL, &reply, &error); if (!res) { fprintf (stderr, "Error with copydb: %s\n", error.message); goto cleanup; } /* Do something with the reply */ print_res (&reply); cleanup: bson_destroy (&reply); bson_destroy (command); mongoc_database_destroy (admindb); return res; } cloneCollection Command This example requires two instances of mongo to be running. Here's an example of the cloneCollection command to clone a collection from another instance of MongoDB: clone-collection.c.INDENT 0.0 bool clone_collection (mongoc_database_t *database, const char *other_host_and_port) { bson_t *command; bson_t reply; bson_error_t error; bool res; BSON_ASSERT (other_host_and_port); command = BCON_NEW ("cloneCollection", BCON_UTF8 ("test.remoteThings"), "from", BCON_UTF8 (other_host_and_port), "query", "{", "x", BCON_INT32 (1), "}"); res = mongoc_database_command_simple (database, command, NULL, &reply, &error); if (!res) { fprintf (stderr, "Error with clone: %s\n", error.message); goto cleanup; } /* Do something with the reply */ print_res (&reply); cleanup: bson_destroy (&reply); bson_destroy (command); return res; } Running the Examples common-operations.c.INDENT 0.0 /* * Copyright 2016 MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <mongoc.h> #include <stdio.h> const char *COLLECTION_NAME = "things"; #include "../doc-common-insert.c" #include "explain.c" #include "copydb.c" #include "clone-collection.c" int main (int argc, char *argv[]) { mongoc_database_t *database = NULL; mongoc_client_t *client = NULL; mongoc_collection_t *collection = NULL; char *host_and_port; int res = 0; char *other_host_and_port = NULL; if (argc < 2 || argc > 3) { fprintf (stderr, "usage: %s MONGOD-1-CONNECTION-STRING " "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n", argv[0]); fprintf (stderr, "MONGOD-1-CONNECTION-STRING can be " "of the following forms:\n"); fprintf (stderr, "localhost\t\t\t\tlocal machine\n"); fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n"); fprintf (stderr, "mongodb://user:pass@localhost:27017\t" "local machine on port 27017, and authenticate with username " "user and password pass\n"); return 1; } mongoc_init (); if (strncmp (argv[1], "mongodb://", 10) == 0) { host_and_port = bson_strdup (argv[1]); } else { host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]); } other_host_and_port = argc > 2 ? argv[2] : NULL; client = mongoc_client_new (host_and_port); if (!client) { fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port); res = 2; goto cleanup; } mongoc_client_set_error_api (client, 2); database = mongoc_client_get_database (client, "test"); collection = mongoc_database_get_collection (database, COLLECTION_NAME); printf ("Inserting data\n"); if (!insert_data (collection)) { res = 3; goto cleanup; } printf ("explain\n"); if (!explain (collection)) { res = 4; goto cleanup; } if (other_host_and_port) { printf ("copydb\n"); if (!copydb (client, other_host_and_port)) { res = 5; goto cleanup; } printf ("clone collection\n"); if (!clone_collection (database, other_host_and_port)) { res = 6; goto cleanup; } } cleanup: if (collection) { mongoc_collection_destroy (collection); } if (database) { mongoc_database_destroy (database); } if (client) { mongoc_client_destroy (client); } bson_free (host_and_port); mongoc_cleanup (); return res; } $ mongod $ mkdir /tmp/db2$ mongod --dbpath /tmp/db2 --port 27018 # second instance Now compile and run the example program: $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018 Inserting data explain { "executionStats" : { "allPlansExecution" : [], "executionStages" : { "advanced" : 19, "direction" : "forward" , "docsExamined" : 76, "executionTimeMillisEstimate" : 0, "filter" : { "x" : { "$eq" : 1 } }, "invalidates" : 0, "isEOF" : 1, "nReturned" : 19, "needTime" : 58, "needYield" : 0, "restoreState" : 0, "saveState" : 0, "stage" : "COLLSCAN" , "works" : 78 }, "executionSuccess" : true, "executionTimeMillis" : 0, "nReturned" : 19, "totalDocsExamined" : 76, "totalKeysExamined" : 0 }, "ok" : 1, "queryPlanner" : { "indexFilterSet" : false, "namespace" : "test.things", "parsedQuery" : { "x" : { "$eq" : 1 } }, "plannerVersion" : 1, "rejectedPlans" : [], "winningPlan" : { "direction" : "forward" , "filter" : { "x" : { "$eq" : 1 } }, "stage" : "COLLSCAN" } }, "serverInfo" : { "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" , "host" : "MacBook-Pro-57.local", "port" : 27017, "version" : "3.2.6" } } copydb { "ok" : 1 } clone collection { "ok" : 1 } Advanced Connections The following guide contains information specific to certain types of MongoDB configurations. For an example of connecting to a simple standalone server, see the Tutorial. To establish a connection with authentication options enabled, see the Authentication page. Connecting to a Replica Set Connecting to a replica set is much like connecting to a standalone MongoDB server. Simply specify the replica set name using the ?replicaSet=myreplset URI option. #include <bson.h> #include <mongoc.h> int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_init (); /* Create our MongoDB Client */ client = mongoc_client_new ( "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset"); /* Do some work */ /* TODO */ /* Clean up */ mongoc_client_destroy (client); mongoc_cleanup (); return 0; } TIP: Multiple hostnames can be specified in the MongoDB connection string URI, with a comma separating hosts in the seed list. It is recommended to use a seed list of members of the replica set to allow the driver to connect to any node. Connecting to a Sharded Cluster To connect to a sharded cluster, specify the mongos nodes the client should connect to. The C Driver will automatically detect that it has connected to a mongos sharding server. If more than one hostname is specified, a seed list will be created to attempt failover between the mongos instances. WARNING: Specifying the replicaSet parameter when connecting to a mongos sharding server is invalid. #include <bson.h> #include <mongoc.h> int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_init (); /* Create our MongoDB Client */ client = mongoc_client_new ("mongodb://myshard01:27017/"); /* Do something with client ... */ /* Free the client */ mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Connecting to an IPv6 Address The MongoDB C Driver will automatically resolve IPv6 addresses from host names. However, to specify an IPv6 address directly, wrap the address in []. mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017"); Connecting to a UNIX Domain Socket On UNIX-like systems, the C Driver can connect directly to a MongoDB server using a UNIX domain socket. Pass the URL-encoded path to the socket, which must be suffixed with .sock. For example, to connect to a domain socket at /tmp/mongodb-27017.sock: mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock"); Include username and password like so: mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock"); Connecting to a server over SSL These are instructions for configuring TLS/SSL connections. To run a server locally (on port 27017, for example): $ mongod --port 27017 --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem Add /?ssl=true to the end of a client URI. mongoc_client_t *client = NULL; client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true"); MongoDB requires client certificates by default, unless the --sslAllowConnectionsWithoutCertificates is provided. The C Driver can be configured to present a client certificate using a mongoc_ssl_opt_t: const mongoc_ssl_opt_t *ssl_default = mongoc_ssl_opt_get_default (); mongoc_ssl_opt_t ssl_opts = { 0 }; /* optionally copy in a custom trust directory or file; otherwise the default is used. */ memcpy (&ssl_opts, ssl_default, sizeof ssl_opts); ssl_opts.pem_file = "client.pem" mongoc_client_set_ssl_opts (client, &ssl_opts); The client certificate provided by pem_file must be issued by one of the server trusted Certificate Authorities listed in --sslCAFile, or issued by a CA in the native certificate store on the server when omitted. To verify the server certificate against a specific CA, provide a PEM armored file with a CA certificate, or concatenated list of CA certificates using the ca_file option, or c_rehash directory structure of CAs, pointed to using the ca_dir option. When no ca_file or ca_dir is provided, the driver will use CAs provided by the native platform certificate store. See mongoc_ssl_opt_t for more information on the various SSL related options. Compressing data to and from MongoDB MongoDB 3.4 added Snappy compression support, and zlib compression in 3.6. To enable compression support the client must be configured with which compressors to use: mongoc_client_t *client = NULL; client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib"); The compressors option specifies the priority order of compressors the client wants to use. Messages are compressed if the client and server share any compressors in common. Note that the compressor used by the server might not be the same compressor as the client used. For example, if the client uses the connection string compressors=zlib,snappy the client will use zlib compression to send data (if possible), but the server might still reply using snappy, depending on how the server was configured. The driver must be built with zlib and/or snappy support to enable compression support, any unknown (or not compiled in) compressor value will be ignored. Additional Connection Options The full list of connection options can be found in the mongoc_uri_t docs. Certain socket/connection related options are not configurable: ┌──────────────┬──────────────────────────┬────────────────────────┐ │Option │ Description │ Value │ ├──────────────┼──────────────────────────┼────────────────────────┤ │SO_KEEPALIVE │ TCP Keep Alive │ Enabled │ ├──────────────┼──────────────────────────┼────────────────────────┤ │TCP_KEEPIDLE │ How long a connection │ 300 seconds │ │ │ needs to remain idle │ │ │ │ before TCP starts │ │ │ │ sending keepalive probes │ │ ├──────────────┼──────────────────────────┼────────────────────────┤ │TCP_KEEPINTVL │ The time in seconds │ 10 seconds │ │ │ between TCP probes │ │ ├──────────────┼──────────────────────────┼────────────────────────┤ │TCP_KEEPCNT │ How many probes to send, │ 9 probes │ │ │ without acknowledgement, │ │ │ │ before dropping the │ │ │ │ connection │ │ ├──────────────┼──────────────────────────┼────────────────────────┤ │TCP_NODELAY │ Send packets as soon as │ Enabled (no buffering) │ │ │ possible or buffer small │ │ │ │ packets (Nagle │ │ │ │ algorithm) │ │ └──────────────┴──────────────────────────┴────────────────────────┘ Connection Pooling The MongoDB C driver has two connection modes: single-threaded and pooled. Single-threaded mode is optimized for embedding the driver within languages like PHP. Multi-threaded programs should use pooled mode: this mode minimizes the total connection count, and in pooled mode a background thread monitors the MongoDB server topology, so the program need not block to scan it. Single Mode In single mode, your program creates a mongoc_client_t directly: mongoc_client_t *client = mongoc_client_new ( "mongodb://hostA,hostB/?replicaSet=my_rs"); The client connects on demand when your program first uses it for a MongoDB operation. Using a non-blocking socket per server, it begins a check on each server concurrently, and uses the asynchronous poll or select function to receive events from the sockets, until all have responded or timed out. Put another way, in single-threaded mode the C Driver fans out to begin all checks concurrently, then fans in once all checks have completed or timed out. Once the scan completes, the client executes your program's operation and returns. In single mode, the client re-scans the server topology roughly once per minute. If more than a minute has elapsed since the previous scan, the next operation on the client will block while the client completes its scan. This interval is configurable with heartbeatFrequencyMS in the connection string. (See mongoc_uri_t.) A single client opens one connection per server in your topology: these connections are used both for scanning the topology and performing normal operations. Pooled Mode To activate pooled mode, create a mongoc_client_pool_t: mongoc_uri_t *uri = mongoc_uri_new ( "mongodb://hostA,hostB/?replicaSet=my_rs"); mongoc_client_pool_t *pool = mongoc_client_pool_new (uri); When your program first calls mongoc_client_pool_pop, the pool launches a background thread for monitoring. The thread fans out and connects to all servers in the connection string, using non-blocking sockets and a simple event loop. As it receives ismaster responses from the servers, it updates its view of the server topology. Each time the thread discovers a new server it begins connecting to it, and adds the new socket to the list of non-blocking sockets in the event loop. Each thread that executes MongoDB operations must check out a client from the pool: mongoc_client_t *client = mongoc_client_pool_pop (pool); /* use the client for operations ... */ mongoc_client_pool_push (pool, client); The mongoc_client_t object is not thread-safe, only the mongoc_client_pool_t is. When the driver is in pooled mode, your program's operations are unblocked as soon as monitoring discovers a usable server. For example, if a thread in your program is waiting to execute an "insert" on the primary, it is unblocked as soon as the primary is discovered, rather than waiting for all secondaries to be checked as well. The pool opens one connection per server for monitoring, and each client opens its own connection to each server it uses for application operations. The background thread re-scans the server topology roughly every 10 seconds. This interval is configurable with heartbeatFrequencyMS in the connection string. (See mongoc_uri_t.) See connection_pool_options to configure pool size and behavior, and see mongoc_client_pool_t for an extended example of a multi-threaded program that uses the driver in pooled mode. Cursors Handling Cursor Failures Cursors exist on a MongoDB server. However, the mongoc_cursor_t structure gives the local process a handle to the cursor. It is possible for errors to occur on the server while iterating a cursor on the client. Even a network partition may occur. This means that applications should be robust in handling cursor failures. While iterating cursors, you should check to see if an error has occurred. See the following example for how to robustly check for errors. static void print_all_documents (mongoc_collection_t *collection) { mongoc_cursor_t *cursor; const bson_t *doc; bson_error_t error; bson_t query = BSON_INITIALIZER; char *str; 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 ("%s\n", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Failed to iterate all documents: %s\n", error.message); } mongoc_cursor_destroy (cursor); } Destroying Server-Side Cursors The MongoDB C driver will automatically destroy a server-side cursor when mongoc_cursor_destroy() is called. Failure to call this function when done with a cursor will leak memory client side as well as consume extra memory server side. If the cursor was configured to never timeout, it will become a memory leak on the server. Tailable Cursors Tailable cursors are cursors that remain open even after they've returned a final result. This way, if more documents are added to a collection (i.e., to the cursor's result set), then you can continue to call mongoc_cursor_next() to retrieve those additional results. Here's a complete test case that demonstrates the use of tailable cursors. NOTE: Tailable cursors are for capped collections only. An example to tail the oplog from a replica set. mongoc-tail.c.INDENT 0.0 #include <bson.h> #include <mongoc.h> #include <stdio.h> #include <stdlib.h> #ifdef _WIN32 #define sleep(_n) Sleep ((_n) *1000) #endif static void print_bson (const bson_t *b) { char *str; str = bson_as_canonical_extended_json (b, NULL); fprintf (stdout, "%s\n", str); bson_free (str); } static mongoc_cursor_t * query_collection (mongoc_collection_t *collection, uint32_t last_time) { mongoc_cursor_t *cursor; bson_t query; bson_t gt; bson_t opts; BSON_ASSERT (collection); bson_init (&query); BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", >); BSON_APPEND_TIMESTAMP (>, "$gt", last_time, 0); bson_append_document_end (&query, >); bson_init (&opts); BSON_APPEND_BOOL (&opts, "tailable", true); BSON_APPEND_BOOL (&opts, "awaitData", true); cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL); bson_destroy (&query); bson_destroy (&opts); return cursor; } static void tail_collection (mongoc_collection_t *collection) { mongoc_cursor_t *cursor; uint32_t last_time; const bson_t *doc; bson_error_t error; bson_iter_t iter; BSON_ASSERT (collection); last_time = (uint32_t) time (NULL); while (true) { cursor = query_collection (collection, last_time); while (!mongoc_cursor_error (cursor, &error) && mongoc_cursor_more (cursor)) { if (mongoc_cursor_next (cursor, &doc)) { if (bson_iter_init_find (&iter, doc, "ts") && BSON_ITER_HOLDS_TIMESTAMP (&iter)) { bson_iter_timestamp (&iter, &last_time, NULL); } print_bson (doc); } } if (mongoc_cursor_error (cursor, &error)) { if (error.domain == MONGOC_ERROR_SERVER) { fprintf (stderr, "%s\n", error.message); exit (1); } } mongoc_cursor_destroy (cursor); sleep (1); } } int main (int argc, char *argv[]) { mongoc_collection_t *collection; mongoc_client_t *client; if (argc != 2) { fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]); return EXIT_FAILURE; } mongoc_init (); client = mongoc_client_new (argv[1]); if (!client) { fprintf (stderr, "Invalid URI: \"%s\"\n", argv[1]); return EXIT_FAILURE; } mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "local", "oplog.rs"); tail_collection (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); return 0; } $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet { "h" : -8458503739429355503, "ns" : "test.test", "o" : { "_id" : { "$oid" : "5372ab0a25164be923d10d50" } }, "op" : "i", "ts" : { "$timestamp" : { "i" : 1, "t" : 1400023818 } }, "v" : 2 } The line of output is a sample from performing db.test.insert({}) from the mongo shell on the replica set. See also mongoc_cursor_set_max_await_time_ms. Bulk Write Operations This tutorial explains how to take advantage of MongoDB C driver bulk write operation features. Executing write operations in batches reduces the number of network round trips, increasing write throughput. Bulk Insert First we need to fetch a bulk operation handle from the mongoc_collection_t. mongoc_bulk_operation_t *bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL); We can now start inserting documents to the bulk operation. These will be buffered until we execute the operation. The bulk operation will coalesce insertions as a single batch for each consecutive call to mongoc_bulk_operation_insert(). This creates a pipelined effect when possible. To execute the bulk operation and receive the result we call mongoc_bulk_operation_execute(). bulk1.c.INDENT 0.0 #include <assert.h> #include <bcon.h> #include <mongoc.h> #include <stdio.h> static void bulk1 (mongoc_collection_t *collection) { mongoc_bulk_operation_t *bulk; bson_error_t error; bson_t *doc; bson_t reply; char *str; bool ret; int i; bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL); for (i = 0; i < 10000; i++) { doc = BCON_NEW ("i", BCON_INT32 (i)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); } ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { fprintf (stderr, "Error: %s\n", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/?appname=bulk1-example"); mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "test", "test"); bulk1 (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Example reply document: {"nInserted" : 10000, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "nUpserted" : 0, "writeErrors" : [] "writeConcernErrors" : [] } Mixed Bulk Write Operations MongoDB C driver also supports executing mixed bulk write operations. A batch of insert, update, and remove operations can be executed together using the bulk write operations API. Ordered Bulk Write Operations Ordered bulk write operations are batched and sent to the server in the order provided for serial execution. The reply document describes the type and count of operations performed. bulk2.c.INDENT 0.0 #include <assert.h> #include <bcon.h> #include <mongoc.h> #include <stdio.h> static void bulk2 (mongoc_collection_t *collection) { mongoc_bulk_operation_t *bulk; bson_error_t error; bson_t *query; bson_t *doc; bson_t *opts; bson_t reply; char *str; bool ret; int i; bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL); /* Remove everything */ query = bson_new (); mongoc_bulk_operation_remove (bulk, query); bson_destroy (query); /* Add a few documents */ for (i = 1; i < 4; i++) { doc = BCON_NEW ("_id", BCON_INT32 (i)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); } /* {_id: 1} => {$set: {foo: "bar"}} */ query = BCON_NEW ("_id", BCON_INT32 (1)); doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}"); mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error); bson_destroy (query); bson_destroy (doc); /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */ opts = BCON_NEW ("upsert", BCON_BOOL (true)); query = BCON_NEW ("_id", BCON_INT32 (4)); doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}"); mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error); bson_destroy (query); bson_destroy (doc); bson_destroy (opts); /* replace {j:1} with {j:2} */ query = BCON_NEW ("j", BCON_INT32 (1)); doc = BCON_NEW ("j", BCON_INT32 (2)); mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error); bson_destroy (query); bson_destroy (doc); ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { printf ("Error: %s\n", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/?appname=bulk2-example"); mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "test", "test"); bulk2 (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Example reply document: { "nInserted" : 3, "nMatched" : 2, "nModified" : 2, "nRemoved" : 10000, "nUpserted" : 1, "upserted" : [{"index" : 5, "_id" : 4}], "writeErrors" : [] "writeConcernErrors" : [] } The index field in the upserted array is the 0-based index of the upsert operation; in this example, the sixth operation of the overall bulk operation was an upsert, so its index is 5. Unordered Bulk Write Operations Unordered bulk write operations are batched and sent to the server in arbitrary order where they may be executed in parallel. Any errors that occur are reported after all operations are attempted. In the next example the first and third operations fail due to the unique constraint on _id. Since we are doing unordered execution the second and fourth operations succeed. bulk3.c.INDENT 0.0 #include <assert.h> #include <bcon.h> #include <mongoc.h> #include <stdio.h> static void bulk3 (mongoc_collection_t *collection) { bson_t opts = BSON_INITIALIZER; mongoc_bulk_operation_t *bulk; bson_error_t error; bson_t *query; bson_t *doc; bson_t reply; char *str; bool ret; /* false indicates unordered */ BSON_APPEND_BOOL (&opts, "ordered", false); bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts); bson_destroy (&opts); /* Add a document */ doc = BCON_NEW ("_id", BCON_INT32 (1)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); /* remove {_id: 2} */ query = BCON_NEW ("_id", BCON_INT32 (2)); mongoc_bulk_operation_remove_one (bulk, query); bson_destroy (query); /* insert {_id: 3} */ doc = BCON_NEW ("_id", BCON_INT32 (3)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); /* replace {_id:4} {'i': 1} */ query = BCON_NEW ("_id", BCON_INT32 (4)); doc = BCON_NEW ("i", BCON_INT32 (1)); mongoc_bulk_operation_replace_one (bulk, query, doc, false); bson_destroy (query); bson_destroy (doc); ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { printf ("Error: %s\n", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); bson_destroy (&opts); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/?appname=bulk3-example"); mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "test", "test"); bulk3 (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Example reply document: { "nInserted" : 0, "nMatched" : 1, "nModified" : 1, "nRemoved" : 1, "nUpserted" : 0, "writeErrors" : [ { "index" : 0, "code" : 11000, "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" }, { "index" : 2, "code" : 11000, "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ], "writeConcernErrors" : [] } Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 } The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000. Bulk Operation Bypassing Document Validation This feature is only available when using MongoDB 3.2 and later. By default bulk operations are validated against the schema, if any is defined. In certain cases however it may be necessary to bypass the document validation. bulk5.c.INDENT 0.0 #include <assert.h> #include <bcon.h> #include <mongoc.h> #include <stdio.h> static void bulk5_fail (mongoc_collection_t *collection) { mongoc_bulk_operation_t *bulk; bson_error_t error; bson_t *doc; bson_t reply; char *str; bool ret; bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL); /* Two inserts */ doc = BCON_NEW ("_id", BCON_INT32 (31)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); doc = BCON_NEW ("_id", BCON_INT32 (32)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); /* The above documents do not comply to the schema validation rules * we created previously, so this will result in an error */ ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { printf ("Error: %s\n", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); } static void bulk5_success (mongoc_collection_t *collection) { mongoc_bulk_operation_t *bulk; bson_error_t error; bson_t *doc; bson_t reply; char *str; bool ret; bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL); /* Allow this document to bypass document validation. * NOTE: When authentication is enabled, the authenticated user must have * either the "dbadmin" or "restore" roles to bypass document validation */ mongoc_bulk_operation_set_bypass_document_validation (bulk, true); /* Two inserts */ doc = BCON_NEW ("_id", BCON_INT32 (31)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); doc = BCON_NEW ("_id", BCON_INT32 (32)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { printf ("Error: %s\n", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); } int main (int argc, char *argv[]) { bson_t *options; bson_error_t error; mongoc_client_t *client; mongoc_collection_t *collection; mongoc_database_t *database; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/?appname=bulk5-example"); mongoc_client_set_error_api (client, 2); database = mongoc_client_get_database (client, "testasdf"); /* Create schema validator */ options = BCON_NEW ( "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}"); collection = mongoc_database_create_collection (database, "collname", options, &error); if (collection) { bulk5_fail (collection); bulk5_success (collection); mongoc_collection_destroy (collection); } else { fprintf (stderr, "Couldn't create collection: '%s'\n", error.message); } bson_free (options); mongoc_database_destroy (database); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } { "nInserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "nUpserted" : 0, "writeErrors" : [ { "index" : 0, "code" : 121, "errmsg" : "Document failed validation" } ] } Error: Document failed validation { "nInserted" : 2, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "nUpserted" : 0, "writeErrors" : [] } The bson_error_t domain is MONGOC_ERROR_COMMAND. Bulk Operation Write Concerns By default bulk operations are executed with the write_concern of the collection they are executed against. A custom write concern can be passed to the mongoc_collection_create_bulk_operation_with_opts() method. Write concern errors (e.g. wtimeout) will be reported after all operations are attempted, regardless of execution order. bulk4.c.INDENT 0.0 #include <assert.h> #include <bcon.h> #include <mongoc.h> #include <stdio.h> static void bulk4 (mongoc_collection_t *collection) { bson_t opts = BSON_INITIALIZER; mongoc_write_concern_t *wc; mongoc_bulk_operation_t *bulk; bson_error_t error; bson_t *doc; bson_t reply; char *str; bool ret; wc = mongoc_write_concern_new (); mongoc_write_concern_set_w (wc, 4); mongoc_write_concern_set_wtimeout (wc, 100); /* milliseconds */ mongoc_write_concern_append (wc, &opts); bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts); /* Two inserts */ doc = BCON_NEW ("_id", BCON_INT32 (10)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); doc = BCON_NEW ("_id", BCON_INT32 (11)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { printf ("Error: %s\n", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); mongoc_write_concern_destroy (wc); bson_destroy (&opts); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/?appname=bulk4-example"); mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "test", "test"); bulk4 (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Example reply document and error message: { "nInserted" : 2, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "nUpserted" : 0, "writeErrors" : [], "writeConcernErrors" : [ { "code" : 64, "errmsg" : "waiting for replication timed out" } ] } Error: waiting for replication timed out The bson_error_t domain is MONGOC_ERROR_WRITE_CONCERN if there are write concern errors and no write errors. Write errors indicate failed operations, so they take precedence over write concern errors, which mean merely that the write concern is not satisfied yet. Setting Collation Order This feature is only available when using MongoDB 3.4 and later. bulk-collation.c.INDENT 0.0 #include <bcon.h> #include <mongoc.h> #include <stdio.h> static void bulk_collation (mongoc_collection_t *collection) { mongoc_bulk_operation_t *bulk; bson_t *opts; bson_t *doc; bson_t *selector; bson_t *update; bson_error_t error; bson_t reply; char *str; uint32_t ret; /* insert {_id: "one"} and {_id: "One"} */ bulk = mongoc_collection_create_bulk_operation_with_opts ( collection, NULL); doc = BCON_NEW ("_id", BCON_UTF8 ("one")); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); doc = BCON_NEW ("_id", BCON_UTF8 ("One")); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); /* "One" normally sorts before "one"; make "one" come first */ opts = BCON_NEW ("collation", "{", "locale", BCON_UTF8 ("en_US"), "caseFirst", BCON_UTF8 ("lower"), "}"); /* set x=1 on the document with _id "One", which now sorts after "one" */ update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}"); selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}"); mongoc_bulk_operation_update_one_with_opts ( bulk, selector, update, opts, &error); ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { printf ("Error: %s\n", error.message); } bson_destroy (&reply); bson_destroy (update); bson_destroy (selector); bson_destroy (opts); mongoc_bulk_operation_destroy (bulk); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/?appname=bulk-collation"); mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "db", "collection"); bulk_collation (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } { "nInserted" : 2, "nMatched" : 1, "nModified" : 1, "nRemoved" : 0, "nUpserted" : 0, "writeErrors" : [ ] } Unacknowledged Bulk Writes Set "w" to zero for an unacknowledged write. The driver sends unacknowledged writes using the legacy opcodes OP_INSERT, OP_UPDATE, and OP_DELETE. bulk6.c.INDENT 0.0 #include <bcon.h> #include <mongoc.h> #include <stdio.h> static void bulk6 (mongoc_collection_t *collection) { bson_t opts = BSON_INITIALIZER; mongoc_write_concern_t *wc; mongoc_bulk_operation_t *bulk; bson_error_t error; bson_t *doc; bson_t *selector; bson_t reply; char *str; bool ret; wc = mongoc_write_concern_new (); mongoc_write_concern_set_w (wc, 0); mongoc_write_concern_append (wc, &opts); bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts); doc = BCON_NEW ("_id", BCON_INT32 (10)); mongoc_bulk_operation_insert (bulk, doc); bson_destroy (doc); selector = BCON_NEW ("_id", BCON_INT32 (11)); mongoc_bulk_operation_remove_one (bulk, selector); bson_destroy (selector); ret = mongoc_bulk_operation_execute (bulk, &reply, &error); str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); if (!ret) { printf ("Error: %s\n", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); mongoc_write_concern_destroy (wc); bson_destroy (&opts); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/?appname=bulk6-example"); mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "test", "test"); bulk6 (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } The reply document is empty: { } Further Reading See the Driver Bulk API Spec, which describes bulk write operations for all MongoDB drivers. Aggregation Framework Examples This document provides a number of practical examples that display the capabilities of the aggregation framework. The Aggregations using the Zip Codes Data Set examples uses a publicly available data set of all zipcodes and populations in the United States. These data are available at: zips.json. Requirements Let's check if everything is installed. Use the following command to load zips.json data set into mongod instance: $ mongoimport --drop -d test -c zipcodes zips.json Let's use the MongoDB shell to verify that everything was imported successfully. $ mongo test MongoDB shell version: 2.6.1 connecting to: test > db.zipcodes.count() 29467 > db.zipcodes.findOne() { "_id" : "35004", "city" : "ACMAR", "loc" : [ -86.51557, 33.584132 ], "pop" : 6055, "state" : "AL" } Aggregations using the Zip Codes Data Set Each document in this collection has the following form: { "_id" : "35004", "city" : "Acmar", "state" : "AL", "pop" : 6055, "loc" : [-86.51557, 33.584132] } In these documents: • The _id field holds the zipcode as a string. • The city field holds the city name. • The state field holds the two letter state abbreviation. • The pop field holds the population. • The loc field holds the location as a [latitude, longitude] array. States with Populations Over 10 Million To get all states with a population greater than 10 million, use the following aggregation pipeline: aggregation1.c.INDENT 0.0 #include <mongoc.h> #include <stdio.h> static void print_pipeline (mongoc_collection_t *collection) { mongoc_cursor_t *cursor; bson_error_t error; const bson_t *doc; bson_t *pipeline; char *str; pipeline = BCON_NEW ("pipeline", "[", "{", "$group", "{", "_id", "$state", "total_pop", "{", "$sum", "$pop", "}", "}", "}", "{", "$match", "{", "total_pop", "{", "$gte", BCON_INT32 (10000000), "}", "}", "}", "]"); cursor = mongoc_collection_aggregate ( collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL); while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_canonical_extended_json (doc, NULL); printf ("%s\n", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\n", error.message); } mongoc_cursor_destroy (cursor); bson_destroy (pipeline); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_init (); client = mongoc_client_new ( "mongodb://localhost:27017?appname=aggregation-example"); mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, "test", "zipcodes"); print_pipeline (collection); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } { "_id" : "PA", "total_pop" : 11881643 } { "_id" : "OH", "total_pop" : 10847115 } { "_id" : "NY", "total_pop" : 17990455 } { "_id" : "FL", "total_pop" : 12937284 } { "_id" : "TX", "total_pop" : 16986510 } { "_id" : "IL", "total_pop" : 11430472 } { "_id" : "CA", "total_pop" : 29760021 } The above aggregation pipeline is build from two pipeline operators: $group and $match. The $group pipeline operator requires _id field where we specify grouping; remaining fields specify how to generate composite value and must use one of the group aggregation functions: $addToSet, $first, $last, $max, $min, $avg, $push, $sum. The $match pipeline operator syntax is the same as the read operation query syntax. The $group process reads all documents and for each state it creates a separate document, for example: { "_id" : "WA", "total_pop" : 4866692 } The total_pop field uses the $sum aggregation function to sum the values of all pop fields in the source documents. Documents created by $group are piped to the $match pipeline operator. It returns the documents with the value of total_pop field greater than or equal to 10 million. Average City Population by State To get the first three states with the greatest average population per city, use the following aggregation: pipeline = BCON_NEW ("pipeline", "[", "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}", "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}", "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}", "{", "$limit", BCON_INT32 (3) "}", "]"); This aggregate pipeline produces: { "_id" : "DC", "avg_city_pop" : 303450.0 } { "_id" : "FL", "avg_city_pop" : 27942.29805615551 } { "_id" : "CA", "avg_city_pop" : 27735.341099720412 } The above aggregation pipeline is build from three pipeline operators: $group, $sort and $limit. The first $group operator creates the following documents: { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 } Note, that the $group operator can't use nested documents except the _id field. The second $group uses these documents to create the following documents: { "_id" : "FL", "avg_city_pop" : 27942.29805615551 } These documents are sorted by the avg_city_pop field in descending order. Finally, the $limit pipeline operator returns the first 3 documents from the sorted set. distinct and mapReduce This document provides some practical, simple, examples to demonstrate the distinct and mapReduce commands. Setup First we'll write some code to insert sample data: doc-common-insert.c.INDENT 0.0 /* Don't try to compile this file on its own. It's meant to be #included by example code */ /* Insert some sample data */ bool insert_data (mongoc_collection_t *collection) { mongoc_bulk_operation_t *bulk; enum N { ndocs = 4 }; bson_t *docs[ndocs]; bson_error_t error; int i = 0; bool ret; bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL); docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]"); docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]"); docs[2] = BCON_NEW ( "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]"); docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]"); for (i = 0; i < ndocs; i++) { mongoc_bulk_operation_insert (bulk, docs[i]); bson_destroy (docs[i]); docs[i] = NULL; } ret = mongoc_bulk_operation_execute (bulk, NULL, &error); if (!ret) { fprintf (stderr, "Error inserting data: %s\n", error.message); } mongoc_bulk_operation_destroy (bulk); return ret; } /* A helper which we'll use a lot later on */ void print_res (const bson_t *reply) { BSON_ASSERT (reply); char *str = bson_as_canonical_extended_json (reply, NULL); printf ("%s\n", str); bson_free (str); } distinct command This is how to use the distinct command to get the distinct values of x which are greater than 1: distinct.c.INDENT 0.0 bool distinct (mongoc_database_t *database) { bson_t *command; bson_t reply; bson_error_t error; bool res; bson_iter_t iter; bson_iter_t array_iter; double val; command = BCON_NEW ("distinct", BCON_UTF8 (COLLECTION_NAME), "key", BCON_UTF8 ("x"), "query", "{", "x", "{", "$gt", BCON_DOUBLE (1.0), "}", "}"); res = mongoc_database_command_simple (database, command, NULL, &reply, &error); if (!res) { fprintf (stderr, "Error with distinct: %s\n", error.message); goto cleanup; } /* Do something with reply (in this case iterate through the values) */ if (!(bson_iter_init_find (&iter, &reply, "values") && BSON_ITER_HOLDS_ARRAY (&iter) && bson_iter_recurse (&iter, &array_iter))) { fprintf (stderr, "Couldn't extract \"values\" field from response\n"); goto cleanup; } while (bson_iter_next (&array_iter)) { if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) { val = bson_iter_double (&array_iter); printf ("Next double: %f\n", val); } } cleanup: /* cleanup */ bson_destroy (command); bson_destroy (&reply); return res; } mapReduce - basic example A simple example using the map reduce framework. It simply adds up the number of occurrences of each "tag". First define the map and reduce functions: constants.c.INDENT 0.0 const char *const COLLECTION_NAME = "things"; /* Our map function just emits a single (key, 1) pair for each tag in the array: */ const char *const MAPPER = "function () {" "this.tags.forEach(function(z) {" "emit(z, 1);" "});" "}"; /* The reduce function sums over all of the emitted values for a given key: */ const char *const REDUCER = "function (key, values) {" "var total = 0;" "for (var i = 0; i < values.length; i++) {" "total += values[i];" "}" "return total;" "}"; /* Note We can't just return values.length as the reduce function might be called iteratively on the results of other reduce steps. */ Run the mapReduce command: map-reduce-basic.c.INDENT 0.0 bool map_reduce_basic (mongoc_database_t *database) { bson_t reply; bson_t *command; bool res; bson_error_t error; mongoc_cursor_t *cursor; const bson_t *doc; bool map_reduce_done = false; bool query_done = false; const char *out_collection_name = "outCollection"; mongoc_collection_t *out_collection; /* Empty find query */ bson_t find_query = BSON_INITIALIZER; /* Construct the mapReduce command */ /* Other arguments can also be specified here, like "query" or "limit" and so on */ command = BCON_NEW ("mapReduce", BCON_UTF8 (COLLECTION_NAME), "map", BCON_CODE (MAPPER), "reduce", BCON_CODE (REDUCER), "out", BCON_UTF8 (out_collection_name)); res = mongoc_database_command_simple (database, command, NULL, &reply, &error); map_reduce_done = true; if (!res) { fprintf (stderr, "MapReduce failed: %s\n", error.message); goto cleanup; } /* Do something with the reply (it doesn't contain the mapReduce results) */ print_res (&reply); /* Now we'll query outCollection to see what the results are */ out_collection = mongoc_database_get_collection (database, out_collection_name); cursor = mongoc_collection_find_with_opts ( out_collection, &find_query, NULL, NULL); query_done = true; /* Do something with the results */ while (mongoc_cursor_next (cursor, &doc)) { print_res (doc); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "ERROR: %s\n", error.message); res = false; goto cleanup; } cleanup: /* cleanup */ if (query_done) { mongoc_cursor_destroy (cursor); mongoc_collection_destroy (out_collection); } if (map_reduce_done) { bson_destroy (&reply); bson_destroy (command); } return res; } mapReduce - more complicated example You must have replica set running for this. In this example we contact a secondary in the replica set and do an "inline" map reduce, so the results are returned immediately: map-reduce-advanced.c.INDENT 0.0 bool map_reduce_advanced (mongoc_database_t *database) { bson_t *command; bson_error_t error; bool res = true; mongoc_cursor_t *cursor; mongoc_read_prefs_t *read_pref; const bson_t *doc; /* Construct the mapReduce command */ /* Other arguments can also be specified here, like "query" or "limit" and so on */ /* Read the results inline from a secondary replica */ command = BCON_NEW ("mapReduce", BCON_UTF8 (COLLECTION_NAME), "map", BCON_CODE (MAPPER), "reduce", BCON_CODE (REDUCER), "out", "{", "inline", "1", "}"); read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY); cursor = mongoc_database_command ( database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref); /* Do something with the results */ while (mongoc_cursor_next (cursor, &doc)) { print_res (doc); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "ERROR: %s\n", error.message); res = false; } mongoc_cursor_destroy (cursor); mongoc_read_prefs_destroy (read_pref); bson_destroy (command); return res; } Running the Examples Here's how to run the example code basic-aggregation.c.INDENT 0.0 /* * Copyright 2016 MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <mongoc.h> #include <stdio.h> #include "constants.c" #include "../doc-common-insert.c" #include "distinct.c" #include "map-reduce-basic.c" #include "map-reduce-advanced.c" int main (int argc, char *argv[]) { mongoc_database_t *database = NULL; mongoc_client_t *client = NULL; mongoc_collection_t *collection = NULL; char *host_and_port = NULL; int res = 0; if (argc != 2) { fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]); fprintf (stderr, "the connection string can be of the following forms:\n"); fprintf (stderr, "localhost\t\t\t\tlocal machine\n"); fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n"); fprintf (stderr, "mongodb://user:pass@localhost:27017\t" "local machine on port 27017, and authenticate with username " "user and password pass\n"); return 1; } mongoc_init (); if (strncmp (argv[1], "mongodb://", 10) == 0) { host_and_port = bson_strdup (argv[1]); } else { host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]); } client = mongoc_client_new (host_and_port); if (!client) { fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port); res = 2; goto cleanup; } mongoc_client_set_error_api (client, 2); database = mongoc_client_get_database (client, "test"); collection = mongoc_database_get_collection (database, COLLECTION_NAME); printf ("Inserting data\n"); if (!insert_data (collection)) { res = 3; goto cleanup; } printf ("distinct\n"); if (!distinct (database)) { res = 4; goto cleanup; } printf ("map reduce\n"); if (!map_reduce_basic (database)) { res = 5; goto cleanup; } printf ("more complicated map reduce\n"); if (!map_reduce_advanced (database)) { res = 6; goto cleanup; } cleanup: if (collection) { mongoc_collection_destroy (collection); } if (database) { mongoc_database_destroy (database); } if (client) { mongoc_client_destroy (client); } if (host_and_port) { bson_free (host_and_port); } mongoc_cleanup (); return res; } (instructions for how to do this can be found here). $ mongod Now compile and run the example program: $ cd examples/basic_aggregation/ $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./agg-example localhost Inserting data distinct Next double: 2.000000 Next double: 3.000000 map reduce { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 } { "_id" : "cat", "value" : 63 } { "_id" : "dog", "value" : 42 } { "_id" : "mouse", "value" : 21 } more complicated map reduce { "results" : [ { "_id" : "cat", "value" : 63 }, { "_id" : "dog", "value" : 42 }, { "_id" : "mouse", "value" : 21 } ], "timeMillis" : 14, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 } Using libmongoc in a Microsoft Visual Studio project Download and install libmongoc on your system, then open Visual Studio, select "File→New→Project...", and create a new Win32 Console Application. [image] Remember to switch the platform from 32-bit to 64-bit: [image] Right-click on your console application in the Solution Explorer and select "Properties". Choose to edit properties for "All Configurations", expand the "C/C++" options and choose "General". Add to the "Additional Include Directories" these paths: C:\mongo-c-driver\include\libbson-1.0 C:\mongo-c-driver\include\libmongoc-1.0 [image] (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your include paths will be different.) Also in the Properties dialog, expand the "Linker" options and choose "Input", and add to the "Additional Dependencies" these libraries: C:\mongo-c-driver\lib\bson-1.0.lib C:\mongo-c-driver\lib\mongoc-1.0.lib [image] Adding these libraries as dependencies provides linker symbols to build your application, but to actually run it, libbson's and libmongoc's DLLs must be in your executable path. Select "Debugging" in the Properties dialog, and set the "Environment" option to: PATH=c:/mongo-c-driver/bin [image] Finally, include "mongoc.h" in your project's "stdafx.h": #include <mongoc.h> Static linking Following the instructions above, you have dynamically linked your application to the libbson and libmongoc DLLs. This is usually the right choice. If you want to link statically instead, update your "Additional Dependencies" list by removing bson-1.0.lib and mongoc-1.0.lib and replacing them with these libraries: C:\mongo-c-driver\lib\bson-static-1.0.lib C:\mongo-c-driver\lib\mongoc-static-1.0.lib ws2_32.lib Secur32.lib Crypt32.lib BCrypt.lib [image] (To explain the purpose of each library: bson-static-1.0.lib and mongoc-static-1.0.lib are static archives of the driver code. The socket library ws2_32 is required by libbson, which uses the socket routine gethostname to help guarantee ObjectId uniqueness. The BCrypt library is used by libmongoc for SSL connections to MongoDB, and Secur32 and Crypt32 are required for enterprise authentication methods like Kerberos.) Finally, define two preprocessor symbols before including mongoc.h in your stdafx.h: #define BSON_STATIC #define MONGOC_STATIC #include <mongoc.h> Making these changes to your project is only required for static linking; for most people, the dynamic-linking instructions above are preferred. Next Steps Now you can build and debug applications in Visual Studio that use libbson and libmongoc. Proceed to making-a-connection in the tutorial to learn how connect to MongoDB and perform operations. Creating Indexes To create indexes on a MongoDB collection, execute the createIndexes command with mongoc_database_write_command_with_opts. See the MongoDB Manual entry for the createIndexes command for details. Example example-create-indexes.c.INDENT 0.0 /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags * --libs libmongoc-1.0) */ /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */ #include <mongoc.h> #include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_database_t *db; const char *uristr = "mongodb://127.0.0.1/?appname=create-indexes-example"; const char *collection_name = "test"; bson_t keys; char *index_name; bson_t *create_indexes; bson_t reply; char *reply_str; bson_error_t error; bool r; mongoc_init (); if (argc > 1) { uristr = argv[1]; } if (argc > 2) { collection_name = argv[2]; } client = mongoc_client_new (uristr); if (!client) { fprintf (stderr, "Failed to parse URI.\n"); return EXIT_FAILURE; } mongoc_client_set_error_api (client, 2); db = mongoc_client_get_database (client, "test"); /* ascending index on field "x" */ bson_init (&keys); BSON_APPEND_INT32 (&keys, "x", 1); index_name = mongoc_collection_keys_to_index_string (&keys); create_indexes = BCON_NEW ("createIndexes", BCON_UTF8 (collection_name), "indexes", "[", "{", "key", BCON_DOCUMENT (&keys), "name", BCON_UTF8 (index_name), "}", "]"); r = mongoc_database_write_command_with_opts ( db, create_indexes, NULL /* opts */, &reply, &error); reply_str = bson_as_json (&reply, NULL); printf ("%s\n", reply_str); if (!r) { fprintf (stderr, "Error in createIndexes: %s\n", error.message); } bson_free (index_name); bson_free (reply_str); bson_destroy (&reply); bson_destroy (create_indexes); mongoc_database_destroy (db); mongoc_client_destroy (client); mongoc_cleanup (); return r ? EXIT_SUCCESS : EXIT_FAILURE; } API Reference Initialization and cleanup Synopsis Initialize the MongoDB C Driver by calling mongoc_init exactly once at the beginning of your program. It is responsible for initializing global state such as process counters, SSL, and threading primitives. Call mongoc_cleanup exactly once at the end of your program to release all memory and other resources allocated by the driver. You must not call any other MongoDB C Driver functions after mongoc_cleanup. Note that mongoc_init does not reinitialize the driver after mongoc_cleanup. Deprecated feature: automatic initialization and cleanup On some platforms the driver can automatically call mongoc_init before main, and call mongoc_cleanup as the process exits. This is problematic in situations where related libraries also execute cleanup code on shutdown, and it creates inconsistent rules across platforms. Therefore the automatic initialization and cleanup feature is deprecated, and will be dropped in version 2.0. Meanwhile, for backward compatibility, the feature is enabled by default on platforms where it is available. For portable, future-proof code, always call mongoc_init and mongoc_cleanup yourself, and configure the driver like: ./configure --disable-automatic-init-and-cleanup Or with CMake: cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO Logging MongoDB C driver Logging Abstraction Synopsis typedef enum { MONGOC_LOG_LEVEL_ERROR, MONGOC_LOG_LEVEL_CRITICAL, MONGOC_LOG_LEVEL_WARNING, MONGOC_LOG_LEVEL_MESSAGE, MONGOC_LOG_LEVEL_INFO, MONGOC_LOG_LEVEL_DEBUG, MONGOC_LOG_LEVEL_TRACE, } mongoc_log_level_t; #define MONGOC_ERROR(...) #define MONGOC_CRITICAL(...) #define MONGOC_WARNING(...) #define MONGOC_MESSAGE(...) #define MONGOC_INFO(...) #define MONGOC_DEBUG(...) typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level, const char *log_domain, const char *message, void *user_data); void mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data); void mongoc_log (mongoc_log_level_t log_level, const char *log_domain, const char *format, ...) BSON_GNUC_PRINTF (3, 4); const char * mongoc_log_level_str (mongoc_log_level_t log_level); void mongoc_log_default_handler (mongoc_log_level_t log_level, const char *log_domain, const char *message, void *user_data); void mongoc_log_trace_enable (void); void mongoc_log_trace_disable (void); The MongoDB C driver comes with an abstraction for logging that you can use in your application, or integrate with an existing logging system. Macros To make logging a little less painful, various helper macros are provided. See the following example. #undef MONGOC_LOG_DOMAIN #define MONGOC_LOG_DOMAIN "my-custom-domain" MONGOC_WARNING ("An error occurred: %s", strerror (errno)); Custom Log Handlers The default log handler prints a timestamp and the log message to stdout, or to stderr for warnings, critical messages, and errors. You can override the handler with mongoc_log_set_handler(). Your handler function is called in a mutex for thread safety. For example, you could register a custom handler to suppress messages at INFO level and below: void my_logger (mongoc_log_level_t log_level, const char *log_domain, const char *message, void *user_data) { /* smaller values are more important */ if (log_level < MONGOC_LOG_LEVEL_INFO) { mongoc_log_default_handler (log_level, log_domain, message, user_data); } } int main (int argc, char *argv[]) { mongoc_init (); mongoc_log_set_handler (my_logger, NULL); /* ... your code ... */ mongoc_cleanup (); return 0; } To restore the default handler: mongoc_log_set_handler (mongoc_log_default_handler, NULL); Disable logging To disable all logging, including warnings, critical messages and errors, provide an empty log handler: mongoc_log_set_handler (NULL, NULL); Tracing If compiling your own copy of the MongoDB C driver, consider configuring with --enable-tracing to enable function tracing and hex dumps of network packets to STDERR and STDOUT during development and debugging. This is especially useful when debugging what may be going on internally in the driver. Trace messages can be enabled and disabled by calling mongoc_log_trace_enable() and mongoc_log_trace_disable() NOTE: Compiling the driver with --enable-tracing will affect its performance. Disabling tracing with mongoc_log_trace_disable() significantly reduces the overhead, but cannot remove it completely. « index Error Reporting Description Many C Driver functions report errors by returning false or -1 and filling out a bson_error_t structure with an error domain, error code, and message. Use domain to determine which subsystem generated the error, and code for the specific error. message is a human-readable error description. See also: Handling Errors in libbson. ┌──────────────────────────────┬────────────────────────────────────────────┬───────────────────────────────────┐ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_CLIENT │ MONGOC_ERROR_CLIENT_TOO_BIG │ You tried to send a │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_CLIENT_AUTHENTICATE │ Wrong credentials, or │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER │ You tried an SSL │ └──────────────────────────────┴────────────────────────────────────────────┴───────────────────────────────────┘ │ │ MONGOC_ERROR_CLIENT_IN_EXHAUST │ You began iterating an │ │ │ │ mongoc_client_t. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_CLIENT_SESSION_FAILURE │ Failure related to │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_STREAM │ MONGOC_ERROR_STREAM_NAME_RESOLUTION │ DNS failure. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_STREAM_SOCKET │ Timeout communicating │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_STREAM_CONNECT │ Failed to connect to │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_PROTOCOL │ MONGOC_ERROR_PROTOCOL_INVALID_REPLY │ Corrupt response from │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION │ The server version is │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_CURSOR │ MONGOC_ERROR_CURSOR_INVALID_CURSOR │ You passed bad arguments │ │ │ │ mongoc_collection_find_with_opts, │ │ │ │ mongoc_cursor_next on a │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN │ A resume token was not returned │ │ │ │ mongoc_change_stream_next │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_QUERY │ MONGOC_ERROR_QUERY_FAILURE │ Error API Version 1: Server error │ │ │ │ error message is in message. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_SERVER │ MONGOC_ERROR_QUERY_FAILURE │ Error API Version 2: Server error │ │ │ │ error message is in message. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_SASL │ A SASL error code. │ man sasl_errors for a list of │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_BSON │ MONGOC_ERROR_BSON_INVALID │ You passed an invalid or │ │ │ │ mongoc_collection_create_index │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_NAMESPACE │ MONGOC_ERROR_NAMESPACE_INVALID │ You tried to create a collection │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_COMMAND │ MONGOC_ERROR_COMMAND_INVALID_ARG │ Many functions set this error │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION │ You tried to use a command option │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_DUPLICATE_KEY │ An insert or update failed │ │ │ │ _id or other unique-index │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_COMMAND │ Error code from server. │ Error API Version 1: Server error │ │ │ │ message is in message. │ └──────────────────────────────┴────────────────────────────────────────────┴───────────────────────────────────┘ │MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: Server error │ │ │ │ message is in message. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_COLLECTION │ MONGOC_ERROR_COLLECTION_INSERT_FAILED, │ Invalid or empty input to │ │ │ MONGOC_ERROR_COLLECTION_UPDATE_FAILED, │ mongoc_collection_insert_one, │ │ │ MONGOC_ERROR_COLLECTION_DELETE_FAILED. │ mongoc_collection_insert_bulk, │ │ │ │ mongoc_collection_update_one, │ │ │ │ mongoc_collection_update_many, │ │ │ │ mongoc_collection_replace_one, │ │ │ │ mongoc_collection_delete_one, or │ │ │ │ mongoc_collection_delete_many. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_COLLECTION │ Error code from server. │ Error API Version 1: Server error │ │ │ │ mongoc_collection_insert_one, │ │ │ │ mongoc_collection_insert_bulk, │ │ │ │ mongoc_collection_update_one, │ │ │ │ mongoc_collection_update_many, │ │ │ │ mongoc_collection_replace_one, │ │ │ │ mongoc_collection_delete_one, or │ │ │ │ mongoc_collection_delete_many. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: Server error │ │ │ │ mongoc_collection_insert_one, │ │ │ │ mongoc_collection_insert_bulk, │ │ │ │ mongoc_collection_update_one, │ │ │ │ mongoc_collection_update_many, │ │ │ │ mongoc_collection_replace_one, │ │ │ │ mongoc_collection_delete_one, or │ │ │ │ mongoc_collection_delete_many. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_GRIDFS │ MONGOC_ERROR_GRIDFS_CHUNK_MISSING │ The GridFS file is missing a │ │ │ │ document in its chunks │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_GRIDFS_INVALID_FILENAME │ You passed a NULL filename to │ │ │ │ mongoc_gridfs_remove_by_filename. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │ │ MONGOC_ERROR_GRIDFS_PROTOCOL_ERROR │ You called │ │ │ │ mongoc_gridfs_file_set_id after │ │ │ │ mongoc_gridfs_file_save. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_SCRAM │ MONGOC_ERROR_SCRAM_PROTOCOL_ERROR │ Failure in SCRAM-SHA-1 │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_SERVER_SELECTION │ MONGOC_ERROR_SERVER_SELECTION_FAILURE │ No replica set member or mongos │ │ │ │ mongoc_read_prefs_t. │ ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤ │MONGOC_ERROR_WRITE_CONCERN │ Error code from server. │ There was a write concern error │ └──────────────────────────────┴────────────────────────────────────────────┴───────────────────────────────────┘ Setting the Error API Version The driver's error reporting began with a design flaw: when the error domain is MONGOC_ERROR_COLLECTION, MONGOC_ERROR_QUERY, or MONGOC_ERROR_COMMAND, the error code might originate from the server or the driver. An application cannot always know where an error originated, and therefore cannot tell what the code means. For example, if mongoc_collection_update_one sets the error's domain to MONGOC_ERROR_COLLECTION and its code to 24, the application cannot know whether 24 is the generic driver error code MONGOC_ERROR_COLLECTION_UPDATE_FAILED or the specific server error code "LockTimeout". To fix this flaw while preserving backward compatibility, the C Driver 1.4 introduces "Error API Versions". Version 1, the default Error API Version, maintains the flawed behavior. Version 2 adds a new error domain, MONGOC_ERROR_SERVER. In Version 2, error codes originating on the server always have error domain MONGOC_ERROR_SERVER or MONGOC_ERROR_WRITE_CONCERN. When the driver uses Version 2 the application can always determine the origin and meaning of error codes. New applications should use Version 2, and existing applications should be updated to use Version 2 as well. ┌────────────────────────────────────────────┬────────────────────────────┬────────────────────────────┐ │Error Source │ API Version 1 │ API Version 2 │ └────────────────────────────────────────────┴────────────────────────────┴────────────────────────────┘ │mongoc_cursor_error │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │ ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤ │mongoc_client_command_with_opts, │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │ │mongoc_database_command_with_opts, │ │ │ │and other command │ │ │ │functions │ │ │ ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤ │mongoc_collection_count_with_opts │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │ │mongoc_client_get_database_names_with_opts, │ │ │ │and other command helper functions │ │ │ ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤ │mongoc_collection_insert_one │ MONGOC_ERROR_COMMAND │ MONGOC_ERROR_SERVER │ │mongoc_collection_insert_bulk │ │ │ │mongoc_collection_update_one │ │ │ │mongoc_collection_update_many │ │ │ │mongoc_collection_replace_one │ │ │ │mongoc_collection_delete_one │ │ │ │mongoc_collection_delete_many │ │ │ ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤ │mongoc_bulk_operation_execute │ MONGOC_ERROR_COMMAND │ MONGOC_ERROR_SERVER │ ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤ │Write-concern timeout │ MONGOC_ERROR_WRITE_CONCERN │ MONGOC_ERROR_WRITE_CONCERN │ └────────────────────────────────────────────┴────────────────────────────┴────────────────────────────┘ The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY and MONGOC_ERROR_API_VERSION_2. Set the version with mongoc_client_set_error_api or mongoc_client_pool_set_error_api. See Also MongoDB Server Error Codes Object Lifecycle This page documents the order of creation and destruction for libmongoc's main struct types. Clients and pools Call mongoc_init() once, before calling any other libmongoc functions, and call mongoc_cleanup() once before your program exits. A program that uses libmongoc from multiple threads should create a mongoc_client_pool_t with mongoc_client_pool_new(). Each thread acquires a mongoc_client_t from the pool with mongoc_client_pool_pop() and returns it with mongoc_client_pool_push() when the thread is finished using it. To destroy the pool, first return all clients, then call mongoc_client_pool_destroy(). If your program uses libmongoc from only one thread, create a mongoc_client_t directly with mongoc_client_new() or mongoc_client_new_from_uri(). Destroy it with mongoc_client_destroy(). Databases, collections, and related objects You can create a mongoc_database_t or mongoc_collection_t from a mongoc_client_t, and create a mongoc_cursor_t or mongoc_bulk_operation_t from a mongoc_collection_t. Each of these objects must be destroyed before the client they were created from, but their lifetimes are otherwise independent. GridFS objects You can create a mongoc_gridfs_t from a mongoc_client_t, create a mongoc_gridfs_file_t or mongoc_gridfs_file_list_t from a mongoc_gridfs_t, create a mongoc_gridfs_file_t from a mongoc_gridfs_file_list_t, and create a mongoc_stream_t from a mongoc_gridfs_file_t. Each of these objects depends on the object it was created from. Always destroy GridFS objects in the reverse of the order they were created. The sole exception is that a mongoc_gridfs_file_t need not be destroyed before the mongoc_gridfs_file_list_t it was created from. Sessions Start a session with mongoc_client_start_session, use the session for a sequence of operations, then free it with mongoc_client_session_destroy(). A session must be freed before the mongoc_client_t it came from. By default, sessions are causally consistent. To disable causal consistency, before starting a session create a mongoc_session_opt_t with mongoc_session_opts_new() and call mongoc_session_opts_set_causal_consistency(), then free the struct with mongoc_session_opts_destroy. Unacknowledged writes are not causally consistent. If you execute a write operation with a mongoc_write_concern_t on which you have called mongoc_write_concern_set_w with a value of 0, the write does not participate in causal consistency. A mongoc_client_session_t must be used by only one thread at a time. Due to session pooling, mongoc_client_start_session may return a session that has been idle for some time and is about to be closed after its idle timeout. Use the session within one minute of acquiring it to refresh the session and avoid a timeout. mongoc_bulk_operation_t Bulk Write Operations Synopsis typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t; The opaque type mongoc_bulk_operation_t provides an abstraction for submitting multiple write operations as a single batch. After adding all of the write operations to the mongoc_bulk_operation_t, call mongoc_bulk_operation_execute() to execute the operation. WARNING: It is only valid to call mongoc_bulk_operation_execute() once. The mongoc_bulk_operation_t must be destroyed afterwards. See Also Bulk Write Operations mongoc_change_stream_t Synopsis #include <mongoc.h> typedef struct _mongoc_change_stream_t mongoc_change_stream_t; mongoc_change_stream_t is a handle to a change stream. A collection change stream can be obtained using mongoc_collection_watch. It is recommended to use a mongoc_change_stream_t and its functions instead of a raw aggregation with a $changeStream stage. For more information see the MongoDB Manual Entry on Change Streams. Example example-collection-watch.c.INDENT 0.0 #include <mongoc.h> int main () { bson_t empty = BSON_INITIALIZER; const bson_t *doc; bson_t *to_insert = BCON_NEW ("x", BCON_INT32 (1)); const bson_t *err_doc; bson_error_t err; mongoc_client_t *client; mongoc_collection_t *coll; mongoc_change_stream_t *stream; mongoc_write_concern_t *wc = mongoc_write_concern_new (); bson_t opts = BSON_INITIALIZER; bool r; mongoc_init (); client = mongoc_client_new ("mongodb://" "localhost:27017,localhost:27018,localhost:" "27019/db?replicaSet=rs0"); if (!client) { fprintf (stderr, "Could not connect to replica set\n"); return 1; } coll = mongoc_client_get_collection (client, "db", "coll"); stream = mongoc_collection_watch (coll, &empty, NULL); mongoc_write_concern_set_wmajority (wc, 10000); mongoc_write_concern_append (wc, &opts); r = mongoc_collection_insert_one (coll, to_insert, &opts, NULL, &err); if (!r) { fprintf (stderr, "Error: %s\n", err.message); return 1; } while (mongoc_change_stream_next (stream, &doc)) { char *as_json = bson_as_relaxed_extended_json (doc, NULL); fprintf (stderr, "Got document: %s\n", as_json); bson_free (as_json); } if (mongoc_change_stream_error_document (stream, &err, &err_doc)) { if (!bson_empty (err_doc)) { fprintf (stderr, "Server Error: %s\n", bson_as_relaxed_extended_json (err_doc, NULL)); } else { fprintf (stderr, "Client Error: %s\n", err.message); } return 1; } bson_destroy (to_insert); mongoc_write_concern_destroy (wc); bson_destroy (&opts); mongoc_change_stream_destroy (stream); mongoc_collection_destroy (coll); mongoc_client_destroy (client); mongoc_cleanup (); } mongoc_client_pool_t A connection pool for multi-threaded programs. See connection-pooling. Synopsis typedef struct _mongoc_client_pool_t mongoc_client_pool_t mongoc_client_pool_t is the basis for multi-threading in the MongoDB C driver. Since mongoc_client_t structures are not thread-safe, this structure is used to retrieve a new mongoc_client_t for a given thread. This structure is thread-safe. Example example-pool.c.INDENT 0.0 /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs * libmongoc-1.0) */ /* ./example-pool [CONNECTION_STRING] */ #include <mongoc.h> #include <pthread.h> #include <stdio.h> 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, "ping", 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, "admin", &ping, NULL, NULL, &error); if (!r) { fprintf (stderr, "%s\n", 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 *uristr = "mongodb://127.0.0.1/?appname=pool-example"; mongoc_uri_t *uri; mongoc_client_pool_t *pool; pthread_t threads[10]; unsigned i; void *ret; pthread_mutex_init (&mutex, NULL); mongoc_init (); if (argc > 1) { uristr = argv[1]; } uri = mongoc_uri_new (uristr); if (!uri) { fprintf (stderr, "Failed to parse URI: \"%s\".\n", uristr); 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 0; } mongoc_client_session_t Use a session for a sequence of operations, optionally with causal consistency. See the MongoDB Manual Entry for Causal Consistency. Synopsis Start a session with mongoc_client_start_session, use the session for a sequence of operations, then free it with mongoc_client_session_destroy(). A session must be freed before the mongoc_client_t it came from. By default, sessions are causally consistent. To disable causal consistency, before starting a session create a mongoc_session_opt_t with mongoc_session_opts_new() and call mongoc_session_opts_set_causal_consistency(), then free the struct with mongoc_session_opts_destroy. Unacknowledged writes are not causally consistent. If you execute a write operation with a mongoc_write_concern_t on which you have called mongoc_write_concern_set_w with a value of 0, the write does not participate in causal consistency. A mongoc_client_session_t must be used by only one thread at a time. Due to session pooling, mongoc_client_start_session may return a session that has been idle for some time and is about to be closed after its idle timeout. Use the session within one minute of acquiring it to refresh the session and avoid a timeout. Example example-session.c.INDENT 0.0 /* gcc example-session.c -o example-session \ * $(pkg-config --cflags --libs libmongoc-1.0) */ /* ./example-session [CONNECTION_STRING] */ #include <stdio.h> #include <mongoc.h> int main (int argc, char *argv[]) { int exit_code = EXIT_FAILURE; mongoc_client_t *client; mongoc_client_session_t *client_session = NULL; mongoc_collection_t *collection = NULL; const char *uristr = "mongodb://127.0.0.1/?appname=session-example"; bson_error_t error; bson_t *selector = NULL; bson_t *update = NULL; bson_t *update_opts = NULL; bson_t *find_opts = NULL; mongoc_read_prefs_t *secondary = NULL; mongoc_cursor_t *cursor = NULL; const bson_t *doc; char *str; bool r; mongoc_init (); if (argc > 1) { uristr = argv[1]; } client = mongoc_client_new (uristr); if (!client) { fprintf (stderr, "Failed to parse URI.\n"); goto done; } mongoc_client_set_error_api (client, 2); /* pass NULL for options - by default the session is causally consistent */ client_session = mongoc_client_start_session (client, NULL, &error); if (!client_session) { fprintf (stderr, "Failed to start session: %s\n", error.message); goto done; } collection = mongoc_client_get_collection (client, "test", "collection"); selector = BCON_NEW ("_id", BCON_INT32 (1)); update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}"); update_opts = bson_new (); if (!mongoc_client_session_append (client_session, update_opts, &error)) { fprintf (stderr, "Could not add session to opts: %s\n", error.message); goto done; } r = mongoc_collection_update_one ( collection, selector, update, update_opts, NULL /* reply */, &error); if (!r) { fprintf (stderr, "Update failed: %s\n", error.message); goto done; } bson_destroy (selector); selector = BCON_NEW ("_id", BCON_INT32 (1)); secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY); find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000)); if (!mongoc_client_session_append (client_session, find_opts, &error)) { fprintf (stderr, "Could not add session to opts: %s\n", error.message); goto done; }; /* read from secondary. since we're in a causally consistent session, the * data is guaranteed to reflect the update we did on the primary. the query * blocks waiting for the secondary to catch up, if necessary, or times out * and fails after 2000 ms. */ cursor = mongoc_collection_find_with_opts ( collection, selector, find_opts, secondary); bson_destroy (selector); mongoc_read_prefs_destroy (secondary); bson_destroy (find_opts); while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_json (doc, NULL); fprintf (stdout, "%s\n", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\n", error.message); goto done; } exit_code = EXIT_SUCCESS; done: if (find_opts) { bson_destroy (find_opts); } if (update) { bson_destroy (update); } if (selector) { bson_destroy (selector); } if (update_opts) { bson_destroy (update_opts); } if (secondary) { mongoc_read_prefs_destroy (secondary); } /* destroy cursor, collection, session before the client they came from */ if (cursor) { mongoc_cursor_destroy (cursor); } if (collection) { mongoc_collection_destroy (collection); } if (client_session) { mongoc_client_session_destroy (client_session); } if (client) { mongoc_client_destroy (client); } mongoc_cleanup (); return exit_code; } mongoc_client_t A single-threaded MongoDB connection. See connection-pooling. Synopsis typedef struct _mongoc_client_t mongoc_client_t; typedef mongoc_stream_t *(*mongoc_stream_initiator_t) ( const mongoc_uri_t *uri, const mongoc_host_list_t *host, void *user_data, bson_error_t *error); mongoc_client_t is an opaque type that provides access to a MongoDB server, replica set, or sharded cluster. It maintains management of underlying sockets and routing to individual nodes based on mongoc_read_prefs_t or mongoc_write_concern_t. Streams The underlying transport for a given client can be customized, wrapped or replaced by any implementation that fulfills mongoc_stream_t. A custom transport can be set with mongoc_client_set_stream_initiator(). Thread Safety mongoc_client_t is NOT thread-safe and should only be used from one thread at a time. When used in multi-threaded scenarios, it is recommended that you use the thread-safe mongoc_client_pool_t to retrieve a mongoc_client_t for your thread. Example example-client.c.INDENT 0.0 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs * libmongoc-1.0) */ /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */ #include <mongoc.h> #include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; bson_error_t error; const bson_t *doc; const char *uristr = "mongodb://127.0.0.1/?appname=client-example"; const char *collection_name = "test"; bson_t query; char *str; mongoc_init (); if (argc > 1) { uristr = argv[1]; } if (argc > 2) { collection_name = argv[2]; } client = mongoc_client_new (uristr); if (!client) { fprintf (stderr, "Failed to parse URI.\n"); return EXIT_FAILURE; } mongoc_client_set_error_api (client, 2); bson_init (&query); #if 0 bson_append_utf8 (&query, "hello", -1, "world", -1); #endif collection = mongoc_client_get_collection (client, "test", collection_name); cursor = mongoc_collection_find_with_opts ( collection, &query, NULL, /* additional options */ NULL); /* read prefs, NULL for default */ while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_canonical_extended_json (doc, NULL); fprintf (stdout, "%s\n", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\n", error.message); return EXIT_FAILURE; } bson_destroy (&query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return EXIT_SUCCESS; } mongoc_collection_t Synopsis #include <mongoc.h> typedef struct _mongoc_collection_t mongoc_collection_t; mongoc_collection_t provides access to a MongoDB collection. This handle is useful for actions for most CRUD operations, I.e. insert, update, delete, find, etc. Read Preferences and Write Concerns Read preferences and write concerns are inherited from the parent client. They can be overridden by set_* commands if so desired. mongoc_cursor_t Client-side cursor abstraction Synopsis typedef struct _mongoc_cursor_t mongoc_cursor_t; mongoc_cursor_t provides access to a MongoDB query cursor. It wraps up the wire protocol negotiation required to initiate a query and retrieve an unknown number of documents. Cursors are lazy, meaning that no network traffic occurs until the first call to mongoc_cursor_next(). At that point we can: • Determine which host we've connected to with mongoc_cursor_get_host(). • Retrieve more records with repeated calls to mongoc_cursor_next(). • Clone a query to repeat execution at a later point with mongoc_cursor_clone(). • Test for errors with mongoc_cursor_error(). Thread Safety mongoc_cursor_t is NOT thread safe. It may only be used from the thread it was created from. Example Query MongoDB and iterate results.INDENT 0.0 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs * libmongoc-1.0) */ /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */ #include <mongoc.h> #include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; bson_error_t error; const bson_t *doc; const char *uristr = "mongodb://127.0.0.1/?appname=client-example"; const char *collection_name = "test"; bson_t query; char *str; mongoc_init (); if (argc > 1) { uristr = argv[1]; } if (argc > 2) { collection_name = argv[2]; } client = mongoc_client_new (uristr); if (!client) { fprintf (stderr, "Failed to parse URI.\n"); return EXIT_FAILURE; } mongoc_client_set_error_api (client, 2); bson_init (&query); #if 0 bson_append_utf8 (&query, "hello", -1, "world", -1); #endif collection = mongoc_client_get_collection (client, "test", collection_name); cursor = mongoc_collection_find_with_opts ( collection, &query, NULL, /* additional options */ NULL); /* read prefs, NULL for default */ while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_canonical_extended_json (doc, NULL); fprintf (stdout, "%s\n", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\n", error.message); return EXIT_FAILURE; } bson_destroy (&query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return EXIT_SUCCESS; } mongoc_database_t MongoDB Database Abstraction Synopsis typedef struct _mongoc_database_t mongoc_database_t; mongoc_database_t provides access to a MongoDB database. This handle is useful for actions a particular database object. It is not a container for mongoc_collection_t structures. Read preferences and write concerns are inherited from the parent client. They can be overridden with mongoc_database_set_read_prefs() and mongoc_database_set_write_concern(). Examples #include <mongoc.h> int main (int argc, char *argv[]) { mongoc_database_t *database; mongoc_client_t *client; mongoc_init (); client = mongoc_client_new ("mongodb://localhost/"); database = mongoc_client_get_database (client, "test"); mongoc_database_destroy (database); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } mongoc_delete_flags_t Flags for deletion operations Synopsis typedef enum { MONGOC_DELETE_NONE = 0, MONGOC_DELETE_SINGLE_REMOVE = 1 << 0, } mongoc_delete_flags_t; Deprecated WARNING: These flags are deprecated and should not be used in new code. Please use mongoc_collection_delete_one() or mongoc_collection_delete_many() instead. mongoc_find_and_modify_opts_t find_and_modify abstraction Synopsis mongoc_find_and_modify_opts_t is a builder interface to construct a find_and_modify command. It was created to be able to accommodate new arguments to the MongoDB find_and_modify command. As of MongoDB 3.2, the mongoc_write_concern_t specified on the mongoc_collection_t will be used, if any. Example flags.c.INDENT 0.0 void fam_flags (mongoc_collection_t *collection) { mongoc_find_and_modify_opts_t *opts; bson_t reply; bson_error_t error; bson_t query = BSON_INITIALIZER; bson_t *update; bool success; /* Find Zlatan Ibrahimovic, the striker */ BSON_APPEND_UTF8 (&query, "firstname", "Zlatan"); BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic"); BSON_APPEND_UTF8 (&query, "profession", "Football player"); BSON_APPEND_INT32 (&query, "age", 34); BSON_APPEND_INT32 ( &query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62)); /* Add his football position */ update = BCON_NEW ("$set", "{", "position", BCON_UTF8 ("striker"), "}"); opts = mongoc_find_and_modify_opts_new (); mongoc_find_and_modify_opts_set_update (opts, update); /* Create the document if it didn't exist, and return the updated document */ mongoc_find_and_modify_opts_set_flags ( opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW); success = mongoc_collection_find_and_modify_with_opts ( collection, &query, opts, &reply, &error); if (success) { char *str; str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); } else { fprintf ( stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } void fam_bypass (mongoc_collection_t *collection) { mongoc_find_and_modify_opts_t *opts; bson_t reply; bson_t *update; bson_error_t error; bson_t query = BSON_INITIALIZER; bool success; /* Find Zlatan Ibrahimovic, the striker */ BSON_APPEND_UTF8 (&query, "firstname", "Zlatan"); BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic"); BSON_APPEND_UTF8 (&query, "profession", "Football player"); /* Bump his age */ update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}"); opts = mongoc_find_and_modify_opts_new (); mongoc_find_and_modify_opts_set_update (opts, update); /* He can still play, even though he is pretty old. */ mongoc_find_and_modify_opts_set_bypass_document_validation (opts, true); success = mongoc_collection_find_and_modify_with_opts ( collection, &query, opts, &reply, &error); if (success) { char *str; str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); } else { fprintf ( stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } void fam_update (mongoc_collection_t *collection) { mongoc_find_and_modify_opts_t *opts; bson_t *update; bson_t reply; bson_error_t error; bson_t query = BSON_INITIALIZER; bool success; /* Find Zlatan Ibrahimovic */ BSON_APPEND_UTF8 (&query, "firstname", "Zlatan"); BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic"); /* Make him a book author */ update = BCON_NEW ("$set", "{", "author", BCON_BOOL (true), "}"); opts = mongoc_find_and_modify_opts_new (); /* Note that the document returned is the _previous_ version of the document * To fetch the modified new version, use * mongoc_find_and_modify_opts_set_flags (opts, * MONGOC_FIND_AND_MODIFY_RETURN_NEW); */ mongoc_find_and_modify_opts_set_update (opts, update); success = mongoc_collection_find_and_modify_with_opts ( collection, &query, opts, &reply, &error); if (success) { char *str; str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); } else { fprintf ( stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } void fam_fields (mongoc_collection_t *collection) { mongoc_find_and_modify_opts_t *opts; bson_t fields = BSON_INITIALIZER; bson_t *update; bson_t reply; bson_error_t error; bson_t query = BSON_INITIALIZER; bool success; /* Find Zlatan Ibrahimovic */ BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic"); BSON_APPEND_UTF8 (&query, "firstname", "Zlatan"); /* Return his goal tally */ BSON_APPEND_INT32 (&fields, "goals", 1); /* Bump his goal tally */ update = BCON_NEW ("$inc", "{", "goals", BCON_INT32 (1), "}"); opts = mongoc_find_and_modify_opts_new (); mongoc_find_and_modify_opts_set_update (opts, update); mongoc_find_and_modify_opts_set_fields (opts, &fields); /* Return the new tally */ mongoc_find_and_modify_opts_set_flags (opts, MONGOC_FIND_AND_MODIFY_RETURN_NEW); success = mongoc_collection_find_and_modify_with_opts ( collection, &query, opts, &reply, &error); if (success) { char *str; str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); } else { fprintf ( stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&fields); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } void fam_sort (mongoc_collection_t *collection) { mongoc_find_and_modify_opts_t *opts; bson_t *update; bson_t sort = BSON_INITIALIZER; bson_t reply; bson_error_t error; bson_t query = BSON_INITIALIZER; bool success; /* Find all users with the lastname Ibrahimovic */ BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic"); /* Sort by age (descending) */ BSON_APPEND_INT32 (&sort, "age", -1); /* Bump his goal tally */ update = BCON_NEW ("$set", "{", "oldest", BCON_BOOL (true), "}"); opts = mongoc_find_and_modify_opts_new (); mongoc_find_and_modify_opts_set_update (opts, update); mongoc_find_and_modify_opts_set_sort (opts, &sort); success = mongoc_collection_find_and_modify_with_opts ( collection, &query, opts, &reply, &error); if (success) { char *str; str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); } else { fprintf ( stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&sort); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } void fam_opts (mongoc_collection_t *collection) { mongoc_find_and_modify_opts_t *opts; bson_t reply; bson_t *update; bson_error_t error; bson_t query = BSON_INITIALIZER; mongoc_write_concern_t *wc; bson_t extra = BSON_INITIALIZER; bool success; /* Find Zlatan Ibrahimovic, the striker */ BSON_APPEND_UTF8 (&query, "firstname", "Zlatan"); BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic"); BSON_APPEND_UTF8 (&query, "profession", "Football player"); /* Bump his age */ update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}"); opts = mongoc_find_and_modify_opts_new (); mongoc_find_and_modify_opts_set_update (opts, update); /* Abort if the operation takes too long. */ mongoc_find_and_modify_opts_set_max_time_ms (opts, 100); /* Set write concern w: 2 */ wc = mongoc_write_concern_new (); mongoc_write_concern_set_w (wc, 2); mongoc_write_concern_append (wc, &extra); /* Some future findAndModify option the driver doesn't support conveniently */ BSON_APPEND_INT32 (&extra, "futureOption", 42); mongoc_find_and_modify_opts_append (opts, &extra); success = mongoc_collection_find_and_modify_with_opts ( collection, &query, opts, &reply, &error); if (success) { char *str; str = bson_as_canonical_extended_json (&reply, NULL); printf ("%s\n", str); bson_free (str); } else { fprintf ( stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (&extra); bson_destroy (update); bson_destroy (&query); mongoc_write_concern_destroy (wc); mongoc_find_and_modify_opts_destroy (opts); } int main (void) { mongoc_collection_t *collection; mongoc_database_t *database; mongoc_client_t *client; bson_error_t error; bson_t *options; mongoc_init (); client = mongoc_client_new ( "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example"); mongoc_client_set_error_api (client, 2); database = mongoc_client_get_database (client, "databaseName"); options = BCON_NEW ("validator", "{", "age", "{", "$lte", BCON_INT32 (34), "}", "}", "validationAction", BCON_UTF8 ("error"), "validationLevel", BCON_UTF8 ("moderate")); collection = mongoc_database_create_collection ( database, "collectionName", options, &error); if (!collection) { fprintf ( stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__); return 1; } fam_flags (collection); fam_bypass (collection); fam_update (collection); fam_fields (collection); fam_opts (collection); fam_sort (collection); mongoc_collection_drop (collection, NULL); bson_destroy (options); mongoc_database_destroy (database); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } Outputs: { "lastErrorObject": { "updatedExisting": false, "n": 1, "upserted": { "$oid": "56562a99d13e6d86239c7b00" } }, "value": { "_id": { "$oid": "56562a99d13e6d86239c7b00" }, "age": 34, "firstname": "Zlatan", "goals": 342, "lastname": "Ibrahimovic", "profession": "Football player", "position": "striker" }, "ok": 1 } { "lastErrorObject": { "updatedExisting": true, "n": 1 }, "value": { "_id": { "$oid": "56562a99d13e6d86239c7b00" }, "age": 34, "firstname": "Zlatan", "goals": 342, "lastname": "Ibrahimovic", "profession": "Football player", "position": "striker" }, "ok": 1 } { "lastErrorObject": { "updatedExisting": true, "n": 1 }, "value": { "_id": { "$oid": "56562a99d13e6d86239c7b00" }, "age": 35, "firstname": "Zlatan", "goals": 342, "lastname": "Ibrahimovic", "profession": "Football player", "position": "striker" }, "ok": 1 } { "lastErrorObject": { "updatedExisting": true, "n": 1 }, "value": { "_id": { "$oid": "56562a99d13e6d86239c7b00" }, "goals": 343 }, "ok": 1 } { "lastErrorObject": { "updatedExisting": true, "n": 1 }, "value": { "_id": { "$oid": "56562a99d13e6d86239c7b00" }, "age": 35, "firstname": "Zlatan", "goals": 343, "lastname": "Ibrahimovic", "profession": "Football player", "position": "striker", "author": true }, "ok": 1 } mongoc_gridfs_file_list_t Synopsis #include <mongoc.h> typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t; Description mongoc_gridfs_file_list_t provides a gridfs file list abstraction. It provides iteration and basic marshalling on top of a regular mongoc_collection_find_with_opts() style query. In interface, it's styled after mongoc_cursor_t. Example mongoc_gridfs_file_list_t *list; mongoc_gridfs_file_t *file; list = mongoc_gridfs_find (gridfs, query); while ((file = mongoc_gridfs_file_list_next (list))) { do_something (file); mongoc_gridfs_file_destroy (file); } mongoc_gridfs_file_list_destroy (list); mongoc_gridfs_file_opt_t Synopsis typedef struct { const char *md5; const char *filename; const char *content_type; const bson_t *aliases; const bson_t *metadata; uint32_t chunk_size; } mongoc_gridfs_file_opt_t; Description This structure contains options that can be set on a mongoc_gridfs_file_t. It can be used by various functions when creating a new gridfs file. mongoc_gridfs_file_t Synopsis typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t; Description This structure provides a MongoDB GridFS file abstraction. It provides several APIs. • readv, writev, seek, and tell. • General file metadata such as filename and length. • GridFS metadata such as md5, filename, content_type, aliases, metadata, chunk_size, and upload_date. Thread Safety This structure is NOT thread-safe and should only be used from one thread at a time. Related • mongoc_client_t • mongoc_gridfs_t • mongoc_gridfs_file_list_t • mongoc_gridfs_file_opt_t mongoc_gridfs_t Synopsis #include <mongoc.h> typedef struct _mongoc_gridfs_t mongoc_gridfs_t; Description mongoc_gridfs_t provides a MongoDB gridfs implementation. The system as a whole is made up of gridfs objects, which contain gridfs_files and gridfs_file_lists. Essentially, a basic file system API. There are extensive caveats about the kind of use cases gridfs is practical for. In particular, any writing after initial file creation is likely to both break any concurrent readers and be quite expensive. That said, this implementation does allow for arbitrary writes to existing gridfs object, just use them with caution. mongoc_gridfs also integrates tightly with the mongoc_stream_t abstraction, which provides some convenient wrapping for file creation and reading/writing. It can be used without, but its worth looking to see if your problem can fit that model. WARNING: mongoc_gridfs_t does not support read preferences. In a replica set, GridFS queries are always routed to the primary. Thread Safety mongoc_gridfs_t is NOT thread-safe and should only be used in the same thread as the owning mongoc_client_t. Lifecycle It is an error to free a mongoc_gridfs_t before freeing all related instances of mongoc_gridfs_file_t and mongoc_gridfs_file_list_t. Example example-gridfs.c.INDENT 0.0 #include <assert.h> #include <mongoc.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> int main (int argc, char *argv[]) { mongoc_gridfs_t *gridfs; mongoc_gridfs_file_t *file; mongoc_gridfs_file_list_t *list; mongoc_gridfs_file_opt_t opt = {0}; mongoc_client_t *client; mongoc_stream_t *stream; bson_t filter; bson_t opts; bson_t child; bson_error_t error; ssize_t r; char buf[4096]; mongoc_iovec_t iov; const char *filename; const char *command; bson_value_t id; if (argc < 2) { fprintf (stderr, "usage - %s command ...\n", argv[0]); return 1; } mongoc_init (); iov.iov_base = (void *) buf; iov.iov_len = sizeof buf; /* connect to localhost client */ client = mongoc_client_new ("mongodb://127.0.0.1:27017/?appname=gridfs-example"); assert (client); mongoc_client_set_error_api (client, 2); /* grab a gridfs handle in test prefixed by fs */ gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error); assert (gridfs); command = argv[1]; filename = argv[2]; if (strcmp (command, "read") == 0) { if (argc != 3) { fprintf (stderr, "usage - %s read filename\n", argv[0]); return 1; } file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error); assert (file); stream = mongoc_stream_gridfs_new (file); assert (stream); for (;;) { r = mongoc_stream_readv (stream, &iov, 1, -1, 0); assert (r >= 0); if (r == 0) { break; } if (fwrite (iov.iov_base, 1, r, stdout) != r) { MONGOC_ERROR ("Failed to write to stdout. Exiting.\n"); exit (1); } } mongoc_stream_destroy (stream); mongoc_gridfs_file_destroy (file); } else if (strcmp (command, "list") == 0) { bson_init (&filter); bson_init (&opts); bson_append_document_begin (&opts, "sort", -1, &child); BSON_APPEND_INT32 (&child, "filename", 1); bson_append_document_end (&opts, &child); list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts); bson_destroy (&filter); bson_destroy (&opts); while ((file = mongoc_gridfs_file_list_next (list))) { const char *name = mongoc_gridfs_file_get_filename (file); printf ("%s\n", name ? name : "?"); mongoc_gridfs_file_destroy (file); } mongoc_gridfs_file_list_destroy (list); } else if (strcmp (command, "write") == 0) { if (argc != 4) { fprintf (stderr, "usage - %s write filename input_file\n", argv[0]); return 1; } stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0); assert (stream); opt.filename = filename; /* the driver generates a file_id for you */ file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt); assert (file); id.value_type = BSON_TYPE_INT32; id.value.v_int32 = 1; /* optional: the following method specifies a file_id of any BSON type */ if (!mongoc_gridfs_file_set_id (file, &id, &error)) { fprintf (stderr, "%s\n", error.message); return 1; } mongoc_gridfs_file_save (file); mongoc_gridfs_file_destroy (file); } else { fprintf (stderr, "Unknown command"); return 1; } mongoc_gridfs_destroy (gridfs); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } mongoc_host_list_t Synopsis typedef struct { mongoc_host_list_t *next; char host[BSON_HOST_NAME_MAX + 1]; char host_and_port[BSON_HOST_NAME_MAX + 7]; uint16_t port; int family; void *padding[4]; } mongoc_host_list_t; Description The host and port of a MongoDB server. Can be part of a linked list: for example the return value of mongoc_uri_get_hosts when multiple hosts are provided in the MongoDB URI. See Also mongoc_uri_get_hosts and mongoc_cursor_get_host. mongoc_index_opt_geo_t Synopsis #include <mongoc.h> typedef struct { uint8_t twod_sphere_version; uint8_t twod_bits_precision; double twod_location_min; double twod_location_max; double haystack_bucket_size; uint8_t *padding[32]; } mongoc_index_opt_geo_t; Description This structure contains the options that may be used for tuning a GEO index. See Also mongoc_index_opt_t mongoc_index_opt_wt_t mongoc_index_opt_t Synopsis #include <mongoc.h> typedef struct { bool is_initialized; bool background; bool unique; const char *name; bool drop_dups; bool sparse; int32_t expire_after_seconds; int32_t v; const bson_t *weights; const char *default_language; const char *language_override; mongoc_index_opt_geo_t *geo_options; mongoc_index_opt_storage_t *storage_options; const bson_t *partial_filter_expression; const bson_t *collation; void *padding[4]; } mongoc_index_opt_t; Deprecated This structure is deprecated and should not be used in new code. See create-indexes. Description This structure contains the options that may be used for tuning a specific index. See the createIndexes documentations in the MongoDB manual for descriptions of individual options. NOTE: dropDups is deprecated as of MongoDB version 3.0.0. This option is silently ignored by the server and unique index builds using this option will fail if a duplicate value is detected. Example { bson_t keys; bson_error_t error; mongoc_index_opt_t opt; mongoc_index_opt_geo_t geo_opt; mongoc_index_opt_init (&opt); mongoc_index_opt_geo_init (&geo_opt); bson_init (&keys); BSON_APPEND_UTF8 (&keys, "location", "2d"); geo_opt.twod_location_min = -123; geo_opt.twod_location_max = +123; geo_opt.twod_bits_precision = 30; opt.geo_options = &geo_opt; collection = mongoc_client_get_collection (client, "test", "geo_test"); if (mongoc_collection_create_index (collection, &keys, &opt, &error)) { /* Successfully created the geo index */ } bson_destroy (&keys); mongoc_collection_destroy (&collection); } See Also mongoc_index_opt_geo_t mongoc_index_opt_wt_t mongoc_index_opt_wt_t Synopsis #include <mongoc.h> typedef struct { mongoc_index_opt_storage_t base; const char *config_str; void *padding[8]; } mongoc_index_opt_wt_t; Description This structure contains the options that may be used for tuning a WiredTiger specific index. See Also mongoc_index_opt_t mongoc_index_opt_geo_t mongoc_insert_flags_t Flags for insert operations Synopsis typedef enum { MONGOC_INSERT_NONE = 0, MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0, } mongoc_insert_flags_t; #define MONGOC_INSERT_NO_VALIDATE (1U << 31) Description These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They may modify how an insert happens on the MongoDB server. Flag Values ┌────────────────────────────────┬──────────────────────────────────┐ │MONGOC_INSERT_NONE │ Specify no insert flags. │ ├────────────────────────────────┼──────────────────────────────────┤ │MONGOC_INSERT_CONTINUE_ON_ERROR │ Continue inserting documents │ │ │ from the insertion set even if │ │ │ one insert fails. │ ├────────────────────────────────┼──────────────────────────────────┤ │MONGOC_INSERT_NO_VALIDATE │ Do not validate insertion │ │ │ documents before performing an │ │ │ insert. Validation can be │ │ │ expensive, so this can save some │ │ │ time if you know your documents │ │ │ are already valid. │ └────────────────────────────────┴──────────────────────────────────┘ mongoc_iovec_t Synopsis Synopsis #include <mongoc.h> #ifdef _WIN32 typedef struct { u_long iov_len; char *iov_base; } mongoc_iovec_t; #else typedef struct iovec mongoc_iovec_t; #endif The mongoc_iovec_t structure is a portability abstraction for consumers of the mongoc_stream_t interfaces. It allows for scatter/gather I/O through the socket subsystem. WARNING: When writing portable code, beware of the ordering of iov_len and iov_base as they are different on various platforms. Therefore, you should not use C initializers for initialization. mongoc_matcher_t Client-side document matching abstraction Synopsis typedef struct _mongoc_matcher_t mongoc_matcher_t; mongoc_matcher_t provides a reduced-interface for client-side matching of BSON documents. It can perform the basics such as $in, $nin, $eq, $neq, $gt, $gte, $lt, and $lte. WARNING: mongoc_matcher_t does not currently support the full spectrum of query operations that the MongoDB server supports. Deprecated WARNING: mongoc_matcher_t is deprecated and will be removed in version 2.0. Example Filter a sequence of BSON documents from STDIN based on a query.INDENT 0.0 #include <bcon.h> #include <bson.h> #include <mongoc.h> #include <stdio.h> int main (int argc, char *argv[]) { mongoc_matcher_t *matcher; bson_reader_t *reader; const bson_t *bson; bson_t *spec; char *str; int fd; mongoc_init (); #ifdef _WIN32 fd = fileno (stdin); #else fd = STDIN_FILENO; #endif reader = bson_reader_new_from_fd (fd, false); spec = BCON_NEW ("hello", "world"); matcher = mongoc_matcher_new (spec, NULL); while ((bson = bson_reader_read (reader, NULL))) { if (mongoc_matcher_match (matcher, bson)) { str = bson_as_canonical_extended_json (bson, NULL); printf ("%s\n", str); bson_free (str); } } bson_reader_destroy (reader); bson_destroy (spec); mongoc_cleanup (); return 0; } mongoc_query_flags_t Flags for query operations Synopsis typedef enum { MONGOC_QUERY_NONE = 0, MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1, MONGOC_QUERY_SLAVE_OK = 1 << 2, MONGOC_QUERY_OPLOG_REPLAY = 1 << 3, MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4, MONGOC_QUERY_AWAIT_DATA = 1 << 5, MONGOC_QUERY_EXHAUST = 1 << 6, MONGOC_QUERY_PARTIAL = 1 << 7, } mongoc_query_flags_t; Description These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They may modify how a query is performed in the MongoDB server. Flag Values ┌───────────────────────────────┬──────────────────────────────────┐ │MONGOC_QUERY_NONE │ Specify no query flags. │ ├───────────────────────────────┼──────────────────────────────────┤ │MONGOC_QUERY_TAILABLE_CURSOR │ Cursor will not be closed when │ │ │ the last data is retrieved. You │ │ │ can resume this cursor later. │ └───────────────────────────────┴──────────────────────────────────┘ │MONGOC_QUERY_SLAVE_OK │ Allow query of replica set │ │ │ secondaries. │ ├───────────────────────────────┼──────────────────────────────────┤ │MONGOC_QUERY_OPLOG_REPLAY │ Used internally by MongoDB. │ ├───────────────────────────────┼──────────────────────────────────┤ │MONGOC_QUERY_NO_CURSOR_TIMEOUT │ The server normally times out an │ │ │ idle cursor after an inactivity │ │ │ period (10 minutes). This │ │ │ prevents that. │ ├───────────────────────────────┼──────────────────────────────────┤ │MONGOC_QUERY_AWAIT_DATA │ Use with │ │ │ MONGOC_QUERY_TAILABLE_CURSOR. │ │ │ Block rather than returning no │ │ │ data. After a period, time out. │ ├───────────────────────────────┼──────────────────────────────────┤ │MONGOC_QUERY_EXHAUST │ Stream the data down full blast │ │ │ in multiple "reply" packets. │ │ │ Faster when you are pulling down │ │ │ a lot of data and you know you │ │ │ want to retrieve it all. │ ├───────────────────────────────┼──────────────────────────────────┤ │MONGOC_QUERY_PARTIAL │ Get partial results from mongos │ │ │ if some shards are down (instead │ │ │ of throwing an error). │ └───────────────────────────────┴──────────────────────────────────┘ mongoc_rand MongoDB Random Number Generator Synopsis void mongoc_rand_add (const void *buf, int num, doubel entropy); void mongoc_rand_seed (const void *buf, int num); int mongoc_rand_status (void); Description The mongoc_rand family of functions provide access to the low level randomness primitives used by the MongoDB C Driver. In particular, they control the creation of cryptographically strong pseudo-random bytes required by some security mechanisms. While we can usually pull enough entropy from the environment, you may be required to seed the PRNG manually depending on your OS, hardware and other entropy consumers running on the same system. Entropy mongoc_rand_add and mongoc_rand_seed allow the user to directly provide entropy. They differ insofar as mongoc_rand_seed requires that each bit provided is fully random. mongoc_rand_add allows the user to specify the degree of randomness in the provided bytes as well. Status The mongoc_rand_status function allows the user to check the status of the mongoc PRNG. This can be used to guarantee sufficient entropy at program startup, rather than waiting for runtime errors to occur. mongoc_read_concern_t Read Concern abstraction Synopsis New in MongoDB 3.2. The mongoc_read_concern_t allows clients to choose a level of isolation for their reads. The default, MONGOC_READ_CONCERN_LEVEL_LOCAL, is right for the great majority of applications. You can specify a read concern on connection objects, database objects, or collection objects. See readConcern on the MongoDB website for more information. Read Concern is only sent to MongoDB when it has explicitly been set by mongoc_read_concern_set_level to anything other than NULL. Read Concern Levels ┌───────────────────────────────────────┬──────────────────────────┬───────────────────────┐ │Macro │ Description │ First MongoDB version │ └───────────────────────────────────────┴──────────────────────────┴───────────────────────┘ │MONGOC_READ_CONCERN_LEVEL_LOCAL │ Level "local", the │ 3.2 │ │ │ default. │ │ ├───────────────────────────────────────┼──────────────────────────┼───────────────────────┤ │MONGOC_READ_CONCERN_LEVEL_MAJORITY │ Level "majority". │ 3.2 │ ├───────────────────────────────────────┼──────────────────────────┼───────────────────────┤ │MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE │ Level "linearizable". │ 3.4 │ └───────────────────────────────────────┴──────────────────────────┴───────────────────────┘ For the sake of compatibility with future versions of MongoDB, mongoc_read_concern_set_level allows any string, not just this list of known read concern levels. See Read Concern Levels in the MongoDB manual for more information about the individual read concern levels. mongoc_read_mode_t Read Preference Modes Synopsis typedef enum { MONGOC_READ_PRIMARY = (1 << 0), MONGOC_READ_SECONDARY = (1 << 1), MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY, MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY, MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY, } mongoc_read_mode_t; Description This enum describes how reads should be dispatched. The default is MONGOC_READ_PRIMARY. Please see the MongoDB website for a description of Read Preferences. mongoc_read_prefs_t A read preference abstraction Synopsis mongoc_read_prefs_t provides an abstraction on top of the MongoDB connection read prefences. It allows for hinting to the driver which nodes in a replica set should be accessed first. You can specify a read preference mode on connection objects, database objects, collection objects, or per-operation. Generally, it makes the most sense to stick with the global default, MONGOC_READ_PRIMARY. All of the other modes come with caveats that won't be covered in great detail here. Read Modes ┌────────────────────────────────┬──────────────────────────────────┐ │MONGOC_READ_PRIMARY │ Default mode. All operations │ │ │ read from the current replica │ │ │ set primary. │ ├────────────────────────────────┼──────────────────────────────────┤ │MONGOC_READ_SECONDARY │ All operations read from among │ │ │ the nearest secondary members of │ │ │ the replica set. │ ├────────────────────────────────┼──────────────────────────────────┤ │MONGOC_READ_PRIMARY_PREFERRED │ In most situations, operations │ │ │ read from the primary but if it │ │ │ is unavailable, operations read │ │ │ from secondary members. │ ├────────────────────────────────┼──────────────────────────────────┤ │MONGOC_READ_SECONDARY_PREFERRED │ In most situations, operations │ │ │ read from among the nearest │ │ │ secondary members, but if no │ │ │ secondaries are available, │ │ │ operations read from the │ │ │ primary. │ ├────────────────────────────────┼──────────────────────────────────┤ │MONGOC_READ_NEAREST │ Operations read from among the │ │ │ nearest members of the replica │ │ │ set, irrespective of the │ │ │ member's type. │ └────────────────────────────────┴──────────────────────────────────┘ Tag Sets Tag sets allow you to specify custom read preferences and write concerns so that your application can target operations to specific members. Custom read preferences and write concerns evaluate tags sets in different ways: read preferences consider the value of a tag when selecting a member to read from. while write concerns ignore the value of a tag to when selecting a member except to consider whether or not the value is unique. You can specify tag sets with the following read preference modes: • primaryPreferred • secondary • secondaryPreferred • nearest Tags are not compatible with MONGOC_READ_PRIMARY and, in general, only apply when selecting a secondary member of a set for a read operation. However, the nearest read mode, when combined with a tag set will select the nearest member that matches the specified tag set, which may be a primary or secondary. Tag sets are represented as a comma-separated list of colon-separated key-value pairs when provided as a connection string, e.g. dc:ny,rack:1. To specify a list of tag sets, using multiple readPreferenceTags, e.g. readPreferenceTags=dc:ny,rack:1;readPreferenceTags=dc:ny;readPreferenceTags= Note the empty value for the last one, which means match any secondary as a last resort. Order matters when using multiple readPreferenceTags. Tag Sets can also be configured using mongoc_read_prefs_set_tags. All interfaces use the same member selection logic to choose the member to which to direct read operations, basing the choice on read preference mode and tag sets. Max Staleness When connected to replica set running MongoDB 3.4 or later, the driver estimates the staleness of each secondary based on lastWriteDate values provided in server isMaster responses. Max Staleness is the maximum replication lag in seconds (wall clock time) that a secondary can suffer and still be eligible for reads. The default is MONGOC_NO_MAX_STALENESS, which disables staleness checks. Otherwise, it must be a positive integer at least MONGOC_SMALLEST_MAX_STALENESS_SECONDS (90 seconds). Max Staleness is also supported by sharded clusters of replica sets if all servers run MongoDB 3.4 or later. mongoc_remove_flags_t Flags for deletion operations Synopsis typedef enum { MONGOC_REMOVE_NONE = 0, MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0, } mongoc_remove_flags_t; Description These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They may change the number of documents that are removed during a remove command. Flag Values ┌────────────────────────────┬──────────────────────────────────┐ │MONGOC_REMOVE_NONE │ Specify no removal flags. All │ │ │ matching documents will be │ │ │ removed. │ ├────────────────────────────┼──────────────────────────────────┤ │MONGOC_REMOVE_SINGLE_REMOVE │ Only remove the first matching │ │ │ document from the selector. │ └────────────────────────────┴──────────────────────────────────┘ mongoc_reply_flags_t Flags from server replies Synopsis typedef enum { MONGOC_REPLY_NONE = 0, MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0, MONGOC_REPLY_QUERY_FAILURE = 1 << 1, MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2, MONGOC_REPLY_AWAIT_CAPABLE = 1 << 3, } mongoc_reply_flags_t; Description These flags correspond to the wire protocol. They may be bitwise or'd together. Flag Values ───────────────────────────────────────────────────────────────────── MONGOC_REPLY_NONE No flags set. ───────────────────────────────────────────────────────────────────── MONGOC_REPLY_CURSOR_NOT_FOUND No matching cursor was found on the server. ───────────────────────────────────────────────────────────────────── MONGOC_REPLY_QUERY_FAILURE The query failed or was invalid. Error document has been provided. ───────────────────────────────────────────────────────────────────── MONGOC_REPLY_SHARD_CONFIG_STALE Shard config is stale. ───────────────────────────────────────────────────────────────────── MONGOC_REPLY_AWAIT_CAPABLE If the returned cursor is capable of MONGOC_QUERY_AWAIT_DATA. ┌────────────────────────────────┬──────────────────────────────────┐ │ │ │ --
AUTHOR
MongoDB, Inc
COPYRIGHT
2018, MongoDB, Inc