.\" Man page generated from reStructuredText. . .TH "MONGOC_INDEX" "3" "May 23, 2017" "1.6.3" "MongoDB C Driver" .SH NAME mongoc_index \- MongoDB C Driver . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .sp A Cross Platform MongoDB Client Library for C .SH INTRODUCTION .sp 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. .sp It depends on \fI\%libbson\fP to generate and parse BSON documents, the native data format of MongoDB. .SS Installing the MongoDB C Driver .sp The following guide will step you through the process of downloading, building, and installing the current release of the MongoDB C Driver. .SS Supported Platforms .sp The MongoDB C Driver is \fI\%continuously tested\fP on variety of platforms including: .TS center; |l|l|l|. _ T{ Operating Systems T} T{ CPU Architectures T} T{ Compiler Toolchain T} _ T{ GNU/Linux T} T{ x86 and x86_64 T} T{ GCC 4.1 and newer T} _ T{ Solaris 11 T} T{ ARM T} T{ Clang 3.3 and newer T} _ T{ Mac OS X 10.6 and newer T} T{ PPC T} T{ Microsoft Visual Studio 2010 and newer T} _ T{ Windows Vista, 7, and 8 T} T{ SPARC T} T{ \fI\%Oracle Solaris Studio 12\fP T} _ T{ FreeBSD T} T{ T} T{ MinGW T} _ .TE .SS Install with a Package Manager .sp The libmongoc package is available on recent versions of Debian and Ubuntu. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ apt\-get install libmongoc\-1.0\-0 .ft P .fi .UNINDENT .UNINDENT .sp On Fedora, a mongo\-c\-driver package is available in the default repositories and can be installed with: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ dnf install mongo\-c\-driver .ft P .fi .UNINDENT .UNINDENT .sp On recent Red Hat systems, such as CentOS and RHEL 7, a mongo\-c\-driver package is available in the \fI\%EPEL\fP repository. To check version available, see \fI\%https://apps.fedoraproject.org/packages/mongo\-c\-driver\fP\&. The package can be installed with: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ yum install mongo\-c\-driver .ft P .fi .UNINDENT .UNINDENT .SS Building on Unix .SS Prerequisites .sp OpenSSL is required for authentication or for SSL connections to MongoDB. Kerberos or LDAP support requires Cyrus SASL. .sp To install all optional dependencies on RedHat / Fedora: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ sudo yum install pkg\-config openssl\-devel cyrus\-sasl\-devel .ft P .fi .UNINDENT .UNINDENT .sp On Debian / Ubuntu: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ sudo apt\-get install pkg\-config libssl\-dev libsasl2\-dev .ft P .fi .UNINDENT .UNINDENT .sp On FreeBSD: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ su \-c \(aqpkg install pkgconf openssl cyrus\-sasl\(aq .ft P .fi .UNINDENT .UNINDENT .SS Building from a release tarball .sp Unless you intend on contributing to the mongo\-c\-driver, you will want to build from a release tarball. .sp The most recent release of libmongoc is 1.6.3 and can be \fI\%downloaded here\fP\&. The following snippet will download and extract the driver, and configure it: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ wget \fI\%https://github.com/mongodb/mongo\-c\-driver/releases/download/1.6.3/mongo\-c\-driver\-1.6.3.tar.gz\fP $ tar xzf mongo\-c\-driver\-1.6.3\&.tar.gz $ cd mongo\-c\-driver\-1.6.3 $ ./configure \-\-disable\-automatic\-init\-and\-cleanup .ft P .fi .UNINDENT .UNINDENT .sp The \fB\-\-disable\-automatic\-init\-and\-cleanup\fP option is recommended, see init\-cleanup\&. For a list of all configure options, run \fB\&./configure \-\-help\fP\&. .sp If \fBconfigure\fP completed successfully, you\(aqll see something like the following describing your build configuration. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C libmongoc 1.6.3 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 Code coverage support : no Cross Compiling : no Fast counters : no Shared memory performance counters : yes SASL : sasl2 SSL : openssl Libbson : bundled Documentation: man : no HTML : no .ft P .fi .UNINDENT .UNINDENT .sp 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. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ make $ sudo make install .ft P .fi .UNINDENT .UNINDENT .SS Building from git .sp To build an unreleased version of the driver from git requires additional dependencies. .sp RedHat / Fedora: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ sudo yum install git gcc automake autoconf libtool .ft P .fi .UNINDENT .UNINDENT .sp Debian / Ubuntu: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ sudo apt\-get install git gcc automake autoconf libtool .ft P .fi .UNINDENT .UNINDENT .sp FreeBSD: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ su \-c \(aqpkg install git gcc automake autoconf libtool\(aq .ft P .fi .UNINDENT .UNINDENT .sp Once you have the dependencies installed, clone the repository and build the current master or a particular release tag: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ 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 .ft P .fi .UNINDENT .UNINDENT .SS Generating the documentation .sp Install \fI\%Sphinx\fP, then: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ./configure \-\-enable\-html\-docs \-\-enable\-man\-pages $ make man html .ft P .fi .UNINDENT .UNINDENT .SS Building on Mac OS X .sp Install the XCode Command Line Tools: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ xcode\-select \-\-install .ft P .fi .UNINDENT .UNINDENT .sp Some Homebrew packages are also required. First \fI\%install Homebrew according to its instructions\fP, then: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ brew install automake autoconf libtool pkgconfig .ft P .fi .UNINDENT .UNINDENT .sp Download the latest release tarball .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ curl \-LO \fI\%https://github.com/mongodb/mongo\-c\-driver/releases/download/1.6.3/mongo\-c\-driver\-1.6.3.tar.gz\fP $ tar xzf mongo\-c\-driver\-1.6.3\&.tar.gz $ cd mongo\-c\-driver\-1.6.3 .ft P .fi .UNINDENT .UNINDENT .sp Build and install the driver: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ./configure $ make $ sudo make install .ft P .fi .UNINDENT .UNINDENT .SS Native TLS Support on Mac OS X / Darwin (Secure Transport) .sp 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. .sp To compile against the Darwin native TLS and crypto libraries, even when OpenSSL is available, configure the driver like so: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ ./configure \-\-enable\-ssl=darwin .ft P .fi .UNINDENT .UNINDENT .SS OpenSSL support on El Capitan .sp 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: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ brew install openssl $ export LDFLAGS="\-L/usr/local/opt/openssl/lib" $ export CPPFLAGS="\-I/usr/local/opt/openssl/include" .ft P .fi .UNINDENT .UNINDENT .SS Building on Windows .sp Building on Windows requires Windows Vista or newer and Visual Studio 2010 or newer. Additionally, \fBcmake\fP is required to generate Visual Studio project files. .sp Let\(aqs 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. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C cd mongo\-c\-driver\-1.6.3\esrc\elibbson cmake \-G "Visual Studio 14 2015 Win64" "\-DCMAKE_INSTALL_PREFIX=C:\emongo\-c\-driver" .ft P .fi .UNINDENT .UNINDENT .sp (Run \fBcmake \-LH .\fP for a list of other options.) .sp Now that we have project files generated, we can either open the project in Visual Studio or compile from the command line. Let\(aqs build using the command line program \fBmsbuild.exe\fP .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C msbuild.exe ALL_BUILD.vcxproj .ft P .fi .UNINDENT .UNINDENT .sp Now that libbson is compiled, let\(aqs install it using msbuild. It will be installed to the path specified by \fBCMAKE_INSTALL_PREFIX\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C msbuild.exe INSTALL.vcxproj .ft P .fi .UNINDENT .UNINDENT .sp You should now see libbson installed in \fBC:\emongo\-c\-driver\fP .sp Now let\(aqs do the same for the MongoDB C driver. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C cd mongo\-c\-driver\-1.6.3 cmake \-G "Visual Studio 14 2015 Win64" \e "\-DCMAKE_INSTALL_PREFIX=C:\emongo\-c\-driver" \e "\-DBSON_ROOT_DIR=C:\emongo\-c\-driver" msbuild.exe ALL_BUILD.vcxproj msbuild.exe INSTALL.vcxproj .ft P .fi .UNINDENT .UNINDENT .sp All of the MongoDB C Driver\(aqs components will now be found in \fBC:\emongo\-c\-driver\fP\&. .SS Native TLS Support on Windows (Secure Channel) .sp 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. .sp To compile against the Windows native TLS and crypto libraries, even when OpenSSL is available, configure the driver like so: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C cmake \-G "Visual Studio 14 2015 Win64" \e "\-DENABLE_SSL=WINDOWS" \e "\-DCMAKE_INSTALL_PREFIX=C:\emongo\-c\-driver" \e "\-DBSON_ROOT_DIR=C:\emongo\-c\-driver" .ft P .fi .UNINDENT .UNINDENT .SS Tutorial .sp This guide offers a brief introduction to the MongoDB C Driver. .sp For more information on the C API, please refer to the api\&. .SS Contents .INDENT 0.0 .IP \(bu 2 \fI\%Tutorial\fP .INDENT 2.0 .IP \(bu 2 \fI\%Installing\fP .IP \(bu 2 \fI\%Starting MongoDB\fP .IP \(bu 2 \fI\%Making a Connection\fP .IP \(bu 2 \fI\%Creating BSON Documents\fP .IP \(bu 2 \fI\%Basic CRUD Operations\fP .IP \(bu 2 \fI\%Executing Commands\fP .IP \(bu 2 \fI\%Threading\fP .IP \(bu 2 \fI\%Next Steps\fP .UNINDENT .UNINDENT .SS Installing .sp For detailed instructions on installing the MongoDB C Driver on a particular platform, please see the installation guide\&. .SS Starting MongoDB .sp To run the examples in this tutorial, MongoDB must be installed and running on \fBlocalhost\fP on the default port, 27017. To check if it is up and running, connect to it with the MongoDB shell. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongo \-\-host localhost \-\-port 27017 MongoDB shell version: 3.0.6 connecting to: localhost:27017/test > .ft P .fi .UNINDENT .UNINDENT .SS Making a Connection .sp The C Driver provides a convenient way to access MongoDB \-\- regardless of cluster configuration \-\- via a \fBmongoc_client_t\fP\&. It transparently connects to standalone servers, replica sets and sharded clusters on demand. Once a connection has been made, handles to databases and collections can be obtained via the structs \fBmongoc_database_t\fP and \fBmongoc_collection_t\fP, respectively. MongoDB operations can then be performed through these handles. .sp At the start of an application, call mongoc_init() before any other libmongoc functions and call mongoc_cleanup() before exiting. When creating handles to clients, databases and servers, call the appropriate destroy functions when finished. .sp The example below establishes a connection to a standalone server on \fBlocalhost\fP, registers the client application as "connect\-example," and performs a simple command. More information about database operations can be found in the \fI\%CRUD Operations\fP and \fI\%Executing Commands\fP sections. Examples of connecting to replica sets and sharded clusters can be found on the Advanced Connections page. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_database_t *database; mongoc_collection_t *collection; bson_t *command, reply, *insert; bson_error_t error; char *str; bool retval; /* * Required to initialize libmongoc\(aqs internals */ mongoc_init (); /* * Create a new client instance */ client = mongoc_client_new ("mongodb://localhost:27017"); /* * 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\en", error.message); return EXIT_FAILURE; } str = bson_as_json (&reply, NULL); printf ("%s\en", str); insert = BCON_NEW ("hello", BCON_UTF8 ("world")); if (!mongoc_collection_insert (collection, MONGOC_INSERT_NONE, insert, NULL, &error)) { fprintf (stderr, "%s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp On a UNIX\-like system, the code can be compiled and run like so: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o connect connect.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./connect { "ok" : 1.000000 } .ft P .fi .UNINDENT .UNINDENT .sp Alternatively, if \fI\%pkg\-config\fP is not available, paths and libraries can be managed manually. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o connect connect.c \-I/usr/local/include \-lmongoc\-1.0 \-lbson\-1.0 $ ./connect { "ok" : 1.000000 } .ft P .fi .UNINDENT .UNINDENT .sp For Windows users, the code can be compiled and run with the following commands. (This assumes that the MongoDB C Driver has been installed to \fBC:\emongo\-c\-driver\fP; change the include directory as needed.) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 connect.c C:\e> connect { "ok" : 1.000000 } .ft P .fi .UNINDENT .UNINDENT .SS Creating BSON Documents .sp Documents are stored in MongoDB\(aqs data format, BSON. The C driver uses \fI\%libbson\fP to create BSON documents. There are several ways to construct them: appending key\-value pairs, using BCON, or parsing JSON. .SS Appending BSON .sp A BSON document, represented as a \fI\%bson_t\fP in code, can be constructed one field at a time using libbson\(aqs append functions. .sp For example, to create a document like this: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { 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" } ] } .ft P .fi .UNINDENT .UNINDENT .sp Use the following code: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include 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_json (document, NULL); printf ("%s\en", str); bson_free (str); /* * Clean up allocated bson documents. */ bson_destroy (document); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp See the \fI\%libbson documentation\fP for all of the types that can be appended to a \fI\%bson_t\fP\&. .SS Using BCON .sp \fIBSON C Object Notation\fP, BCON for short, is an alternative way of constructing BSON documents in a manner closer to the intended format. It has less type\-safety than BSON\(aqs append functions but results in less code. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include int main (int argc, char *argv[]) { struct tm born = { 0 }; struct tm died = { 0 }; bson_t *document; char *str; born.tm_year = 6; born.tm_mon = 11; born.tm_mday = 9; died.tm_year = 92; died.tm_mon = 0; died.tm_mday = 1; document = BCON_NEW ( "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_json (document, NULL); printf ("%s\en", str); bson_free (str); /* * Clean up allocated bson documents. */ bson_destroy (document); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp Notice that BCON can create arrays, subdocuments and arbitrary fields. .SS Creating BSON from JSON .sp For \fIsingle\fP documents, BSON can be created from JSON strings via \fI\%bson_new_from_json\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include int main (int argc, char *argv[]) { bson_error_t error; bson_t *bson; char *string; const char *json = "{\e"name\e": {\e"first\e":\e"Grace\e", \e"last\e":\e"Hopper\e"}}"; bson = bson_new_from_json ((const uint8_t *)json, \-1, &error); if (!bson) { fprintf (stderr, "%s\en", error.message); return EXIT_FAILURE; } string = bson_as_json (bson, NULL); printf ("%s\en", string); bson_free (string); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp To initialize BSON from a sequence of JSON documents, use \fI\%bson_json_reader_t\fP\&. .SS Basic CRUD Operations .sp This section demonstrates the basics of using the C Driver to interact with MongoDB. .SS Inserting a Document .sp To insert documents into a collection, first obtain a handle to a \fBmongoc_collection_t\fP via a \fBmongoc_client_t\fP\&. Then, use mongoc_collection_insert() to add BSON documents to the collection. This example inserts into the database "mydb" and collection "mycoll". .sp When finished, ensure that allocated structures are freed by using their respective destroy functions. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; bson_error_t error; bson_oid_t oid; bson_t *doc; mongoc_init (); client = mongoc_client_new ("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 (collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { fprintf (stderr, "%s\en", error.message); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o insert insert.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./insert .ft P .fi .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 insert.c C:\e> insert .ft P .fi .UNINDENT .UNINDENT .sp To verify that the insert succeeded, connect with the MongoDB shell. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.find() { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" } > .ft P .fi .UNINDENT .UNINDENT .SS Finding a Document .sp 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 \fBstdout\fP as JSON strings. .sp Use a document as a query specifier; for example, .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "color" : "red" } .ft P .fi .UNINDENT .UNINDENT .sp will match any document with a field named "color" with value "red". An empty document \fB{}\fP can be used to match all documents. .sp This first example uses an empty query specifier to find all documents in the database "mydb" and collection "mycoll". .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; const bson_t *doc; bson_t *query; char *str; mongoc_init (); client = mongoc_client_new ("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_json (doc, NULL); printf ("%s\en", str); bson_free (str); } bson_destroy (query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o find find.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./find { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } .ft P .fi .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 find.c C:\e> find { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } .ft P .fi .UNINDENT .UNINDENT .sp To look for a specific document, add a specifier to \fBquery\fP\&. This example adds a call to \fBBSON_APPEND_UTF8()\fP to look for all documents matching \fB{"hello" : "world"}\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; const bson_t *doc; bson_t *query; char *str; mongoc_init (); client = mongoc_client_new ( "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_json (doc, NULL); printf ("%s\en", str); bson_free (str); } bson_destroy (query); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o find\-specific find\-specific.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./find\-specific { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } .ft P .fi .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 find\-specific.c C:\e> find\-specific { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } .ft P .fi .UNINDENT .UNINDENT .SS Updating a Document .sp This code snippet gives an example of using mongoc_collection_update() to update the fields of a document. .sp Using the "mydb" database, the following example inserts an example document into the "mycoll" collection. Then, using its \fB_id\fP field, the document is updated with different values and a new field. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include int main (int argc, char *argv[]) { mongoc_collection_t *collection; mongoc_client_t *client; bson_error_t error; bson_oid_t oid; bson_t *doc = NULL; bson_t *update = NULL; bson_t *query = NULL; mongoc_init (); client = mongoc_client_new ("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 ( collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { fprintf (stderr, "%s\en", 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 ( collection, MONGOC_UPDATE_NONE, query, update, NULL, &error)) { fprintf (stderr, "%s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o update update.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./update .ft P .fi .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 update.c C:\e> update { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" } .ft P .fi .UNINDENT .UNINDENT .sp To verify that the update succeeded, connect with the MongoDB shell. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ 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" } > .ft P .fi .UNINDENT .UNINDENT .SS Deleting a Document .sp This example illustrates the use of mongoc_collection_remove() to delete documents. .sp The following code inserts a sample document into the database "mydb" and collection "mycoll". Then, it deletes all documents matching \fB{"hello" : "world"}\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; bson_error_t error; bson_oid_t oid; bson_t *doc; mongoc_init (); client = mongoc_client_new ("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 ( collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { fprintf (stderr, "Insert failed: %s\en", error.message); } bson_destroy (doc); doc = bson_new (); BSON_APPEND_OID (doc, "_id", &oid); if (!mongoc_collection_remove ( collection, MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) { fprintf (stderr, "Delete failed: %s\en", error.message); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o delete delete.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./delete .ft P .fi .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 delete.c C:\e> delete .ft P .fi .UNINDENT .UNINDENT .sp Use the MongoDB shell to prove that the documents have been removed successfully. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongo MongoDB shell version: 3.0.6 connecting to: test > use mydb switched to db mydb > db.mycoll.count({"hello" : "world"}) 0 > .ft P .fi .UNINDENT .UNINDENT .SS Counting Documents .sp Counting the number of documents in a MongoDB collection is similar to performing a \fI\%find operation\fP\&. This example counts the number of documents matching \fB{"hello" : "world"}\fP in the database "mydb" and collection "mycoll". .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; bson_error_t error; bson_t *doc; int64_t count; mongoc_init (); client = mongoc_client_new ("mongodb://localhost:27017/?appname=count\-example"); collection = mongoc_client_get_collection (client, "mydb", "mycoll"); doc = bson_new_from_json ( (const uint8_t *) "{\e"hello\e" : \e"world\e"}", \-1, &error); count = mongoc_collection_count ( collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); if (count < 0) { fprintf (stderr, "%s\en", error.message); } else { printf ("%" PRId64 "\en", count); } bson_destroy (doc); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-o count count.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./count 1 .ft P .fi .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 count.c C:\e> count 1 .ft P .fi .UNINDENT .UNINDENT .SS Executing Commands .sp The driver provides helper functions for executing MongoDB commands on client, database and collection structures. These functions return cursors; the \fB_simple\fP variants return booleans indicating success or failure. .sp This example executes the \fI\%collStats\fP command against the collection "mycoll" in database "mydb". .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); } else { fprintf (stderr, "Failed to run command: %s\en", error.message); } bson_destroy (command); bson_destroy (&reply); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp Compile the code and run it: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ 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 } .ft P .fi .UNINDENT .UNINDENT .sp On Windows: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C C:\e> cl.exe /IC:\emongo\-c\-driver\einclude\elibbson\-1.0 /IC:\emongo\-c\-driver\einclude\elibmongoc\-1.0 executing.c C:\e> executing { "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 } .ft P .fi .UNINDENT .UNINDENT .SS Threading .sp The MongoDB C Driver is thread\-unaware in the vast majority of its operations. This means it is up to the programmer to guarantee thread\-safety. .sp However, \fBmongoc_client_pool_t\fP is thread\-safe and is used to fetch a \fBmongoc_client_t\fP in a thread\-safe manner. After retrieving a client from the pool, the client structure should be considered owned by the calling thread. When the thread is finished, the client should be placed back into the pool. example\-pool.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* gcc example\-pool.c \-o example\-pool $(pkg\-config \-\-cflags \-\-libs * libmongoc\-1.0) */ /* ./example\-pool [CONNECTION_STRING] */ #include #include #include static pthread_mutex_t mutex; static bool in_shutdown = false; static void * worker (void *data) { mongoc_client_pool_t *pool = data; mongoc_client_t *client; bson_t ping = BSON_INITIALIZER; bson_error_t error; bool r; BSON_APPEND_INT32 (&ping, "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\en", 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: \e"%s\e".\en", 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; } .ft P .fi .UNINDENT .UNINDENT .SS Next Steps .sp To find information on advanced topics, browse the rest of the C driver guide or the \fI\%official MongoDB documentation\fP\&. .sp For help with common issues, consult the Troubleshooting page. To report a bug or request a new feature, follow these instructions\&. .SS Authentication .sp 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 \fI\%MongoDB security documentation\fP\&. .SS Basic Authentication .sp The MongoDB C driver supports challenge response authentication (sometimes known as \fBMONGODB\-CR\fP) through the use of MongoDB connection URIs. .sp Simply provide the username and password as one would with an \fBHTTP URL\fP, as well as the database to authenticate against via \fBauthSource\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb"); .ft P .fi .UNINDENT .UNINDENT .SS GSSAPI (Kerberos) Authentication .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 Kerberos support is only provided in environments supported by the \fBcyrus\-sasl\fP Kerberos implementation. This currently limits support to UNIX\-like environments. .UNINDENT .UNINDENT .sp \fBGSSAPI\fP (Kerberos) authentication is available in the Enterprise Edition of MongoDB, version 2.4 and newer. To authenticate using \fBGSSAPI\fP, the MongoDB C driver must be installed with SASL support. Run the \fBkinit\fP command before using the following authentication methods: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ kinit mongodbuser@EXAMPLE.COMmongodbuser@EXAMPLE.COM\(aqs 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 .ft P .fi .UNINDENT .UNINDENT .sp Now authenticate using the MongoDB URI. \fBGSSAPI\fP authenticates against the \fB$external\fP virtual database, so a database does not need to be specified in the URI. Note that the Kerberos principal \fImust\fP be URL\-encoded: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_client_t *client; client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@example.com/?authMechanism=GSSAPI"); .ft P .fi .UNINDENT .UNINDENT .sp The driver supports these GSSAPI properties: .INDENT 0.0 .IP \(bu 2 \fBCANONICALIZE_HOST_NAME\fP: This might be required when the hosts report different hostnames than what is used in the kerberos database. The default is "false". .IP \(bu 2 \fBSERVICE_NAME\fP: Use a different service name than the default, "mongodb". .UNINDENT .sp Set properties in the URL: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_client_t *client; client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@example.com/?authMechanism=GSSAPI&" "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true"); .ft P .fi .UNINDENT .UNINDENT .sp If you encounter errors such as \fBInvalid net address\fP, check if the application is behind a NAT (Network Address Translation) firewall. If so, create a ticket that uses \fBforwardable\fP and \fBaddressless\fP Kerberos tickets. This can be done by passing \fB\-f \-A\fP to \fBkinit\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ kinit \-f \-A mongodbuser@EXAMPLE.COM .ft P .fi .UNINDENT .UNINDENT .SS SASL Plain Authentication .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 The MongoDB C Driver must be compiled with SASL support in order to use \fBSASL PLAIN\fP authentication. .UNINDENT .UNINDENT .sp MongoDB Enterprise Edition versions 2.5.0 and newer support the \fBSASL PLAIN\fP authentication mechanism, initially intended for delegating authentication to an LDAP server. Using the \fBSASL PLAIN\fP mechanism is very similar to the challenge response mechanism with usernames and passwords. These examples use the \fB$external\fP virtual database for \fBLDAP\fP support: .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 \fBSASL PLAIN\fP is a clear\-text authentication mechanism. It is strongly recommended to connect to MongoDB using SSL with certificate validation when using the \fBPLAIN\fP mechanism. .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_client_t *client; client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN&authSource=$external"); .ft P .fi .UNINDENT .UNINDENT .SS X.509 Certificate Authentication .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 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: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongod \-\-clusterAuthMode x509 \-\-sslMode requireSSL \-\-sslPEMKeyFile server.pem \-\-sslCAFile ca.pem .ft P .fi .UNINDENT .UNINDENT .UNINDENT .UNINDENT .sp The \fBMONGODB\-X509\fP 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 and is available in MongoDB 2.5.1 and newer: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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); .ft P .fi .UNINDENT .UNINDENT .sp \fBMONGODB\-X509\fP authenticates against the \fB$external\fP database, so specifying a database is not required. For more information on the x509_derived_username, see the MongoDB server \fI\%x.509 tutorial\fP\&. .SS Basic Troubleshooting .SS Troubleshooting Checklist .sp The following is a short list of things to check when you have a problem. .INDENT 0.0 .IP \(bu 2 Did you call \fBmongoc_init()\fP in \fBmain()\fP? If not, you will likely see a segfault. .IP \(bu 2 Have you leaked any clients or cursors as can be found with \fBmongoc\-stat \fP? .IP \(bu 2 Have packets been delivered to the server? See egress bytes from \fBmongoc\-stat \fP\&. .IP \(bu 2 Does \fBvalgrind\fP show any leaks? Ensure you call \fBmongoc_cleanup()\fP at the end of your process to cleanup lingering allocations from the MongoDB C driver. .IP \(bu 2 If compiling your own copy of MongoDB C driver, consider configuring with \fB\-\-enable\-tracing\fP to enable function tracing and hex dumps of network packets to \fBSTDERR\fP and \fBSTDOUT\fP\&. .UNINDENT .SS Performance Counters .sp 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 \fBwatch \-\-interval=0.5 \-d mongoc\-stat $PID\fP to monitor an application. .sp Counters are currently available on UNIX\-like platforms that support shared memory segments. .INDENT 0.0 .IP \(bu 2 Active and Disposed Cursors .IP \(bu 2 Active and Disposed Clients, Client Pools, and Socket Streams. .IP \(bu 2 Number of operations sent and received, by type. .IP \(bu 2 Bytes transferred and received. .IP \(bu 2 Authentication successes and failures. .IP \(bu 2 Number of wire protocol errors. .UNINDENT .sp To access counters for a given process, simply provide the process id to the \fBmongoc\-stat\fP program installed with the MongoDB C Driver. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ 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 .ft P .fi .UNINDENT .UNINDENT .SS Submitting a Bug Report .sp Think you\(aqve found a bug? Want to see a new feature in the MongoDB C driver? Please open a case in our issue management tool, JIRA: .INDENT 0.0 .IP \(bu 2 \fI\%Create an account and login\fP\&. .IP \(bu 2 Navigate to \fI\%the CDRIVER project\fP\&. .IP \(bu 2 Click \fICreate Issue\fP \- Please provide as much information as possible about the issue type and how to reproduce it. .UNINDENT .sp Bug reports in JIRA for all driver projects (i.e. CDRIVER, CSHARP, JAVA) and the Core Server (i.e. SERVER) project are \fIpublic\fP\&. .SS Guides .SS Common Tasks .sp 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. .sp This snippet contains example code for the \fBexplain\fP, \fBcopydb\fP and \fBcloneCollection\fP commands. .SS Setup .sp First we\(aqll write some code to insert sample data: doc\-common\-insert.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Don\(aqt try to compile this file on its own. It\(aqs 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 (collection, true, 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\en", error.message); } mongoc_bulk_operation_destroy (bulk); return ret; } /* A helper which we\(aqll use a lot later on */ void print_res (const bson_t *reply) { BSON_ASSERT (reply); char *str = bson_as_json (reply, NULL); printf ("%s\en", str); bson_free (str); } .ft P .fi .UNINDENT .UNINDENT .SS "explain" Command .sp This is how to use the \fBexplain\fP command in MongoDB 3.2+: explain.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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\en", error.message); goto cleanup; } /* Do something with the reply */ print_res (&reply); cleanup: bson_destroy (&reply); bson_destroy (command); return res; } .ft P .fi .UNINDENT .UNINDENT .SS "copydb" Command .sp This example requires two instances of mongo to be running. .sp Here\(aqs how to use the \fBcopydb\fP command to copy a database from another instance of MongoDB: copydb.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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\en", 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; } .ft P .fi .UNINDENT .UNINDENT .SS "cloneCollection" Command .sp This example requires two instances of mongo to be running. .sp Here\(aqs an example of the \fBcloneCollection\fP command to clone a collection from another instance of MongoDB: clone\-collection.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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\en", error.message); goto cleanup; } /* Do something with the reply */ print_res (&reply); cleanup: bson_destroy (&reply); bson_destroy (command); return res; } .ft P .fi .UNINDENT .UNINDENT .SS Running the Examples common\-operations.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* * 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 #include 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]\en", argv[0]); fprintf (stderr, "MONGOD\-1\-CONNECTION\-STRING can be " "of the following forms:\en"); fprintf (stderr, "localhost\et\et\et\etlocal machine\en"); fprintf (stderr, "localhost:27018\et\et\et\etlocal machine on port 27018\en"); fprintf (stderr, "mongodb://user:pass@localhost:27017\et" "local machine on port 27017, and authenticate with username " "user and password pass\en"); 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\en", 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\en"); if (!insert_data (collection)) { res = 3; goto cleanup; } printf ("explain\en"); if (!explain (collection)) { res = 4; goto cleanup; } if (other_host_and_port) { printf ("copydb\en"); if (!copydb (client, other_host_and_port)) { res = 5; goto cleanup; } printf ("clone collection\en"); 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; } .ft P .fi .UNINDENT .UNINDENT .sp First launch two separate instances of mongod (must be done from separate shells): .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongod .ft P .fi .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mkdir /tmp/db2$ mongod \-\-dbpath /tmp/db2 \-\-port 27018 # second instance .ft P .fi .UNINDENT .UNINDENT .sp Now compile and run the example program: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ 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 } .ft P .fi .UNINDENT .UNINDENT .SS Advanced Connections .sp The following guide contains information specific to certain types of MongoDB configurations. .sp 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. .SS Connecting to a Replica Set .sp Connecting to a \fI\%replica set\fP is much like connecting to a standalone MongoDB server. Simply specify the replica set name using the \fB?replicaSet=myreplset\fP URI option. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include 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; } .ft P .fi .UNINDENT .UNINDENT .sp \fBTIP:\fP .INDENT 0.0 .INDENT 3.5 Multiple hostnames can be specified in the MongoDB connection string URI, with a comma separating hosts in the seed list. .sp It is recommended to use a seed list of members of the replica set to allow the driver to connect to any node. .UNINDENT .UNINDENT .SS Connecting to a Sharded Cluster .sp To connect to a \fI\%sharded cluster\fP, specify the \fBmongos\fP nodes the client should connect to. The C Driver will automatically detect that it has connected to a \fBmongos\fP sharding server. .sp If more than one hostname is specified, a seed list will be created to attempt failover between the \fBmongos\fP instances. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 Specifying the \fBreplicaSet\fP parameter when connecting to a \fBmongos\fP sharding server is invalid. .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include 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; } .ft P .fi .UNINDENT .UNINDENT .SS Connecting to an IPv6 Address .sp The MongoDB C Driver will automatically resolve IPv6 addresses from host names. However, to specify an IPv6 address directly, wrap the address in \fB[]\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017"); .ft P .fi .UNINDENT .UNINDENT .SS Connecting to a UNIX Domain Socket .sp 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 \fImust\fP be suffixed with \fB\&.sock\fP\&. For example, to connect to a domain socket at \fB/tmp/mongodb\-27017.sock\fP: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb\-27017.sock"); .ft P .fi .UNINDENT .UNINDENT .sp Include username and password like so: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb\-27017.sock"); .ft P .fi .UNINDENT .UNINDENT .SS Connecting to a server over SSL .sp These are instructions for configuring TLS/SSL connections. .sp To run a server locally (on port 27017, for example): .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongod \-\-port 27017 \-\-sslMode requireSSL \-\-sslPEMKeyFile server.pem \-\-sslCAFile ca.pem .ft P .fi .UNINDENT .UNINDENT .sp Add \fB/?ssl=true\fP to the end of a client URI. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_client_t *client = NULL; client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true"); .ft P .fi .UNINDENT .UNINDENT .sp MongoDB requires client certificates by default, unless the \fB\-\-sslAllowConnectionsWithoutCertificates\fP is provided. The C Driver can be configured to present a client certificate using a \fBmongoc_ssl_opt_t\fP: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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); .ft P .fi .UNINDENT .UNINDENT .sp The client certificate provided by \fBpem_file\fP must be issued by one of the server trusted Certificate Authorities listed in \fB\-\-sslCAFile\fP, or issued by a CA in the native certificate store on the server when omitted. .sp To verify the server certificate against a specific CA, provide a PEM armored file with a CA certificate, or contatinated list of CA certificates using the \fBca_file\fP option, or \fBc_rehash\fP directory structure of CAs, pointed to using the \fBca_dir\fP option. When no \fBca_file\fP or \fBca_dir\fP is provided, the driver will use CAs provided by the native platform certificate store. .sp See mongoc_ssl_opt_t for more information on the various SSL related options. .SS Additional Connection Options .sp A variety of connection options for the MongoDB URI can be found \fI\%here\fP\&. .SS Cursors .SS Handling Cursor Failures .sp Cursors exist on a MongoDB server. However, the \fBmongoc_cursor_t\fP 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. .sp While iterating cursors, you should check to see if an error has occurred. See the following example for how to robustly check for errors. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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_json (doc, NULL); printf ("%s\en", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Failed to iterate all documents: %s\en", error.message); } mongoc_cursor_destroy (cursor); } .ft P .fi .UNINDENT .UNINDENT .SS Destroying Server\-Side Cursors .sp The MongoDB C driver will automatically destroy a server\-side cursor when \fBmongoc_cursor_destroy()\fP 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. .SS Tailable Cursors .sp Tailable cursors are cursors that remain open even after they\(aqve returned a final result. This way, if more documents are added to a collection (i.e., to the cursor\(aqs result set), then you can continue to call \fBmongoc_cursor_next()\fP to retrieve those additional results. .sp Here\(aqs a complete test case that demonstrates the use of tailable cursors. .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 Tailable cursors are for capped collections only. .UNINDENT .UNINDENT .sp An example to tail the oplog from a replicaSet. mongoc\-tail.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include #ifdef _WIN32 #define sleep(_n) Sleep ((_n) *1000) #endif static void print_bson (const bson_t *b) { char *str; str = bson_as_json (b, NULL); fprintf (stdout, "%s\en", 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\en", 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\en", argv[0]); return EXIT_FAILURE; } mongoc_init (); client = mongoc_client_new (argv[1]); if (!client) { fprintf (stderr, "Invalid URI: \e"%s\e"\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp Let\(aqs compile and run this example against a replica set to see updates as they are made. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ gcc \-Wall \-o mongoc\-tail mongoc\-tail.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0)$ ./mongoc\-tail mongodb://example.com/?replicaSet=myReplSet{ "ts" : { "$timestamp" : { "t" : 1400023818, "i" : 1 } }, "h" : \-8458503739429355503, "v" : 2, "op" : "i", "ns" : "test.test", "o" : { "_id" : { "$oid" : "5372ab0a25164be923d10d50" } } } .ft P .fi .UNINDENT .UNINDENT .sp The line of output is a sample from performing \fBdb.test.insert({})\fP from the mongo shell on the given replicaSet. .sp See also \fBmongoc_cursor_set_max_await_time_ms\fP\&. .SS Bulk Write Operations .sp 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. .SS Bulk Insert .sp First we need to fetch a bulk operation handle from the \fBmongoc_collection_t\fP\&. This can be performed in either ordered or unordered mode. Unordered mode allows for greater parallelization when working with sharded clusters. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_bulk_operation_t *bulk = mongoc_collection_create_bulk_operation (collection, true, write_concern); .ft P .fi .UNINDENT .UNINDENT .sp We can now start inserting documents to the bulk operation. These will be buffered until we execute the operation. .sp The bulk operation will coalesce insertions as a single batch for each consecutive call to \fBmongoc_bulk_operation_insert()\fP\&. This creates a pipelined effect when possible. .sp \fBTIP:\fP .INDENT 0.0 .INDENT 3.5 The bulk operation API will automatically handle MongoDB servers < 2.6 by speaking the old wire protocol. However, some performance degradation may occur. .UNINDENT .UNINDENT .sp To execute the bulk operation and receive the result we call \fBmongoc_bulk_operation_execute()\fP\&. bulk1.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include 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 (collection, true, 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { fprintf (stderr, "Error: %s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp Example \fBreply\fP document: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C {"nInserted" : 10000, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "nUpserted" : 0, "writeErrors" : [] "writeConcernErrors" : [] } .ft P .fi .UNINDENT .UNINDENT .SS Mixed Bulk Write Operations .sp 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. .sp \fBTIP:\fP .INDENT 0.0 .INDENT 3.5 Though the following API will work with all versions of MongoDB, it is designed to be used with MongoDB versions >= 2.6. Much better bulk insert performance can be achieved with older versions of MongoDB through the deprecated \fBmongoc_collection_insert_bulk()\fP method. .UNINDENT .UNINDENT .SS Ordered Bulk Write Operations .sp Ordered bulk write operations are batched and sent to the server in the order provided for serial execution. The \fBreply\fP document describes the type and count of operations performed. bulk2.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include 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 (collection, true, 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} => {\(aq$inc\(aq: {\(aqj\(aq: 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { printf ("Error: %s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp Example \fBreply\fP document: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "nInserted" : 3, "nMatched" : 2, "nModified" : 2, "nRemoved" : 10000, "nUpserted" : 1, "upserted" : [{"index" : 5, "_id" : 4}], "writeErrors" : [] "writeConcernErrors" : [] } .ft P .fi .UNINDENT .UNINDENT .sp The \fBindex\fP field in the \fBupserted\fP 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. .sp \fBnModified\fP is only reported when using MongoDB 2.6 and later, otherwise the field is omitted. .SS Unordered Bulk Write Operations .sp Unordered bulk write operations are batched and sent to the server in \fIarbitrary order\fP where they may be executed in parallel. Any errors that occur are reported after all operations are attempted. .sp In the next example the first and third operations fail due to the unique constraint on \fB_id\fP\&. Since we are doing unordered execution the second and fourth operations succeed. bulk3.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include static void bulk3 (mongoc_collection_t *collection) { 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 */ bulk = mongoc_collection_create_bulk_operation (collection, false, NULL); /* 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} {\(aqi\(aq: 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { printf ("Error: %s\en", 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=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; } .ft P .fi .UNINDENT .UNINDENT .sp Example \fBreply\fP document: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "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 } .ft P .fi .UNINDENT .UNINDENT .sp The \fBbson_error_t\fP domain is \fBMONGOC_ERROR_COMMAND\fP and its code is 11000. .SS Bulk Operation Bypassing Document Validation .sp This feature is only available when using MongoDB 3.2 and later. .sp 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 .INDENT 3.5 .sp .nf .ft C #include #include #include #include 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 (collection, true, 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { printf ("Error: %s\en", 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 (collection, true, 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { printf ("Error: %s\en", 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\(aqt create collection: \(aq%s\(aq\en", error.message); } bson_free (options); mongoc_database_destroy (database); mongoc_client_destroy (client); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp Running the above example will result in: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "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" : [] } .ft P .fi .UNINDENT .UNINDENT .sp The \fBbson_error_t\fP domain is \fBMONGOC_ERROR_COMMAND\fP\&. .SS Bulk Operation Write Concerns .sp By default bulk operations are executed with the \fBwrite_concern\fP of the collection they are executed against. A custom write concern can be passed to the \fBmongoc_collection_create_bulk_operation()\fP method. Write concern errors (e.g. wtimeout) will be reported after all operations are attempted, regardless of execution order. bulk4.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include static void bulk4 (mongoc_collection_t *collection) { 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 */ bulk = mongoc_collection_create_bulk_operation (collection, true, wc); /* 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { printf ("Error: %s\en", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); mongoc_write_concern_destroy (wc); } 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; } .ft P .fi .UNINDENT .UNINDENT .sp Example \fBreply\fP document and error message: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "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 .ft P .fi .UNINDENT .UNINDENT .sp The \fBbson_error_t\fP domain is \fBMONGOC_ERROR_WRITE_CONCERN\fP 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 \fIyet\fP\&. .SS Setting Collation Order .sp This feature is only available when using MongoDB 3.4 and later. bulk\-collation.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include 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 (collection, true, 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { printf ("Error: %s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp Running the above example will result in: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "nInserted" : 2, "nMatched" : 1, "nModified" : 1, "nRemoved" : 0, "nUpserted" : 0, "writeErrors" : [ ] } .ft P .fi .UNINDENT .UNINDENT .SS Unacknowledged Bulk Writes .sp Set "w" to zero for an unacknowledged write. The driver sends unacknowledged writes using the legacy opcodes \fBOP_INSERT\fP, \fBOP_UPDATE\fP, and \fBOP_DELETE\fP\&. bulk6.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include static void bulk6 (mongoc_collection_t *collection) { 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); bulk = mongoc_collection_create_bulk_operation (collection, true, wc); 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); if (!ret) { printf ("Error: %s\en", error.message); } bson_destroy (&reply); mongoc_bulk_operation_destroy (bulk); mongoc_write_concern_destroy (wc); } 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; } .ft P .fi .UNINDENT .UNINDENT .sp The \fBreply\fP document is empty: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { } .ft P .fi .UNINDENT .UNINDENT .SS Further Reading .sp See the \fI\%Driver Bulk API Spec\fP, which describes bulk write operations for all MongoDB drivers. .SS Aggregation Framework Examples .sp This document provides a number of practical examples that display the capabilities of the aggregation framework. .sp The \fI\%Aggregations using the Zip Codes Data Set\fP examples uses a publicly available data set of all zipcodes and populations in the United States. These data are available at: \fI\%zips.json\fP\&. .SS Requirements .sp \fI\%MongoDB\fP, version 2.2.0 or later. \fI\%MongoDB C driver\fP, version 0.96.0 or later. .sp Let\(aqs check if everything is installed. .sp Use the following command to load zips.json data set into mongod instance: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongoimport \-\-drop \-d test \-c zipcodes zips.json .ft P .fi .UNINDENT .UNINDENT .sp Let\(aqs use the MongoDB shell to verify that everything was imported successfully. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongo testMongoDB 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" } .ft P .fi .UNINDENT .UNINDENT .SS Aggregations using the Zip Codes Data Set .sp Each document in this collection has the following form: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "_id" : "35004", "city" : "Acmar", "state" : "AL", "pop" : 6055, "loc" : [\-86.51557, 33.584132] } .ft P .fi .UNINDENT .UNINDENT .sp In these documents: .INDENT 0.0 .IP \(bu 2 The \fB_id\fP field holds the zipcode as a string. .IP \(bu 2 The \fBcity\fP field holds the city name. .IP \(bu 2 The \fBstate\fP field holds the two letter state abbreviation. .IP \(bu 2 The \fBpop\fP field holds the population. .IP \(bu 2 The \fBloc\fP field holds the location as a \fB[latitude, longitude]\fP array. .UNINDENT .SS States with Populations Over 10 Million .sp To get all states with a population greater than 10 million, use the following aggregation pipeline: aggregation1.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include 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_json (doc, NULL); printf ("%s\en", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp You should see a result like the following: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "_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 } .ft P .fi .UNINDENT .UNINDENT .sp The above aggregation pipeline is build from two pipeline operators: \fB$group\fP and \fB$match\fP\&. .sp The \fB$group\fP 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: \fB$addToSet\fP, \fB$first\fP, \fB$last\fP, \fB$max\fP, \fB$min\fP, \fB$avg\fP, \fB$push\fP, \fB$sum\fP\&. The \fB$match\fP pipeline operator syntax is the same as the read operation query syntax. .sp The \fB$group\fP process reads all documents and for each state it creates a separate document, for example: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "_id" : "WA", "total_pop" : 4866692 } .ft P .fi .UNINDENT .UNINDENT .sp The \fBtotal_pop\fP field uses the $sum aggregation function to sum the values of all pop fields in the source documents. .sp Documents created by \fB$group\fP are piped to the \fB$match\fP pipeline operator. It returns the documents with the value of \fBtotal_pop\fP field greater than or equal to 10 million. .SS Average City Population by State .sp To get the first three states with the greatest average population per city, use the following aggregation: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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) "}", "]"); .ft P .fi .UNINDENT .UNINDENT .sp This aggregate pipeline produces: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "_id" : "DC", "avg_city_pop" : 303450.0 } { "_id" : "FL", "avg_city_pop" : 27942.29805615551 } { "_id" : "CA", "avg_city_pop" : 27735.341099720412 } .ft P .fi .UNINDENT .UNINDENT .sp The above aggregation pipeline is build from three pipeline operators: \fB$group\fP, \fB$sort\fP and \fB$limit\fP\&. .sp The first \fB$group\fP operator creates the following documents: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 } .ft P .fi .UNINDENT .UNINDENT .sp Note, that the \fB$group\fP operator can\(aqt use nested documents except the \fB_id\fP field. .sp The second \fB$group\fP uses these documents to create the following documents: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "_id" : "FL", "avg_city_pop" : 27942.29805615551 } .ft P .fi .UNINDENT .UNINDENT .sp These documents are sorted by the \fBavg_city_pop\fP field in descending order. Finally, the \fB$limit\fP pipeline operator returns the first 3 documents from the sorted set. .SS "distinct" and "mapReduce" .sp This document provides some practical, simple, examples to demonstrate the \fBdistinct\fP and \fBmapReduce\fP commands. .SS Setup .sp First we\(aqll write some code to insert sample data: doc\-common\-insert.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Don\(aqt try to compile this file on its own. It\(aqs 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 (collection, true, 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\en", error.message); } mongoc_bulk_operation_destroy (bulk); return ret; } /* A helper which we\(aqll use a lot later on */ void print_res (const bson_t *reply) { BSON_ASSERT (reply); char *str = bson_as_json (reply, NULL); printf ("%s\en", str); bson_free (str); } .ft P .fi .UNINDENT .UNINDENT .SS "distinct" command .sp This is how to use the \fBdistinct\fP command to get the distinct values of \fBx\fP which are greater than \fB1\fP: distinct.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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\en", 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\(aqt extract \e"values\e" field from response\en"); 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\en", val); } } cleanup: /* cleanup */ bson_destroy (command); bson_destroy (&reply); return res; } .ft P .fi .UNINDENT .UNINDENT .SS "mapReduce" \- basic example .sp A simple example using the map reduce framework. It simply adds up the number of occurrences of each "tag". .sp First define the \fBmap\fP and \fBreduce\fP functions: constants.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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\(aqt just return values.length as the reduce function might be called iteratively on the results of other reduce steps. */ .ft P .fi .UNINDENT .UNINDENT .sp Run the \fBmapReduce\fP command: map\-reduce\-basic.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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\en", error.message); goto cleanup; } /* Do something with the reply (it doesn\(aqt contain the mapReduce results) */ print_res (&reply); /* Now we\(aqll 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\en", 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; } .ft P .fi .UNINDENT .UNINDENT .SS "mapReduce" \- more complicated example .sp You must have replica set running for this. .sp 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 .INDENT 3.5 .sp .nf .ft C 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\en", error.message); res = false; } mongoc_cursor_destroy (cursor); mongoc_read_prefs_destroy (read_pref); bson_destroy (command); return res; } .ft P .fi .UNINDENT .UNINDENT .SS Running the Examples .sp Here\(aqs how to run the example code basic\-aggregation.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* * 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 #include #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\en", argv[0]); fprintf (stderr, "the connection string can be of the following forms:\en"); fprintf (stderr, "localhost\et\et\et\etlocal machine\en"); fprintf (stderr, "localhost:27018\et\et\et\etlocal machine on port 27018\en"); fprintf (stderr, "mongodb://user:pass@localhost:27017\et" "local machine on port 27017, and authenticate with username " "user and password pass\en"); 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\en", 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\en"); if (!insert_data (collection)) { res = 3; goto cleanup; } printf ("distinct\en"); if (!distinct (database)) { res = 4; goto cleanup; } printf ("map reduce\en"); if (!map_reduce_basic (database)) { res = 5; goto cleanup; } printf ("more complicated map reduce\en"); 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; } .ft P .fi .UNINDENT .UNINDENT .sp If you want to try the advanced map reduce example with a secondary, start a replica set (instructions for how to do this can be found \fI\%here\fP). .sp Otherwise, just start an instance of MongoDB: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ mongod .ft P .fi .UNINDENT .UNINDENT .sp Now compile and run the example program: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C $ 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 } .ft P .fi .UNINDENT .UNINDENT .SS API Reference .SS Initialization and cleanup .SS Synopsis .sp Initialize the MongoDB C Driver by calling \fBmongoc_init\fP exactly once at the beginning of your program. It is responsible for initializing global state such as process counters, SSL, and threading primitives. .sp Call \fBmongoc_cleanup\fP 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 \fBmongoc_cleanup\fP\&. Note that \fBmongoc_init\fP does \fBnot\fP reinitialize the driver after \fBmongoc_cleanup\fP\&. .SS Deprecated feature: automatic initialization and cleanup .sp On some platforms the driver can automatically call \fBmongoc_init\fP before \fBmain\fP, and call \fBmongoc_cleanup\fP 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 \fIenabled\fP by default on platforms where it is available. .sp For portable, future\-proof code, always call \fBmongoc_init\fP and \fBmongoc_cleanup\fP yourself, and configure the driver like: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C \&./configure \-\-disable\-automatic\-init\-and\-cleanup .ft P .fi .UNINDENT .UNINDENT .sp Or with CMake: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C cmake \-DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO .ft P .fi .UNINDENT .UNINDENT .SS Logging .sp MongoDB C driver Logging Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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); .ft P .fi .UNINDENT .UNINDENT .sp The MongoDB C driver comes with an abstraction for logging that you can use in your application, or integrate with an existing logging system. .SS Macros .sp To make logging a little less painful, various helper macros are provided. See the following example. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #undef MONGOC_LOG_DOMAIN #define MONGOC_LOG_DOMAIN "my\-custom\-domain" MONGOC_WARNING ("An error occurred: %s", strerror (errno)); .ft P .fi .UNINDENT .UNINDENT .SS Custom Log Handlers .INDENT 0.0 .TP .B The default log handler prints a timestamp and the log message to \fBstdout\fP, or to \fBstderr\fP for warnings, critical messages, and errors. You can override the handler with \fBmongoc_log_set_handler()\fP\&. Your handler function is called in a mutex for thread safety. .UNINDENT .sp For example, you could register a custom handler to suppress messages at INFO level and below: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; } .ft P .fi .UNINDENT .UNINDENT .sp To restore the default handler: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_log_set_handler (mongoc_log_default_handler, NULL); .ft P .fi .UNINDENT .UNINDENT .SS Disable logging .sp To disable all logging, including warnings, critical messages and errors, provide an empty log handler: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_log_set_handler (NULL, NULL); .ft P .fi .UNINDENT .UNINDENT .SS Tracing .sp If compiling your own copy of the MongoDB C driver, consider configuring with \fB\-\-enable\-tracing\fP to enable function tracing and hex dumps of network packets to \fBSTDERR\fP and \fBSTDOUT\fP during development and debugging. .sp This is especially useful when debugging what may be going on internally in the driver. .sp Trace messages can be enabled and disabled by calling \fBmongoc_log_trace_enable()\fP and \fBmongoc_log_trace_disable()\fP .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 Compiling the driver with \fB\-\-enable\-tracing\fP will affect its performance. Disabling tracing with \fBmongoc_log_trace_disable()\fP significantly reduces the overhead, but cannot remove it completely. .UNINDENT .UNINDENT « index .SS Error Reporting .SS Description .sp Many C Driver functions report errors by returning \fBfalse\fP or \-1 and filling out a \fI\%bson_error_t\fP structure with an error domain, error code, and message. Use \fBdomain\fP to determine which subsystem generated the error, and \fBcode\fP for the specific error. \fBmessage\fP is a human\-readable error description. .sp See also: \fI\%Handling Errors in libbson\fP\&. .TS center; |l|l|l|. _ T{ Domain T} T{ Code T} T{ Description T} _ T{ \fBMONGOC_ERROR_CLIENT\fP T} T{ \fBMONGOC_ERROR_CLIENT_TOO_BIG\fP T} T{ You tried to send a message larger than the server\(aqs max message size. T} _ T{ T} T{ \fBMONGOC_ERROR_CLIENT_AUTHENTICATE\fP T} T{ Wrong credentials, or failure sending or receiving authentication messages. T} _ T{ T} T{ \fBMONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER\fP T} T{ You tried an SSL connection but the driver was not built with SSL. T} _ T{ T} T{ \fBMONGOC_ERROR_CLIENT_IN_EXHAUST\fP T} T{ You began iterating an exhaust cursor, then tried to begin another operation with the same \fBmongoc_client_t\fP\&. T} _ T{ \fBMONGOC_ERROR_STREAM\fP T} T{ \fBMONGOC_ERROR_STREAM_NAME_RESOLUTION\fP T} T{ DNS failure. T} _ T{ T} T{ \fBMONGOC_ERROR_STREAM_SOCKET\fP T} T{ Timeout communicating with server, or connection closed. T} _ T{ T} T{ \fBMONGOC_ERROR_STREAM_CONNECT\fP T} T{ Failed to connect to server. T} _ T{ \fBMONGOC_ERROR_PROTOCOL\fP T} T{ \fBMONGOC_ERROR_PROTOCOL_INVALID_REPLY\fP T} T{ Corrupt response from server. T} _ T{ T} T{ \fBMONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION\fP T} T{ The server version is too old or too new to communicate with the driver. T} _ T{ \fBMONGOC_ERROR_CURSOR\fP T} T{ \fBMONGOC_ERROR_CURSOR_INVALID_CURSOR\fP T} T{ You passed bad arguments to \fBmongoc_collection_find_with_opts\fP, or you called \fBmongoc_cursor_next\fP on a completed or failed cursor, or the cursor timed out on the server. T} _ T{ \fBMONGOC_ERROR_QUERY\fP T} T{ \fBMONGOC_ERROR_QUERY_FAILURE\fP T} T{ \fI\%Error API Version 1\fP: Server error from command or query. The server error message is in \fBmessage\fP\&. T} _ T{ \fBMONGOC_ERROR_SERVER\fP T} T{ \fBMONGOC_ERROR_QUERY_FAILURE\fP T} T{ \fI\%Error API Version 2\fP: Server error from command or query. The server error message is in \fBmessage\fP\&. T} _ T{ \fBMONGOC_ERROR_SASL\fP T} T{ A SASL error code. T} T{ \fBman sasl_errors\fP for a list of codes. T} _ T{ \fBMONGOC_ERROR_BSON\fP T} T{ \fBMONGOC_ERROR_BSON_INVALID\fP T} T{ You passed an invalid or oversized BSON document as a parameter, or called \fBmongoc_collection_create_index\fP with invalid keys, or the server reply was corrupt. T} _ T{ \fBMONGOC_ERROR_NAMESPACE\fP T} T{ \fBMONGOC_ERROR_NAMESPACE_INVALID\fP T} T{ You tried to create a collection with an invalid name. T} _ T{ \fBMONGOC_ERROR_COMMAND\fP T} T{ \fBMONGOC_ERROR_COMMAND_INVALID_ARG\fP T} T{ Many functions set this error code when passed bad parameters. Print the error message for details. T} _ T{ T} T{ \fBMONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION\fP T} T{ You tried to use a command option the server does not support. T} _ T{ T} T{ \fBMONGOC_ERROR_DUPLICATE_KEY\fP T} T{ An insert or update failed because because of a duplicate \fB_id\fP or other unique\-index violation. T} _ T{ \fBMONGOC_ERROR_COMMAND\fP T} T{ \fI\%Error code from server\fP\&. T} T{ \fI\%Error API Version 1\fP: Server error from a command. The server error message is in \fBmessage\fP\&. T} _ T{ \fBMONGOC_ERROR_SERVER\fP T} T{ \fI\%Error code from server\fP\&. T} T{ \fI\%Error API Version 2\fP: Server error from a command. The server error message is in \fBmessage\fP\&. T} _ T{ \fBMONGOC_ERROR_COLLECTION\fP T} T{ \fBMONGOC_ERROR_COLLECTION_INSERT_FAILED\fP, \fBMONGOC_ERROR_COLLECTION_UPDATE_FAILED\fP, \fBMONGOC_ERROR_COLLECTION_DELETE_FAILED\fP\&. T} T{ Invalid or empty input to \fBmongoc_collection_insert\fP, \fBmongoc_collection_insert_bulk\fP, \fBmongoc_collection_update\fP, or \fBmongoc_collection_remove\fP\&. T} _ T{ \fBMONGOC_ERROR_COLLECTION\fP T} T{ \fI\%Error code from server\fP\&. T} T{ \fI\%Error API Version 1\fP: Server error from \fBmongoc_collection_insert\fP, \fBmongoc_collection_insert_bulk\fP, \fBmongoc_collection_update\fP, or \fBmongoc_collection_remove\fP\&. T} _ T{ \fBMONGOC_ERROR_SERVER\fP T} T{ \fI\%Error code from server\fP\&. T} T{ \fI\%Error API Version 2\fP: Server error from \fBmongoc_collection_insert\fP, \fBmongoc_collection_insert_bulk\fP, \fBmongoc_collection_update\fP, or \fBmongoc_collection_remove\fP\&. T} _ T{ \fBMONGOC_ERROR_GRIDFS\fP T} T{ \fBMONGOC_ERROR_GRIDFS_CHUNK_MISSING\fP T} T{ The GridFS file is missing a document in its \fBchunks\fP collection. T} _ T{ T} T{ \fBMONGOC_ERROR_GRIDFS_INVALID_FILENAME\fP T} T{ You passed a NULL filename to \fBmongoc_gridfs_remove_by_filename\fP\&. T} _ T{ T} T{ \fBMONGOC_ERROR_GRIDFS_PROTOCOL_ERROR\fP T} T{ You called \fBmongoc_gridfs_file_set_id\fP after \fBmongoc_gridfs_file_save\fP\&. T} _ T{ \fBMONGOC_ERROR_SCRAM\fP T} T{ \fBMONGOC_ERROR_SCRAM_PROTOCOL_ERROR\fP T} T{ Failure in SCRAM\-SHA\-1 authentication. T} _ T{ \fBMONGOC_ERROR_SERVER_SELECTION\fP T} T{ \fBMONGOC_ERROR_SERVER_SELECTION_FAILURE\fP T} T{ No replica set member or mongos is available, or none matches your read preference, or you supplied an invalid \fBmongoc_read_prefs_t\fP\&. T} _ T{ \fBMONGOC_ERROR_WRITE_CONCERN\fP T} T{ \fI\%Error code from server\fP\&. T} T{ There was a write concern error or timeout from the server. T} _ .TE .SS Setting the Error API Version .sp The driver\(aqs error reporting began with a design flaw: when the error \fIdomain\fP is \fBMONGOC_ERROR_COLLECTION\fP, \fBMONGOC_ERROR_QUERY\fP, or \fBMONGOC_ERROR_COMMAND\fP, the error \fIcode\fP 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. .sp For example, if \fBmongoc_collection_update\fP sets the error\(aqs domain to \fBMONGOC_ERROR_COLLECTION\fP and its code to 24, the application cannot know whether 24 is the generic driver error code \fBMONGOC_ERROR_COLLECTION_UPDATE_FAILED\fP or the specific server error code "LockTimeout". .sp 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, \fBMONGOC_ERROR_SERVER\fP\&. In Version 2, error codes originating on the server always have error domain \fBMONGOC_ERROR_SERVER\fP or \fBMONGOC_ERROR_WRITE_CONCERN\fP\&. 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. .TS center; |l|l|l|. _ T{ Error Source T} T{ API Version 1 T} T{ API Version 2 T} _ T{ \fBmongoc_cursor_error\fP T} T{ \fBMONGOC_ERROR_QUERY\fP T} T{ \fBMONGOC_ERROR_SERVER\fP T} _ T{ \fBmongoc_client_command\fP, \fBmongoc_database_command\fP, and other command functions T} T{ \fBMONGOC_ERROR_QUERY\fP T} T{ \fBMONGOC_ERROR_SERVER\fP T} _ T{ \fBmongoc_collection_count_with_opts\fP, \fBmongoc_client_get_database_names\fP, and other command helper functions T} T{ \fBMONGOC_ERROR_QUERY\fP T} T{ \fBMONGOC_ERROR_SERVER\fP T} _ T{ \fBmongoc_collection_insert\fP \fBmongoc_collection_insert_bulk\fP \fBmongoc_collection_update\fP \fBmongoc_collection_remove\fP T} T{ \fBMONGOC_ERROR_COMMAND\fP T} T{ \fBMONGOC_ERROR_SERVER\fP T} _ T{ \fBmongoc_bulk_operation_execute\fP T} T{ \fBMONGOC_ERROR_COMMAND\fP T} T{ \fBMONGOC_ERROR_SERVER\fP T} _ T{ Write\-concern timeout T} T{ \fBMONGOC_ERROR_WRITE_CONCERN\fP T} T{ \fBMONGOC_ERROR_WRITE_CONCERN\fP T} _ .TE .sp The Error API Versions are defined with \fBMONGOC_ERROR_API_VERSION_LEGACY\fP and \fBMONGOC_ERROR_API_VERSION_2\fP\&. Set the version with \fBmongoc_client_set_error_api\fP or \fBmongoc_client_pool_set_error_api\fP\&. .SS See Also .sp \fI\%MongoDB Server Error Codes\fP .SS Version Checks .sp Conditional compilation based on mongoc version .SS Description .sp The following preprocessor macros can be used to perform various checks based on the version of the library you are compiling against. This may be useful if you only want to enable a feature on a certain version of the library. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #define MONGOC_MAJOR_VERSION (1) #define MONGOC_MINOR_VERSION (6) #define MONGOC_MICRO_VERSION (3) #define MONGOC_VERSION_S "1.6.3" #define MONGOC_VERSION_HEX ((1 << 24) | (0 << 16) | (0 << 8) | 0) #define MONGOC_CHECK_VERSION(major, minor, micro) .ft P .fi .UNINDENT .UNINDENT .sp Only compile a block on MongoDB C Driver 1.1.0 and newer. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #if MONGOC_CHECK_VERSION(1, 1, 0) static void do_something (void) { } #endif .ft P .fi .UNINDENT .UNINDENT .SS mongoc_bulk_operation_t .sp Bulk Write Operations .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t; .ft P .fi .UNINDENT .UNINDENT .sp The opaque type \fBmongoc_bulk_operation_t\fP provides an abstraction for submitting multiple write operations as a single batch. .sp After adding all of the write operations to the \fBmongoc_bulk_operation_t\fP, call \fBmongoc_bulk_operation_execute()\fP to execute the operation. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 It is only valid to call \fBmongoc_bulk_operation_execute()\fP once. The \fBmongoc_bulk_operation_t\fP must be destroyed afterwards. .UNINDENT .UNINDENT .SS See Also .sp \fBBulk Write Operations\fP .SS mongoc_client_pool_t .sp Connection pooling abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_client_pool_t mongoc_client_pool_t .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_client_pool_t\fP is the basis for multi\-threading in the MongoDB C driver. Since \fBmongoc_client_t\fP structures are not thread\-safe, this structure is used to retrieve a new \fBmongoc_client_t\fP for a given thread. This structure \fIis thread\-safe\fP\&. .SS Example example\-pool.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* gcc example\-pool.c \-o example\-pool $(pkg\-config \-\-cflags \-\-libs * libmongoc\-1.0) */ /* ./example\-pool [CONNECTION_STRING] */ #include #include #include static pthread_mutex_t mutex; static bool in_shutdown = false; static void * worker (void *data) { mongoc_client_pool_t *pool = data; mongoc_client_t *client; bson_t ping = BSON_INITIALIZER; bson_error_t error; bool r; BSON_APPEND_INT32 (&ping, "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\en", 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: \e"%s\e".\en", 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; } .ft P .fi .UNINDENT .UNINDENT .SS mongoc_client_t .sp MongoDB Connection Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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); .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_client_t\fP is an opaque type that provides access to a MongoDB node, replica\-set, or sharded\-cluster. It maintains management of underlying sockets and routing to individual nodes based on \fBmongoc_read_prefs_t\fP or \fBmongoc_write_concern_t\fP\&. .SS Streams .sp The underlying transport for a given client can be customized, wrapped or replaced by any implementation that fulfills \fBmongoc_stream_t\fP\&. A custom transport can be set with \fBmongoc_client_set_stream_initiator()\fP\&. .SS Thread Safety .sp \fBmongoc_client_t\fP is \fINOT\fP 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 \fBmongoc_client_pool_t\fP to retrieve a \fBmongoc_client_t\fP for your thread. .SS Lifecycle .sp It is an error to call \fBmongoc_client_destroy\fP on a client that has operations pending. It is required that you release \fBmongoc_collection_t\fP and \fBmongoc_database_t\fP structures before calling \fBmongoc_client_destroy\fP\&. .SS Example example\-client.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* gcc example\-client.c \-o example\-client $(pkg\-config \-\-cflags \-\-libs * libmongoc\-1.0) */ /* ./example\-client [CONNECTION_STRING [COLLECTION_NAME]] */ #include #include #include 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.\en"); 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_json (doc, NULL); fprintf (stdout, "%s\en", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .SS mongoc_collection_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include typedef struct _mongoc_collection_t mongoc_collection_t; .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_collection_t\fP provides access to a MongoDB collection. This handle is useful for actions for most CRUD operations, I.e. insert, update, delete, find, etc. .SS Read Preferences and Write Concerns .sp Read preferences and write concerns are inherited from the parent client. They can be overridden by set_* commands if so desired. .SS Lifecycle .sp It is an error to call \fBmongoc_collection_destroy()\fP on a collection that has operations pending. It is required that you release \fBmongoc_cursor_t\fP structures before calling \fBmongoc_collection_destroy()\fP\&. .SS mongoc_cursor_t .sp Client\-side cursor abtraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_cursor_t mongoc_cursor_t; .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_cursor_t\fP 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. .sp Cursors are lazy, meaning that no network traffic occurs until the first call to \fBmongoc_cursor_next()\fP\&. .sp At that point we can: .INDENT 0.0 .IP \(bu 2 Determine which host we\(aqve connected to with \fBmongoc_cursor_get_host()\fP\&. .IP \(bu 2 Retrieve more records with repeated calls to \fBmongoc_cursor_next()\fP\&. .IP \(bu 2 Clone a query to repeat execution at a later point with \fBmongoc_cursor_clone()\fP\&. .IP \(bu 2 Test for errors with \fBmongoc_cursor_error()\fP\&. .UNINDENT .SS Thread Safety .sp \fBmongoc_cursor_t\fP is \fINOT\fP thread safe. It may only be used from the thread it was created from. .SS Example Query MongoDB and iterate results.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* gcc example\-client.c \-o example\-client $(pkg\-config \-\-cflags \-\-libs * libmongoc\-1.0) */ /* ./example\-client [CONNECTION_STRING [COLLECTION_NAME]] */ #include #include #include 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.\en"); 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_json (doc, NULL); fprintf (stdout, "%s\en", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\en", 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; } .ft P .fi .UNINDENT .UNINDENT .SS mongoc_database_t .sp MongoDB Database Abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_database_t mongoc_database_t; .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_database_t\fP provides access to a MongoDB database. This handle is useful for actions a particular database object. It \fIis not\fP a container for \fBmongoc_collection_t\fP structures. .sp Read preferences and write concerns are inherited from the parent client. They can be overridden with \fBmongoc_database_set_read_prefs()\fP and \fBmongoc_database_set_write_concern()\fP\&. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 It is an error to call \fBmongoc_database_destroy()\fP on a database that has operations pending. It is required that you release \fBmongoc_cursor_t\fP structures before calling \fBmongoc_database_destroy\fP\&. .UNINDENT .UNINDENT .SS Examples .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include 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; } .ft P .fi .UNINDENT .UNINDENT .SS mongoc_delete_flags_t .sp Flags for deletion operations .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef enum { MONGOC_DELETE_NONE = 0, MONGOC_DELETE_SINGLE_REMOVE = 1 << 0, } mongoc_delete_flags_t; .ft P .fi .UNINDENT .UNINDENT .SS Deprecated .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 These flags are deprecated and should not be used in new code. .UNINDENT .UNINDENT .sp Please use \fBmongoc_remove_flags_t\fP with \fBmongoc_collection_remove()\fP instead. .SS mongoc_find_and_modify_opts_t .sp find_and_modify abstraction .SS Synopsis .sp \fBmongoc_find_and_modify_opts_t\fP is a builder interface to construct a \fI\%find_and_modify\fP command. .sp It was created to be able to accommodate new arguments to the MongoDB find_and_modify command. .sp As of MongoDB 3.2, the \fBmongoc_write_concern_t\fP specified on the \fBmongoc_collection_t\fP will be used, if any. .SS Example flags.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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\(aqt 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); } else { fprintf ( stderr, "Got error: \e"%s\e" on line %d\en", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } .ft P .fi .UNINDENT .UNINDENT bypass.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); } else { fprintf ( stderr, "Got error: \e"%s\e" on line %d\en", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } .ft P .fi .UNINDENT .UNINDENT update.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); } else { fprintf ( stderr, "Got error: \e"%s\e" on line %d\en", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } .ft P .fi .UNINDENT .UNINDENT fields.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); } else { fprintf ( stderr, "Got error: \e"%s\e" on line %d\en", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&fields); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } .ft P .fi .UNINDENT .UNINDENT sort.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); } else { fprintf ( stderr, "Got error: \e"%s\e" on line %d\en", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (update); bson_destroy (&sort); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } .ft P .fi .UNINDENT .UNINDENT opts.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; 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); /* Some future findAndModify option the driver doesn\(aqt 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_json (&reply, NULL); printf ("%s\en", str); bson_free (str); } else { fprintf ( stderr, "Got error: \e"%s\e" on line %d\en", error.message, __LINE__); } bson_destroy (&reply); bson_destroy (&extra); bson_destroy (update); bson_destroy (&query); mongoc_find_and_modify_opts_destroy (opts); } .ft P .fi .UNINDENT .UNINDENT fam.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include "flags.c" #include "bypass.c" #include "update.c" #include "fields.c" #include "opts.c" #include "sort.c" 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: \e"%s\e" on line %d\en", 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; } .ft P .fi .UNINDENT .UNINDENT .sp Outputs: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { "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 } .ft P .fi .UNINDENT .UNINDENT .SS mongoc_gridfs_file_list_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp \fBmongoc_gridfs_file_list_t\fP provides a gridfs file list abstraction. It provides iteration and basic marshalling on top of a regular \fBmongoc_collection_find_with_opts()\fP style query. In interface, it\(aqs styled after \fBmongoc_cursor_t\fP\&. .SS Example .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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); .ft P .fi .UNINDENT .UNINDENT .SS mongoc_gridfs_file_opt_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp This structure contains options that can be set on a \fBmongoc_gridfs_file_t\fP\&. It can be used by various functions when creating a new gridfs file. .SS mongoc_gridfs_file_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp This structure provides a MongoDB GridFS file abstraction. It provides several APIs. .INDENT 0.0 .IP \(bu 2 readv, writev, seek, and tell. .IP \(bu 2 General file metadata such as filename and length. .IP \(bu 2 GridFS metadata such as md5, filename, content_type, aliases, metadata, chunk_size, and upload_date. .UNINDENT .SS Thread Safety .sp This structure is NOT thread\-safe and should only be used from one thread at a time. .SS Related .INDENT 0.0 .IP \(bu 2 \fBmongoc_client_t\fP .IP \(bu 2 \fBmongoc_gridfs_t\fP .IP \(bu 2 \fBmongoc_gridfs_file_list_t\fP .IP \(bu 2 \fBmongoc_gridfs_file_opt_t\fP .UNINDENT .SS mongoc_gridfs_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include typedef struct _mongoc_gridfs_t mongoc_gridfs_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp \fBmongoc_gridfs_t\fP provides a MongoDB gridfs implementation. The system as a whole is made up of \fBgridfs\fP objects, which contain \fBgridfs_files\fP and \fBgridfs_file_lists\fP\&. Essentially, a basic file system API. .sp 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. .sp mongoc_gridfs also integrates tightly with the \fBmongoc_stream_t\fP 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. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 \fBmongoc_gridfs_t\fP does not support read preferences. In a replica set, GridFS queries are always routed to the primary. .UNINDENT .UNINDENT .SS Thread Safety .sp \fBmongoc_gridfs_t\fP is NOT thread\-safe and should only be used in the same thread as the owning \fBmongoc_client_t\fP\&. .SS Lifecycle .sp It is an error to free a \fBmongoc_gridfs_t\fP before freeing all related instances of \fBmongoc_gridfs_file_t\fP and \fBmongoc_gridfs_file_list_t\fP\&. .SS Example example\-gridfs.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include 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 ...\en", 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\en", 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.\en"); 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\en", 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\en", 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\en", 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; } .ft P .fi .UNINDENT .UNINDENT .SS mongoc_host_list_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp The host and port of a MongoDB server. Can be part of a linked list: for example the return value of \fBmongoc_uri_get_hosts\fP when multiple hosts are provided in the MongoDB URI. .SS See Also .sp \fBmongoc_uri_get_hosts\fP and \fBmongoc_cursor_get_host\fP\&. .SS mongoc_index_opt_geo_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include 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; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp This structure contains the options that may be used for tuning a GEO index. .SS See Also .sp mongoc_index_opt_t .sp mongoc_index_opt_wt_t .SS mongoc_index_opt_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include 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; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp This structure contains the options that may be used for tuning a specific index. .sp See the \fI\%createIndexes documentations\fP in the MongoDB manual for descriptions of individual options. .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 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. .UNINDENT .UNINDENT .SS Example .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C { 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); } .ft P .fi .UNINDENT .UNINDENT .SS See Also .sp mongoc_index_opt_geo_t .sp mongoc_index_opt_wt_t .SS mongoc_index_opt_wt_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include typedef struct { mongoc_index_opt_storage_t base; const char *config_str; void *padding[8]; } mongoc_index_opt_wt_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp This structure contains the options that may be used for tuning a WiredTiger specific index. .SS See Also .sp mongoc_index_opt_t .sp mongoc_index_opt_geo_t .SS mongoc_insert_flags_t .sp Flags for insert operations .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef enum { MONGOC_INSERT_NONE = 0, MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0, } mongoc_insert_flags_t; #define MONGOC_INSERT_NO_VALIDATE (1U << 31) .ft P .fi .UNINDENT .UNINDENT .SS Description .sp These flags correspond to the MongoDB wire protocol. They may be bitwise or\(aqd together. They may modify how an insert happens on the MongoDB server. .SS Flag Values .TS center; |l|l|. _ T{ MONGOC_INSERT_NONE T} T{ Specify no insert flags. T} _ T{ MONGOC_INSERT_CONTINUE_ON_ERROR T} T{ Continue inserting documents from the insertion set even if one insert fails. T} _ T{ MONGOC_INSERT_NO_VALIDATE T} T{ 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. T} _ .TE .SS mongoc_iovec_t .SS Synopsis .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #ifdef _WIN32 typedef struct { u_long iov_len; char *iov_base; } mongoc_iovec_t; #else typedef struct iovec mongoc_iovec_t; #endif .ft P .fi .UNINDENT .UNINDENT .sp The \fBmongoc_iovec_t\fP structure is a portability abstraction for consumers of the \fBmongoc_stream_t\fP interfaces. It allows for scatter/gather I/O through the socket subsystem. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 When writing portable code, beware of the ordering of \fBiov_len\fP and \fBiov_base\fP as they are different on various platforms. Therefore, you should not use C initializers for initialization. .UNINDENT .UNINDENT .SS mongoc_matcher_t .sp Client\-side document matching abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_matcher_t mongoc_matcher_t; .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_matcher_t\fP provides a reduced\-interface for client\-side matching of BSON documents. .sp It can perform the basics such as $in, $nin, $eq, $neq, $gt, $gte, $lt, and $lte. .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 \fBmongoc_matcher_t\fP does not currently support the full spectrum of query operations that the MongoDB server supports. .UNINDENT .UNINDENT .SS Deprecated .sp \fBWARNING:\fP .INDENT 0.0 .INDENT 3.5 \fBmongoc_matcher_t\fP is deprecated and will be removed in version 2.0. .UNINDENT .UNINDENT .SS Example Filter a sequence of BSON documents from STDIN based on a query.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include #include #include #include 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_json (bson, NULL); printf ("%s\en", str); bson_free (str); } } bson_reader_destroy (reader); bson_destroy (spec); mongoc_cleanup (); return 0; } .ft P .fi .UNINDENT .UNINDENT .SS mongoc_query_flags_t .sp Flags for query operations .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp These flags correspond to the MongoDB wire protocol. They may be bitwise or\(aqd together. They may modify how a query is performed in the MongoDB server. .SS Flag Values .TS center; |l|l|. _ T{ MONGOC_QUERY_NONE T} T{ Specify no query flags. T} _ T{ MONGOC_QUERY_TAILABLE_CURSOR T} T{ Cursor will not be closed when the last data is retrieved. You can resume this cursor later. T} _ T{ MONGOC_QUERY_SLAVE_OK T} T{ Allow query of replica set secondaries. T} _ T{ MONGOC_QUERY_OPLOG_REPLAY T} T{ Used internally by MongoDB. T} _ T{ MONGOC_QUERY_NO_CURSOR_TIMEOUT T} T{ The server normally times out an idle cursor after an inactivity period (10 minutes). This prevents that. T} _ T{ MONGOC_QUERY_AWAIT_DATA T} T{ Use with MONGOC_QUERY_TAILABLE_CURSOR. Block rather than returning no data. After a period, time out. T} _ T{ MONGOC_QUERY_EXHAUST T} T{ 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. T} _ T{ MONGOC_QUERY_PARTIAL T} T{ Get partial results from mongos if some shards are down (instead of throwing an error). T} _ .TE .SS mongoc_rand .sp MongoDB Random Number Generator .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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); .ft P .fi .UNINDENT .UNINDENT .SS Description .sp The \fBmongoc_rand\fP 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. .sp 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. .SS Entropy .sp \fBmongoc_rand_add\fP and \fBmongoc_rand_seed\fP allow the user to directly provide entropy. They differ insofar as \fBmongoc_rand_seed\fP requires that each bit provided is fully random. \fBmongoc_rand_add\fP allows the user to specify the degree of randomness in the provided bytes as well. .SS Status .sp The \fBmongoc_rand_status\fP 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. .SS mongoc_read_concern_t .sp Read Concern abstraction .SS Synopsis .sp New in MongoDB 3.2. .sp The \fBmongoc_read_concern_t\fP 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. .sp You can specify a read concern on connection objects, database objects, or collection objects. .sp See \fI\%readConcern\fP on the MongoDB website for more information. .sp Read Concern is only sent to MongoDB when it has explicitly been set by \fBmongoc_read_concern_set_level\fP to anything other then empty string. .SS Read Concern Levels .TS center; |l|l|. _ T{ MONGOC_READ_CONCERN_LEVEL_LOCAL T} T{ Default. Uses read concern level "local". T} _ T{ MONGOC_READ_CONCERN_LEVEL_MAJORITY T} T{ Uses read concern level "majority". T} _ T{ MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE T} T{ Uses read concern level "linearizable". T} _ .TE .sp See \fI\%Read Concern Levels\fP in the MongoDB manual for more information about the individual read concern levels. .SS mongoc_read_mode_t .sp Read Preference Modes .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp This enum describes how reads should be dispatched. The default is MONGOC_READ_PRIMARY. .sp Please see the MongoDB website for a description of \fI\%Read Preferences\fP\&. .SS mongoc_read_prefs_t .sp A read preference abstraction .SS Synopsis .sp \fBmongoc_read_prefs_t\fP 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. .sp 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, \fBMONGOC_READ_PRIMARY\fP\&. All of the other modes come with caveats that won\(aqt be covered in great detail here. .SS Read Modes .TS center; |l|l|. _ T{ MONGOC_READ_PRIMARY T} T{ Default mode. All operations read from the current replica set primary. T} _ T{ MONGOC_READ_SECONDARY T} T{ All operations read from among the nearest secondary members of the replica set. T} _ T{ MONGOC_READ_PRIMARY_PREFERRED T} T{ In most situations, operations read from the primary but if it is unavailable, operations read from secondary members. T} _ T{ MONGOC_READ_SECONDARY_PREFERRED T} T{ In most situations, operations read from among the nearest secondary members, but if no secondaries are available, operations read from the primary. T} _ T{ MONGOC_READ_NEAREST T} T{ Operations read from among the nearest members of the replica set, irrespective of the member\(aqs type. T} _ .TE .SS Tag Sets .sp Tag sets allow you to specify custom read preferences and write concerns so that your application can target operations to specific members. .sp 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. .sp You can specify tag sets with the following read preference modes: .INDENT 0.0 .IP \(bu 2 primaryPreferred .IP \(bu 2 secondary .IP \(bu 2 secondaryPreferred .IP \(bu 2 nearest .UNINDENT .sp Tags are not compatible with \fBMONGOC_READ_PRIMARY\fP 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. .sp 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. .SS Max Staleness .sp 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. .sp 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 \fBMONGOC_NO_MAX_STALENESS\fP, which disables staleness checks. Otherwise, it must be a positive integer at least \fBMONGOC_SMALLEST_MAX_STALENESS_SECONDS\fP (90 seconds). .sp Max Staleness is also supported by sharded clusters of replica sets if all servers run MongoDB 3.4 or later. .SS mongoc_remove_flags_t .sp Flags for deletion operations .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef enum { MONGOC_REMOVE_NONE = 0, MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0, } mongoc_remove_flags_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp These flags correspond to the MongoDB wire protocol. They may be bitwise or\(aqd together. They may change the number of documents that are removed during a remove command. .SS Flag Values .TS center; |l|l|. _ T{ MONGOC_REMOVE_NONE T} T{ Specify no removal flags. All matching documents will be removed. T} _ T{ MONGOC_REMOVE_SINGLE_REMOVE T} T{ Only remove the first matching document from the selector. T} _ .TE .SS mongoc_reply_flags_t .sp Flags from server replies .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C 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; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp These flags correspond to the wire protocol. They may be bitwise or\(aqd together. .SS Flag Values .TS center; |l|l|. _ T{ MONGOC_REPLY_NONE T} T{ No flags set. T} _ T{ MONGOC_REPLY_CURSOR_NOT_FOUND T} T{ No matching cursor was found on the server. T} _ T{ MONGOC_REPLY_QUERY_FAILURE T} T{ The query failed or was invalid. Error document has been provided. T} _ T{ MONGOC_REPLY_SHARD_CONFIG_STALE T} T{ Shard config is stale. T} _ T{ MONGOC_REPLY_AWAIT_CAPABLE T} T{ If the returned cursor is capable of MONGOC_QUERY_AWAIT_DATA. T} _ .TE .SS mongoc_server_description_t .sp Server description .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include typedef struct _mongoc_server_description_t mongoc_server_description_t .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_server_description_t\fP holds information about a mongod or mongos the driver is connected to. .sp See also \fBmongoc_client_get_server_descriptions()\fP\&. .SS Lifecycle .sp Clean up with \fBmongoc_server_description_destroy()\fP\&. .SS mongoc_socket_t .sp Portable socket abstraction .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #include typedef struct _mongoc_socket_t mongoc_socket_t .ft P .fi .UNINDENT .UNINDENT .SS Synopsis .sp This structure provides a socket abstraction that is friendlier for portability than BSD sockets directly. Inconsistencies between Linux, various BSDs, Solaris, and Windows are handled here. .SS mongoc_ssl_opt_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct { const char *pem_file; const char *pem_pwd; const char *ca_file; const char *ca_dir; const char *crl_file; bool weak_cert_validation; bool allow_invalid_hostname; void *padding[7]; } mongoc_ssl_opt_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp This structure is used to set the SSL options for a \fBmongoc_client_t\fP or \fBmongoc_client_pool_t\fP\&. .sp Beginning in version 1.2.0, once a pool or client has any SSL options set, all connections use SSL, even if \fBssl=true\fP is omitted from the MongoDB URI. Before, SSL options were ignored unless \fBssl=true\fP was included in the URI. .sp As of 1.4.0, the \fBmongoc_client_pool_set_ssl_opts\fP and \fBmongoc_client_set_ssl_opts\fP will not only shallow copy the struct, but will also copy the \fBconst char*\fP\&. It is therefore no longer needed to make sure the values remain valid after setting them. .SS Client Authentication .sp When MongoDB is started with SSL enabled, it will by default require the client o provide a client certificate issued by a certificate authority specified by \fB\-\-sslCAFile\fP, or an authority trusted by the native certificate store in use on the server. .sp To provide the client certificate, the user must configure the \fBpem_file\fP to point at a PEM armored certificate. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongoc_ssl_opt_t ssl_opts = {0}; ssl_opts.pem_file = "/path/to/client\-certificate.pem" /* Then set the client ssl_opts, when using a single client mongoc_client_t */ mongoc_client_pool_set_ssl_opts (pool, &ssl_opts); /* or, set the pool ssl_opts, when using a the thread safe mongoc_client_pool_t */ mongoc_client_set_ssl_opts (client, &ssl_opts); .ft P .fi .UNINDENT .UNINDENT .SS Server Certificate Verification .sp The MongoDB C Driver will automatically verify the validity of the server certificate, such as issued by configured Certificate Authority, hostname validation, and expiration. .sp To overwrite this behaviour, it is possible to disable hostname validation, and/or allow otherwise invalid certificates. This behaviour is controlled using the \fBallow_invalid_hostname\fP and \fBweak_cert_validation\fP fields. By default, both are set to \fBfalse\fP\&. It is not recommended to change these defaults as it exposes the client to \fIMan In The Middle\fP attacks (when \fBallow_invalid_hostname\fP is set) and otherwise invalid certificates when \fBweak_cert_validation\fP is set to \fBtrue\fP\&. .SS Native TLS Support on Linux (OpenSSL) .sp The MongoDB C Driver supports the dominating TLS library (OpenSSL) and crypto libraries (OpenSSL\(aqs libcrypto) on Linux and Unix platforms. .sp Support for OpenSSL 1.1 and later was added in 1.4.0. .sp When compiled against OpenSSL, the driver will attempt to load the system default certificate store, as configured by the distribution, if the \fBca_file\fP and \fBca_dir\fP are not set. .SS Native TLS Support on Windows (Secure Channel) .sp The MongoDB C Driver supports the Windows native TLS library (Secure Channel, or SChannel), and its native crypto library (Cryptography API: Next Generation, or CNG). .sp When compiled against the Windows native libraries, the \fBca_dir\fP option is not supported, and will issue an error if used. .sp Encrypted PEM files (e.g., requiring \fBpem_pwd\fP) are also not supported, and will result in error when attempting to load them. .sp When \fBca_file\fP is provided, the driver will only allow server certificates issued by the authority (or authorities) provided. When no \fBca_file\fP is provided, the driver will look up the Certificate Authority using the \fBSystem Local Machine Root\fP certificate store to confirm the provided certificate. .sp When \fBcrl_file\fP is provided, the driver will import the revocation list to the \fBSystem Local Machine Root\fP certificate store. .SS Native TLS Support on Mac OS X / Darwin (Secure Transport) .sp The MongoDB C Driver supports the Darwin (OS X, macOS, iOS, etc.) native TLS library (Secure Transport), and its native crypto library (Common Crypto, or CC). .sp When compiled against Secure Transport, the \fBca_dir\fP option is not supported, and will issue an error if used. .sp When \fBca_file\fP is provided, the driver will only allow server certificates issued by the authority (or authorities) provided. When no \fBca_file\fP is provided, the driver will use the Certificate Authorities in the currently unlocked keychains. .SS See Also .INDENT 0.0 .IP \(bu 2 mongoc_client_set_ssl_opts .IP \(bu 2 mongoc_client_pool_set_ssl_opts .UNINDENT .SS mongoc_stream_buffered_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp \fBmongoc_stream_buffered_t\fP should be considered a subclass of \fBmongoc_stream_t\fP\&. It performs buffering on an underlying stream. .SS See Also .sp mongoc_stream_buffered_new() .sp mongoc_stream_destroy() .SS mongoc_stream_file_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_stream_file_t mongoc_stream_file_t .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_stream_file_t\fP is a \fBmongoc_stream_t\fP subclass for working with standard UNIX style file\-descriptors. .SS mongoc_stream_gridfs_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_stream_gridfs_t mongoc_stream_gridfs_t .ft P .fi .UNINDENT .UNINDENT .sp The \fBmongoc_stream_gridfs_t\fP class is an implementation of \fBmongoc_stream_t\fP for files stored in GridFS. It allows for transparently streaming GridFS files from a MongoDB server. .SS mongoc_stream_socket_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_stream_socket_t\fP should be considered a subclass of \fBmongoc_stream_t\fP that works upon socket streams. .SS mongoc_stream_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_stream_t mongoc_stream_t .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_stream_t\fP provides a generic streaming IO abstraction based on a struct of pointers interface. The idea is to allow wrappers, perhaps other language drivers, to easily shim their IO system on top of \fBmongoc_stream_t\fP\&. .sp The API for the stream abstraction is currently private and non\-extensible. .SS Stream Types .sp There are a number of built in stream types that come with mongoc. The default configuration is a buffered unix stream. If SSL is in use, that in turn is wrapped in a tls stream. .SS See Also .sp mongoc_stream_buffered_t .sp mongoc_stream_file_t .sp mongoc_stream_socket_t .sp mongoc_stream_tls_t .sp mongoc_stream_gridfs_t .SS mongoc_stream_tls_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_stream_tls_t\fP is a \fBmongoc_stream_t\fP subclass for working with OpenSSL TLS streams. .SS mongoc_topology_description_t .sp Status of MongoDB Servers .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_topology_description_t mongoc_topology_description_t; .ft P .fi .UNINDENT .UNINDENT .sp \fBmongoc_topology_description_t\fP is an opaque type representing the driver\(aqs knowledge of the MongoDB server or servers it is connected to. Its API conforms to the \fI\%SDAM Monitoring Specification\fP\&. .sp Applications receive a temporary reference to a \fBmongoc_topology_description_t\fP as a parameter to an SDAM Monitoring callback. See Introduction to Application Performance Monitoring\&. .SS mongoc_update_flags_t .sp Flags for update operations .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef enum { MONGOC_UPDATE_NONE = 0, MONGOC_UPDATE_UPSERT = 1 << 0, MONGOC_UPDATE_MULTI_UPDATE = 1 << 1, } mongoc_update_flags_t; #define MONGOC_UPDATE_NO_VALIDATE (1U << 31) .ft P .fi .UNINDENT .UNINDENT .SS Description .sp These flags correspond to the MongoDB wire protocol. They may be bitwise or\(aqd together. The allow for modifying the way an update is performed in the MongoDB server. .SS Flag Values .TS center; |l|l|. _ T{ MONGOC_UPDATE_NONE T} T{ No update flags set. T} _ T{ MONGOC_UPDATE_UPSERT T} T{ If an upsert should be performed. T} _ T{ MONGOC_UPDATE_MULTI_UPDATE T} T{ If more than a single matching document should be updated. By default only the first document is updated. T} _ T{ MONGOC_UPDATE_NO_VALIDATE T} T{ Do not perform client side BSON validations when performing an update. This is useful if you already know your BSON documents are valid. T} _ .TE .SS mongoc_uri_t .SS Synopsis .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef struct _mongoc_uri_t mongoc_uri_t; .ft P .fi .UNINDENT .UNINDENT .SS Description .sp \fBmongoc_uri_t\fP provides an abstraction on top of the MongoDB connection URI format. It provides standardized parsing as well as convenience methods for extracting useful information such as replica hosts or authorization information. .sp See \fI\%Connection String URI Reference\fP on the MongoDB website for more information. .SS Format .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongodb:// <1> [username:password@] <2> host1 <3> [:port1] <4> [,host2[:port2],...[,hostN[:portN]]] <5> [/[database] <6> [?options]] <7> .ft P .fi .UNINDENT .UNINDENT .INDENT 0.0 .IP 1. 3 mongodb is the specifier of the MongoDB protocol. .IP 2. 3 An optional username and password. .IP 3. 3 The only required part of the uri. This specifies either a hostname, IP address or UNIX domain socket. .IP 4. 3 An optional port number. Defaults to :27017. .IP 5. 3 Extra optional hosts and ports. You would specify multiple hosts, for example, for connections to replica sets. .IP 6. 3 The name of the database to authenticate if the connection string includes authentication credentials. If /database is not specified and the connection string includes credentials, defaults to the \(aqadmin\(aq database. .IP 7. 3 Connection specific options. .UNINDENT .SS Replica Set Example .sp To describe a connection to a replica set named \(aqtest\(aq with the following mongod hosts: .INDENT 0.0 .IP \(bu 2 \fBdb1.example.com\fP on port \fB27017\fP .IP \(bu 2 \fBdb2.example.com\fP on port \fB2500\fP .UNINDENT .sp You would use the connection string that resembles the following. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test .ft P .fi .UNINDENT .UNINDENT .SS Connection Options .TS center; |l|l|. _ T{ ssl T} T{ {true|false}, indicating if SSL must be used. (See also \fBmongoc_client_set_ssl_opts\fP and \fBmongoc_client_pool_set_ssl_opts\fP\&.) T} _ T{ connectTimeoutMS T} T{ A timeout in milliseconds to attempt a connection before timing out. This setting applies to server discovery and monitoring connections as well as to connections for application operations. The default is 10 seconds. T} _ T{ socketTimeoutMS T} T{ The time in milliseconds to attempt to send or receive on a socket before the attempt times out. The default is 5 minutes. T} _ .TE .sp Setting any of the *TimeoutMS options above to \fB0\fP will be interpreted as "use the default value". .SS Server Discovery, Monitoring, and Selection Options .sp Clients in a \fBmongoc_client_pool_t\fP share a topology scanner that runs on a background thread. The thread wakes every \fBheartbeatFrequencyMS\fP (default 10 seconds) to scan all MongoDB servers in parallel. Whenever an application operation requires a server that is not known\-\-for example, if there is no known primary and your application attempts an insert\-\-the thread rescans all servers every half\-second. In this situation the pooled client waits up to \fBserverSelectionTimeoutMS\fP (default 30 seconds) for the thread to find a server suitable for the operation, then returns an error with domain \fBMONGOC_ERROR_SERVER_SELECTION\fP\&. .sp Technically, the total time an operation may wait while a pooled client scans the topology is controlled both by \fBserverSelectionTimeoutMS\fP and \fBconnectTimeoutMS\fP\&. The longest wait occurs if the last scan begins just at the end of the selection timeout, and a slow or down server requires the full connection timeout before the client gives up. .sp A non\-pooled client is single\-threaded. Every \fBheartbeatFrequencyMS\fP, it blocks the next application operation while it does a parallel scan. This scan takes as long as needed to check the slowest server: roughly \fBconnectTimeoutMS\fP\&. Therefore the default \fBheartbeatFrequencyMS\fP for single\-threaded clients is greater than for pooled clients: 60 seconds. .sp By default, single\-threaded (non\-pooled) clients scan only once when an operation requires a server that is not known. If you attempt an insert and there is no known primary, the client checks all servers once trying to find it, then succeeds or returns an error with domain \fBMONGOC_ERROR_SERVER_SELECTION\fP\&. But if you set \fBserverSelectionTryOnce\fP to "false", the single\-threaded client loops, checking all servers every half\-second, until \fBserverSelectionTimeoutMS\fP\&. .sp The total time an operation may wait for a single\-threaded client to scan the topology is determined by \fBconnectTimeoutMS\fP in the try\-once case, or \fBserverSelectionTimeoutMS\fP and \fBconnectTimeoutMS\fP if \fBserverSelectionTryOnce\fP is set "false". .TS center; |l|l|. _ T{ heartbeatFrequencyMS T} T{ The interval between server monitoring checks. Defaults to 10 seconds in pooled (multi\-threaded) mode, 60 seconds in non\-pooled mode (single\-threaded). T} _ T{ serverSelectionTimeoutMS T} T{ A timeout in milliseconds to block for server selection before throwing an exception. The default is 30 seconds. T} _ T{ serverSelectionTryOnce T} T{ If "true", the driver scans the topology exactly once after server selection fails, then either selects a server or returns an error. If it is false, then the driver repeatedly searches for a suitable server for up to \fBserverSelectionTimeoutMS\fP milliseconds (pausing a half second between attempts). The default for \fBserverSelectionTryOnce\fP is "false" for pooled clients, otherwise "true". .sp Pooled clients ignore serverSelectionTryOnce; they signal the thread to rescan the topology every half\-second until serverSelectionTimeoutMS expires. T} _ T{ socketCheckIntervalMS T} T{ Only applies to single threaded clients. If a socket has not been used within this time, its connection is checked with a quick "isMaster" call before it is used again. Defaults to 5 seconds. T} _ .TE .sp Setting any of the *TimeoutMS options above to \fB0\fP will be interpreted as "use the default value". .SS Connection Pool Options .sp These options govern the behavior of a \fBmongoc_client_pool_t\fP\&. They are ignored by a non\-pooled \fBmongoc_client_t\fP\&. .TS center; |l|l|. _ T{ maxPoolSize T} T{ The maximum number of clients created by a \fBmongoc_client_pool_t\fP total (both in the pool and checked out). The default value is 100. Once it is reached, \fBmongoc_client_pool_pop\fP blocks until another thread pushes a client. T} _ T{ minPoolSize T} T{ The number of clients to keep in the pool; once it is reached, \fBmongoc_client_pool_push\fP destroys clients instead of pushing them. The default value, 0, means "no minimum": a client pushed into the pool is always stored, not destroyed. T} _ T{ maxIdleTimeMS T} T{ Not implemented. T} _ T{ waitQueueMultiple T} T{ Not implemented. T} _ T{ waitQueueTimeoutMS T} T{ Not implemented. T} _ .TE .SS Write Concern Options .TS center; |l|l|l|. _ T{ w T} T{ 0 T} T{ The driver will not acknowledge write operations but will pass or handle any network and socket errors that it receives to the client. If you disable write concern but enable the getLastError command’s w option, w overrides the w option. T} _ T{ T} T{ 1 T} T{ Provides basic acknowledgment of write operations. By specifying 1, you require that a standalone mongod instance, or the primary for replica sets, acknowledge all write operations. For drivers released after the default write concern change, this is the default write concern setting. T} _ T{ T} T{ majority T} T{ For replica sets, if you specify the special majority value to w option, write operations will only return successfully after a majority of the configured replica set members have acknowledged the write operation. T} _ T{ T} T{ n T} T{ For replica sets, if you specify a number n greater than 1, operations with this write concern return only after n members of the set have acknowledged the write. If you set n to a number that is greater than the number of available set members or members that hold data, MongoDB will wait, potentially indefinitely, for these members to become available. T} _ T{ T} T{ tags T} T{ For replica sets, you can specify a tag set to require that all members of the set that have these tags configured return confirmation of the write operation. T} _ T{ wtimeoutMS T} T{ T} T{ The time in milliseconds to wait for replication to succeed, as specified in the w option, before timing out. When wtimeoutMS is 0, write operations will never time out. T} _ T{ journal T} T{ T} T{ Controls whether write operations will wait until the mongod acknowledges the write operations and commits the data to the on disk journal. T} _ T{ T} T{ true T} T{ Enables journal commit acknowledgment write concern. Equivalent to specifying the getLastError command with the j option enabled. T} _ T{ T} T{ false T} T{ Does not require that mongod commit write operations to the journal before acknowledging the write operation. This is the default option for the journal parameter. T} _ .TE .SS Read Concern Options .TS center; |l|l|. _ T{ readConcernLevel T} T{ The level of isolation for read operations. If the level is left unspecified, the server default will be used. See \fI\%readConcern in the MongoDB Manual\fP for details. T} _ .TE .SS Read Preference Options .sp When connected to a replica set, the driver chooses which member to query using the read preference: .INDENT 0.0 .IP 1. 3 Choose members whose type matches "readPreference". .IP 2. 3 From these, if there are any tags sets configured, choose members matching the first tag set. If there are none, fall back to the next tag set and so on, until some members are chosen or the tag sets are exhausted. .IP 3. 3 From the chosen servers, distribute queries randomly among the server with the fastest round\-trip times. These include the server with the fastest time and any whose round\-trip time is no more than "localThresholdMS" slower. .UNINDENT .TS center; |l|l|. _ T{ readPreference T} T{ Specifies the replica set read preference for this connection. This setting overrides any slaveOk value. The read preference values are the following: .INDENT 0.0 .IP \(bu 2 primary (default) .IP \(bu 2 primaryPreferred .IP \(bu 2 secondary .IP \(bu 2 secondaryPreferred .IP \(bu 2 nearest .UNINDENT T} _ T{ readPreferenceTags T} T{ Specifies a tag set as a comma\-separated list of colon\-separated key\-value pairs. .sp Cannot be combined with preference "primary". T} _ T{ localThresholdMS T} T{ How far to distribute queries, beyond the server with the fastest round\-trip time. By default, only servers within 15ms of the fastest round\-trip time receive queries. T} _ .TE .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 "localThresholdMS" is ignored when talking to replica sets through a mongos. The equivalent is \fI\%mongos\(aqs localThreshold command line option\fP\&. .UNINDENT .UNINDENT .SS mongoc_write_concern_t .sp Write Concern abstraction .SS Synopsis .sp \fBmongoc_write_concern_t\fP tells the driver what level of acknowledgment to await from the server. The default, MONGOC_WRITE_CONCERN_W_DEFAULT, is right for the great majority of applications. .sp You can specify a write concern on connection objects, database objects, collection objects, or per\-operation. Data\-modifying operations typically use the write concern of the object they operate on, and check the server response for a write concern error or write concern timeout. For example, \fBmongoc_collection_drop_index\fP uses the collection\(aqs write concern, and a write concern error or timeout in the response is considered a failure. .sp Exceptions to this principle are the generic command functions: .INDENT 0.0 .IP \(bu 2 \fBmongoc_client_command\fP .IP \(bu 2 \fBmongoc_client_command_simple\fP .IP \(bu 2 \fBmongoc_database_command\fP .IP \(bu 2 \fBmongoc_database_command_simple\fP .IP \(bu 2 \fBmongoc_collection_command\fP .IP \(bu 2 \fBmongoc_collection_command_simple\fP .UNINDENT .sp These generic command functions do not automatically apply a write concern, and they do not check the server response for a write concern error or write concern timeout. .sp See \fI\%Write Concern\fP on the MongoDB website for more information. .SS Write Concern Levels .sp Set the write concern level with \fBmongoc_write_concern_set_w\fP\&. .TS center; |l|l|. _ T{ MONGOC_WRITE_CONCERN_W_DEFAULT (1) T} T{ By default, writes block awaiting acknowledgment from MongoDB. Acknowledged write concern allows clients to catch network, duplicate key, and other errors. T} _ T{ MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (0) T} T{ With this write concern, MongoDB does not acknowledge the receipt of write operation. Unacknowledged is similar to errors ignored; however, mongoc attempts to receive and handle network errors when possible. T} _ T{ MONGOC_WRITE_CONCERN_W_MAJORITY (majority) T} T{ Block until a write has been propagated to a majority of the nodes in the replica set. T} _ T{ n T} T{ Block until a write has been propagated to at least \fBn\fP nodes in the replica set. T} _ .TE .SS Deprecations .sp The write concern \fBMONGOC_WRITE_CONCERN_W_ERRORS_IGNORED\fP (value \-1) is a deprecated synonym for \fBMONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED\fP (value 0), and will be removed in the next major release. .sp \fBmongoc_write_concern_set_fsync\fP is deprecated. .SS Application Performance Monitoring (APM) .sp The MongoDB C Driver allows you to monitor all the MongoDB operations the driver executes. This event\-notification system conforms to two MongoDB driver specs: .INDENT 0.0 .IP \(bu 2 \fI\%Command Monitoring\fP: events related to all application operations. .IP \(bu 2 \fI\%SDAM Monitoring\fP: events related to the driver\(aqs Server Discovery And Monitoring logic. .UNINDENT .sp To receive notifications, create a \fBmongoc_apm_callbacks_t\fP with \fBmongoc_apm_callbacks_new\fP, set callbacks on it, then pass it to \fBmongoc_client_set_apm_callbacks\fP or \fBmongoc_client_pool_set_apm_callbacks\fP\&. .SS Command\-Monitoring Example example\-command\-monitoring.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* gcc example\-command\-monitoring.c \-o example\-command\-monitoring \e * $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) */ /* ./example\-command\-monitoring [CONNECTION_STRING] */ #include #include typedef struct { int started; int succeeded; int failed; } stats_t; void command_started (const mongoc_apm_command_started_t *event) { char *s; s = bson_as_json (mongoc_apm_command_started_get_command (event), NULL); printf ("Command %s started on %s:\en%s\en\en", mongoc_apm_command_started_get_command_name (event), mongoc_apm_command_started_get_host (event)\->host, s); ((stats_t *) mongoc_apm_command_started_get_context (event))\->started++; bson_free (s); } void command_succeeded (const mongoc_apm_command_succeeded_t *event) { char *s; s = bson_as_json (mongoc_apm_command_succeeded_get_reply (event), NULL); printf ("Command %s succeeded:\en%s\en\en", mongoc_apm_command_succeeded_get_command_name (event), s); ((stats_t *) mongoc_apm_command_succeeded_get_context (event))\->succeeded++; bson_free (s); } void command_failed (const mongoc_apm_command_failed_t *event) { bson_error_t error; mongoc_apm_command_failed_get_error (event, &error); printf ("Command %s failed:\en\e"%s\e"\en\en", mongoc_apm_command_failed_get_command_name (event), error.message); ((stats_t *) mongoc_apm_command_failed_get_context (event))\->failed++; } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_apm_callbacks_t *callbacks; stats_t stats = {0}; mongoc_collection_t *collection; const char *uristr = "mongodb://127.0.0.1/?appname=cmd\-monitoring\-example"; const char *collection_name = "test"; bson_t doc; mongoc_init (); if (argc > 1) { uristr = argv[1]; } client = mongoc_client_new (uristr); if (!client) { fprintf (stderr, "Failed to parse URI.\en"); return EXIT_FAILURE; } mongoc_client_set_error_api (client, 2); callbacks = mongoc_apm_callbacks_new (); mongoc_apm_set_command_started_cb (callbacks, command_started); mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded); mongoc_apm_set_command_failed_cb (callbacks, command_failed); mongoc_client_set_apm_callbacks ( client, callbacks, (void *) &stats /* context pointer */); bson_init (&doc); BSON_APPEND_INT32 (&doc, "_id", 1); collection = mongoc_client_get_collection (client, "test", collection_name); mongoc_collection_drop (collection, NULL); mongoc_collection_insert (collection, MONGOC_INSERT_NONE, &doc, NULL, NULL); /* duplicate key error on the second insert */ mongoc_collection_insert (collection, MONGOC_INSERT_NONE, &doc, NULL, NULL); printf ("started: %d\ensucceeded: %d\enfailed: %d\en", stats.started, stats.succeeded, stats.failed); bson_destroy (&doc); mongoc_collection_destroy (collection); mongoc_apm_callbacks_destroy (callbacks); mongoc_client_destroy (client); mongoc_cleanup (); return EXIT_SUCCESS; } .ft P .fi .UNINDENT .UNINDENT .sp This example program prints: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C Command drop started on 127.0.0.1: { "drop" : "test" } Command drop failed: "ns not found" Command insert started on 127.0.0.1: { "insert" : "test", "documents" : [ { "_id" : 1 } ] } Command insert succeeded: { "ok" : 1, "n" : 1 } Command insert started on 127.0.0.1: { "insert" : "test", "documents" : [ { "_id" : 1 } ] } Command insert succeeded: { "ok" : 1, "n" : 0, "writeErrors" : [ { "index" : 0, "code" : 11000, "errmsg" : "E11000 duplicate key error" } ] } started: 3 succeeded: 2 failed: 1 .ft P .fi .UNINDENT .UNINDENT .sp In older versions of the MongoDB wire protocol, queries and write operations are sent to the server with special \fI\%opcodes\fP, not as commands. To provide consistent event notifications with any MongoDB version, these legacy opcodes are reported as if they had used modern commands. .sp The final "insert" command is considered successful, despite the writeError, because the server replied to the overall command with \fB"ok": 1\fP\&. .SS SDAM Monitoring Example example\-sdam\-monitoring.c.INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* gcc example\-sdam\-monitoring.c \-o example\-sdam\-monitoring \e * $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) */ /* ./example\-sdam\-monitoring [CONNECTION_STRING] */ #include #include typedef struct { int server_changed_events; int server_opening_events; int server_closed_events; int topology_changed_events; int topology_opening_events; int topology_closed_events; int heartbeat_started_events; int heartbeat_succeeded_events; int heartbeat_failed_events; } stats_t; static void server_changed (const mongoc_apm_server_changed_t *event) { stats_t *context; const mongoc_server_description_t *prev_sd, *new_sd; context = (stats_t *) mongoc_apm_server_changed_get_context (event); context\->server_changed_events++; prev_sd = mongoc_apm_server_changed_get_previous_description (event); new_sd = mongoc_apm_server_changed_get_new_description (event); printf ("server changed: %s %s \-> %s\en", mongoc_apm_server_changed_get_host (event)\->host_and_port, mongoc_server_description_type (prev_sd), mongoc_server_description_type (new_sd)); } static void server_opening (const mongoc_apm_server_opening_t *event) { stats_t *context; context = (stats_t *) mongoc_apm_server_opening_get_context (event); context\->server_opening_events++; printf ("server opening: %s\en", mongoc_apm_server_opening_get_host (event)\->host_and_port); } static void server_closed (const mongoc_apm_server_closed_t *event) { stats_t *context; context = (stats_t *) mongoc_apm_server_closed_get_context (event); context\->server_closed_events++; printf ("server closed: %s\en", mongoc_apm_server_closed_get_host (event)\->host_and_port); } static void topology_changed (const mongoc_apm_topology_changed_t *event) { stats_t *context; const mongoc_topology_description_t *prev_td; const mongoc_topology_description_t *new_td; mongoc_server_description_t **prev_sds; size_t n_prev_sds; mongoc_server_description_t **new_sds; size_t n_new_sds; size_t i; context = (stats_t *) mongoc_apm_topology_changed_get_context (event); context\->topology_changed_events++; prev_td = mongoc_apm_topology_changed_get_previous_description (event); prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds); new_td = mongoc_apm_topology_changed_get_new_description (event); new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds); printf ("topology changed: %s \-> %s\en", mongoc_topology_description_type (prev_td), mongoc_topology_description_type (new_td)); if (n_prev_sds) { printf (" previous servers:\en"); for (i = 0; i < n_prev_sds; i++) { printf (" %s %s\en", mongoc_server_description_type (prev_sds[i]), mongoc_server_description_host (prev_sds[i])\->host_and_port); } } if (n_new_sds) { printf (" new servers:\en"); for (i = 0; i < n_new_sds; i++) { printf (" %s %s\en", mongoc_server_description_type (new_sds[i]), mongoc_server_description_host (new_sds[i])\->host_and_port); } } mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds); mongoc_server_descriptions_destroy_all (new_sds, n_new_sds); } static void topology_opening (const mongoc_apm_topology_opening_t *event) { stats_t *context; context = (stats_t *) mongoc_apm_topology_opening_get_context (event); context\->topology_opening_events++; printf ("topology opening\en"); } static void topology_closed (const mongoc_apm_topology_closed_t *event) { stats_t *context; context = (stats_t *) mongoc_apm_topology_closed_get_context (event); context\->topology_closed_events++; printf ("topology closed\en"); } static void server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event) { stats_t *context; context = (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event); context\->heartbeat_started_events++; printf ("%s heartbeat started\en", mongoc_apm_server_heartbeat_started_get_host (event)\->host_and_port); } static void server_heartbeat_succeeded ( const mongoc_apm_server_heartbeat_succeeded_t *event) { stats_t *context; char *reply; context = (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event); context\->heartbeat_succeeded_events++; reply = bson_as_json ( mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL); printf ( "%s heartbeat succeeded: %s\en", mongoc_apm_server_heartbeat_succeeded_get_host (event)\->host_and_port, reply); bson_free (reply); } static void server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event) { stats_t *context; bson_error_t error; context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event); context\->heartbeat_failed_events++; mongoc_apm_server_heartbeat_failed_get_error (event, &error); printf ("%s heartbeat failed: %s\en", mongoc_apm_server_heartbeat_failed_get_host (event)\->host_and_port, error.message); } int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_apm_callbacks_t *cbs; stats_t stats = {0}; const char *uristr = "mongodb://127.0.0.1/?appname=sdam\-monitoring\-example"; bson_t cmd = BSON_INITIALIZER; bson_t reply; bson_error_t error; mongoc_init (); if (argc > 1) { uristr = argv[1]; } client = mongoc_client_new (uristr); if (!client) { fprintf (stderr, "Failed to parse URI.\en"); return EXIT_FAILURE; } mongoc_client_set_error_api (client, 2); cbs = mongoc_apm_callbacks_new (); mongoc_apm_set_server_changed_cb (cbs, server_changed); mongoc_apm_set_server_opening_cb (cbs, server_opening); mongoc_apm_set_server_closed_cb (cbs, server_closed); mongoc_apm_set_topology_changed_cb (cbs, topology_changed); mongoc_apm_set_topology_opening_cb (cbs, topology_opening); mongoc_apm_set_topology_closed_cb (cbs, topology_closed); mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started); mongoc_apm_set_server_heartbeat_succeeded_cb (cbs, server_heartbeat_succeeded); mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed); mongoc_client_set_apm_callbacks ( client, cbs, (void *) &stats /* context pointer */); /* the driver connects on demand to perform first operation */ BSON_APPEND_INT32 (&cmd, "buildinfo", 1); mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error); mongoc_client_destroy (client); printf ("Events:\en" " server changed: %d\en" " server opening: %d\en" " server closed: %d\en" " topology changed: %d\en" " topology opening: %d\en" " topology closed: %d\en" " heartbeat started: %d\en" " heartbeat succeeded: %d\en" " heartbeat failed: %d\en", stats.server_changed_events, stats.server_opening_events, stats.server_closed_events, stats.topology_changed_events, stats.topology_opening_events, stats.topology_closed_events, stats.heartbeat_started_events, stats.heartbeat_succeeded_events, stats.heartbeat_failed_events); bson_destroy (&cmd); bson_destroy (&reply); mongoc_apm_callbacks_destroy (cbs); mongoc_cleanup (); return EXIT_SUCCESS; } .ft P .fi .UNINDENT .UNINDENT .sp Start a 3\-node replica set on localhost with set name "rs" and start the program: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C \&./example\-sdam\-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs" .ft P .fi .UNINDENT .UNINDENT .sp This example program prints something like: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C topology opening topology changed: Unknown \-> ReplicaSetNoPrimary server opening: localhost:27017 server opening: localhost:27018 localhost:27017 heartbeat started localhost:27018 heartbeat started localhost:27017 heartbeat succeeded: { ... reply ... } server changed: localhost:27017 Unknown \-> RSPrimary server opening: localhost:27019 topology changed: ReplicaSetNoPrimary \-> ReplicaSetWithPrimary new servers: RSPrimary localhost:27017 localhost:27019 heartbeat started localhost:27018 heartbeat succeeded: { ... reply ... } server changed: localhost:27018 Unknown \-> RSSecondary topology changed: ReplicaSetWithPrimary \-> ReplicaSetWithPrimary previous servers: RSPrimary localhost:27017 new servers: RSPrimary localhost:27017 RSSecondary localhost:27018 localhost:27019 heartbeat succeeded: { ... reply ... } server changed: localhost:27019 Unknown \-> RSSecondary topology changed: ReplicaSetWithPrimary \-> ReplicaSetWithPrimary previous servers: RSPrimary localhost:27017 RSSecondary localhost:27018 new servers: RSPrimary localhost:27017 RSSecondary localhost:27018 RSSecondary localhost:27019 topology closed Events: server changed: 3 server opening: 3 server closed: 0 topology changed: 4 topology opening: 1 topology closed: 1 heartbeat started: 3 heartbeat succeeded: 3 heartbeat failed: 0 .ft P .fi .UNINDENT .UNINDENT .sp The driver discovers the third member, "localhost:27019", and adds it to the topology. .SH AUTHOR MongoDB, Inc .SH COPYRIGHT 2017, MongoDB, Inc .\" Generated by docutils manpage writer. .