Provided by: libmongoc-doc_1.9.2+dfsg-1build1_all bug

NAME

       mongoc_reference - Index

MONGODB C DRIVER

       A Cross Platform MongoDB Client Library for C

   Introduction
       The  MongoDB C Driver, also known as "libmongoc", is a library for using MongoDB from C applications, and
       for writing MongoDB drivers in higher-level languages.

       It depends on libbson to generate and parse BSON documents, the native data format of MongoDB.

   Installing the MongoDB C Driver
       The following guide will step you through the  process  of  downloading,  building,  and  installing  the
       current release of the MongoDB C Driver.

   Supported Platforms
       The MongoDB C Driver is continuously tested on variety of platforms including:

       • Archlinux

       • Debian 8.1

       • macOS 10.10

       • Microsoft Windows Server 2008

       • RHEL 7.0, 7.1, 7.2

       • SUSE 12

       • Ubuntu 12.04, 14.04, 16.04

       • Clang 3.4, 3.5, 3.7, 3.8

       • GCC 4.6, 4.8, 4.9, 5.3

       • MinGW-W64

       • Visual Studio 2010, 2013, 2015

       • x86, x86_64, ARM (aarch64), Power8 (ppc64le), zSeries (s390x)

   Install with a Package Manager
       The libmongoc package is available on recent versions of Debian and Ubuntu.

          $ apt-get install libmongoc-1.0-0

       On Fedora, a mongo-c-driver package is available in the default repositories and can be installed with:

          $ dnf install mongo-c-driver

       On  recent  Red Hat systems, such as CentOS and RHEL 7, a mongo-c-driver package is available in the EPEL
       repository. To check version available, see  https://apps.fedoraproject.org/packages/mongo-c-driver.  The
       package can be installed with:

          $ yum install mongo-c-driver

   Building on Unix
   Prerequisites
       OpenSSL  is  required  for  authentication  or  for  SSL connections to MongoDB. Kerberos or LDAP support
       requires Cyrus SASL.

       To install all optional dependencies on RedHat / Fedora:

          $ sudo yum install pkg-config openssl-devel cyrus-sasl-devel

       On Debian / Ubuntu:

          $ sudo apt-get install pkg-config libssl-dev libsasl2-dev

       On FreeBSD:

          $ su -c 'pkg install pkgconf openssl cyrus-sasl'

   Building from a release tarball
       Unless you intend on contributing to the mongo-c-driver, you will want to build from a release tarball.

       The most recent release of libmongoc is 1.9.2 and can be downloaded  here.  The  following  snippet  will
       download and extract the driver, and configure it:

          $ wget https://github.com/mongodb/mongo-c-driver/releases/download/1.9.2/mongo-c-driver-1.9.2.tar.gz
          $ tar xzf mongo-c-driver-1.9.2.tar.gz
          $ cd mongo-c-driver-1.9.2
          $ ./configure --disable-automatic-init-and-cleanup

       The  --disable-automatic-init-and-cleanup  option  is  recommended,  see  init-cleanup. For a list of all
       configure options, run ./configure --help.

       If configure completed successfully, you'll see  something  like  the  following  describing  your  build
       configuration.

          libmongoc 1.9.2 was configured with the following options:

          Build configuration:
            Enable debugging (slow)                          : no
            Compile with debug symbols (slow)                : no
            Enable GCC build optimization                    : yes
            Enable automatic init and cleanup                : no
            Enable maintainer flags                          : no
            Code coverage support                            : no
            Cross Compiling                                  : no
            Fast counters                                    : no
            Shared memory performance counters               : yes
            SASL                                             : sasl2
            SSL                                              : openssl
            Snappy Compression                               : no
            Zlib Compression                                 : bundled
            Libbson                                          : bundled

          Documentation:
            man                                              : no
            HTML                                             : no

       mongo-c-driver  contains  a copy of libbson, in case your system does not already have libbson installed.
       The configure script will detect if libbson is not installed and use the bundled libbson.

          $ make
          $ sudo make install

   Building from git
       To build an unreleased version of the driver from git requires additional dependencies.

       RedHat / Fedora:

          $ sudo yum install git gcc automake autoconf libtool

       Debian / Ubuntu:

          $ sudo apt-get install git gcc automake autoconf libtool

       FreeBSD:

          $ su -c 'pkg install git gcc automake autoconf libtool'

       Once you have the dependencies installed, clone  the  repository  and  build  the  current  master  or  a
       particular release tag:

          $ git clone https://github.com/mongodb/mongo-c-driver.git
          $ cd mongo-c-driver
          $ git checkout x.y.z  # To build a particular release
          $ ./autogen.sh --with-libbson=bundled
          $ make
          $ sudo make install

   Generating the documentation
       Install Sphinx, then:

          $ ./configure --enable-html-docs --enable-man-pages
          $ make man html

   Building on Mac OS X
       Install the XCode Command Line Tools:

          $ xcode-select --install

       The pkg-config utility is also required. First install Homebrew according to its instructions, then:

          $ brew install pkgconfig

       Download the latest release tarball:

          $ curl -LO https://github.com/mongodb/mongo-c-driver/releases/download/1.9.2/mongo-c-driver-1.9.2.tar.gz
          $ tar xzf mongo-c-driver-1.9.2.tar.gz
          $ cd mongo-c-driver-1.9.2

       Build and install the driver:

          $ ./configure
          $ make
          $ sudo make install

   Native TLS Support on Mac OS X / Darwin (Secure Transport)
       The  MongoDB  C  Driver  supports the Darwin native TLS and crypto libraries.  Using the native libraries
       there is no need to install OpenSSL. By default however, the driver will compile against  OpenSSL  if  it
       detects it being available. If OpenSSL is not available, it will fallback on the native libraries.

       To  compile against the Darwin native TLS and crypto libraries, even when OpenSSL is available, configure
       the driver like so:

          $ ./configure --enable-ssl=darwin

   OpenSSL support on El Capitan
       Beginning in OS X 10.11 El Capitan, OS X no longer includes the OpenSSL headers. To build the driver with
       SSL on El Capitan and later:

          $ brew install openssl
          $ export LDFLAGS="-L/usr/local/opt/openssl/lib"
          $ export CPPFLAGS="-I/usr/local/opt/openssl/include"

   Building on Windows
       Building on Windows requires Windows Vista or newer and Visual Studio 2010 or newer. Additionally,  cmake
       is required to generate Visual Studio project files.

       Let's  start  by  generating  Visual  Studio project files for libbson, a dependency of the C driver. The
       following assumes we are compiling for 64-bit Windows using Visual Studio  2015  Express,  which  can  be
       freely downloaded from Microsoft.

          cd mongo-c-driver-1.9.2\src\libbson
          cmake -G "Visual Studio 14 2015 Win64" \
            "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \
            "-DCMAKE_BUILD_TYPE=Release" # Defaults to debug builds

       (Run cmake -LH . for a list of other options.)

       Now that we have project files generated, we can either open the project in Visual Studio or compile from
       the command line. Let's build using the command line program msbuild.exe

          msbuild.exe /p:Configuration=Release ALL_BUILD.vcxproj

       Now  that libbson is compiled, let's install it using msbuild. It will be installed to the path specified
       by CMAKE_INSTALL_PREFIX.

          msbuild.exe /p:Configuration=Release INSTALL.vcxproj

       You should now see libbson installed in C:\mongo-c-driver

       Now let's do the same for the MongoDB C driver.

          cd mongo-c-driver-1.9.2
          cmake -G "Visual Studio 14 2015 Win64" \
            "-DENABLE_SSL=WINDOWS" \
            "-DENABLE_SASL=SSPI" \
            "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \
            "-DCMAKE_PREFIX_PATH=C:\mongo-c-driver" \
            "-DCMAKE_BUILD_TYPE=Release" # Defaults to debug builds

          msbuild.exe /p:Configuration=Release ALL_BUILD.vcxproj
          msbuild.exe /p:Configuration=Release INSTALL.vcxproj

       All of the MongoDB C Driver's components will now have been build in release mode and  can  be  found  in
       C:\mongo-c-driver.  To build and install debug binaries, remove the "-DCMAKE_BUILD_TYPE=Release" argument
       to cmake and /p:Configuration=Release to msbuild.exe.

       To use the driver libraries in your program, see visual-studio-guide.

   Native TLS Support on Windows (Secure Channel)
       The  MongoDB  C  Driver supports the Windows native TLS and crypto libraries.  Using the native libraries
       there is no need to install OpenSSL. By default however, the driver will compile against  OpenSSL  if  it
       detects it being available. If OpenSSL is not available, it will fallback on the native libraries.

       To compile against the Windows native TLS and crypto libraries, even when OpenSSL is available, configure
       the driver like so:

          cmake -G "Visual Studio 14 2015 Win64" \
            "-DENABLE_SSL=WINDOWS" \
            "-DCMAKE_INSTALL_PREFIX=C:\\mongo-c-driver" \
            "-DCMAKE_PREFIX_PATH=C:\\mongo-c-driver"

   Native SASL Support on Windows (SSPI)
       The MongoDB C Driver supports the Windows native Kerberos and Active Directory interface, SSPI. Using the
       native  libraries  there is no need to install any dependencies, such as cyrus-sasl.  By default however,
       the driver will compile against cyrus-sasl.

       To compile against the Windows native SSPI, configure the driver like so:

          cmake -G "Visual Studio 14 2015 Win64" \
            "-DENABLE_SASL=SSPI" \
            "-DCMAKE_INSTALL_PREFIX=C:\\mongo-c-driver" \
            "-DCMAKE_PREFIX_PATH=C:\\mongo-c-driver"

   OpenSSL support on Windows
       For backwards compatibility CMake will default to OpenSSL support.  If not found,  it  will  fallback  to
       native TLS support provided by the platform.

       OpenSSL 1.1.0 support requires CMake 3.7 or later on Windows.

   Tutorial
       This guide offers a brief introduction to the MongoDB C Driver.

       For more information on the C API, please refer to the api.

   ContentsTutorialInstallingStarting MongoDBInclude and link libmongoc in your C programUse libmongoc in a Microsoft Visual Studio ProjectMaking a ConnectionCreating BSON DocumentsBasic CRUD OperationsExecuting CommandsThreadingNext Steps

   Installing
       For  detailed  instructions  on  installing the MongoDB C Driver on a particular platform, please see the
       installation guide.

   Starting MongoDB
       To run the examples in this tutorial, MongoDB must be installed and running on localhost on  the  default
       port, 27017. To check if it is up and running, connect to it with the MongoDB shell.

          $ mongo --host localhost --port 27017
          MongoDB shell version: 3.0.6
          connecting to: localhost:27017/test
          >

   Include and link libmongoc in your C program
   Include mongoc.h
       All libmongoc's functions and types are available in one header file. Simply include mongoc.h:

          #include <mongoc.h>

   CMake
       The  libmongoc  installation  includes  a  CMake config-file package, so you can use CMake's find_package
       command to find libmongoc's header and library paths and link to libmongoc: CMakeLists.txt.INDENT 0.0

          # Specify the minimum version you require.
          find_package (libmongoc-1.0 1.7 REQUIRED)

          message ("--   mongoc found version \"${MONGOC_VERSION}\"")
          message ("--   mongoc include path \"${MONGOC_INCLUDE_DIRS}\"")
          message ("--   mongoc libraries \"${MONGOC_LIBRARIES}\"")

          # The "hello_mongoc.c" sample program is shared among four tests.
          add_executable (hello_mongoc ../../hello_mongoc.c)
          target_include_directories (hello_mongoc PRIVATE "${MONGOC_INCLUDE_DIRS}")
          target_link_libraries (hello_mongoc PRIVATE "${MONGOC_LIBRARIES}")
          target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_DEFINITIONS}")
libmongoc-static-1.0 config-file package:

          # Specify the minimum version you require.
          find_package (libmongoc-static-1.0 1.7 REQUIRED)

          message ("--   mongoc found version \"${MONGOC_STATIC_VERSION}\"")
          message ("--   mongoc include path \"${MONGOC_STATIC_INCLUDE_DIRS}\"")
          message ("--   mongoc libraries \"${MONGOC_STATIC_LIBRARIES}\"")

          # The "hello_mongoc.c" sample program is shared among four tests.
          add_executable (hello_mongoc ../../hello_mongoc.c)
          target_include_directories (hello_mongoc PRIVATE "${MONGOC_STATIC_INCLUDE_DIRS}")
          target_link_libraries (hello_mongoc PRIVATE "${MONGOC_STATIC_LIBRARIES}")
          target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_STATIC_DEFINITIONS}")

   pkg-config
       If you're not using CMake, use pkg-config on the command line to set header and library paths:

          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0)

       Or to statically link to libmongoc:

          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0)

   Specifying header and include paths manually
       If you aren't using CMake or pkg-config, paths and libraries can be managed manually.

          $ gcc -o hello_mongoc hello_mongoc.c \
              -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \
              -lmongoc-1.0 -lbson-1.0
          $ ./hello_mongoc
          { "ok" : 1.000000 }

       For Windows users, the code can be compiled and run with the following commands. (This assumes  that  the
       MongoDB C Driver has been installed to C:\mongo-c-driver; change the include directory as needed.)

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 hello_mongoc.c
          C:\> hello_mongoc
          { "ok" : 1.000000 }

   Use libmongoc in a Microsoft Visual Studio Project
       See the libmongoc and Visual Studio guide.

   Making a Connection
       Access  MongoDB with a mongoc_client_t. It transparently connects to standalone servers, replica sets and
       sharded clusters on demand. To perform operations on a database or collection, create a mongoc_database_t
       or mongoc_collection_t struct from the mongoc_client_t.

       At the start of an application, call mongoc_init before any other libmongoc functions. At the  end,  call
       the  appropriate  destroy function for each collection, database, or client handle, in reverse order from
       how they were constructed. Call mongoc_cleanup before exiting.

       The example below establishes a connection to a standalone server  on  localhost,  registers  the  client
       application as "connect-example," and performs a simple command.

       More  information  about  database  operations can be found in the CRUD Operations and Executing Commands
       sections. Examples of connecting to replica sets and sharded  clusters  can  be  found  on  the  Advanced
       Connections page.  hello_mongoc.c.INDENT 0.0

          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             const char *uri_str = "mongodb://localhost:27017";
             mongoc_client_t *client;
             mongoc_database_t *database;
             mongoc_collection_t *collection;
             bson_t *command, reply, *insert;
             bson_error_t error;
             char *str;
             bool retval;

             /*
              * Required to initialize libmongoc's internals
              */
             mongoc_init ();

             /*
              * Optionally get MongoDB URI from command line
              */
             if (argc > 1) {
                uri_str = argv[1];
             }

             /*
              * Create a new client instance
              */
             client = mongoc_client_new (uri_str);

             /*
              * Register the application name so we can track it in the profile logs
              * on the server. This can also be done from the URI (see other examples).
              */
             mongoc_client_set_appname (client, "connect-example");

             /*
              * Get a handle on the database "db_name" and collection "coll_name"
              */
             database = mongoc_client_get_database (client, "db_name");
             collection = mongoc_client_get_collection (client, "db_name", "coll_name");

             /*
              * Do work. This example pings the database, prints the result as JSON and
              * performs an insert
              */
             command = BCON_NEW ("ping", BCON_INT32 (1));

             retval = mongoc_client_command_simple (
                client, "admin", command, NULL, &reply, &error);

             if (!retval) {
                fprintf (stderr, "%s\n", error.message);
                return EXIT_FAILURE;
             }

             str = bson_as_json (&reply, NULL);
             printf ("%s\n", str);

             insert = BCON_NEW ("hello", BCON_UTF8 ("world"));

             if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) {
                fprintf (stderr, "%s\n", error.message);
             }

             bson_destroy (insert);
             bson_destroy (&reply);
             bson_destroy (command);
             bson_free (str);

             /*
              * Release our handles and clean up libmongoc
              */
             mongoc_collection_destroy (collection);
             mongoc_database_destroy (database);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

   Creating BSON Documents
       Documents  are stored in MongoDB's data format, BSON. The C driver uses libbson to create BSON documents.
       There are several ways to construct them: appending key-value pairs, using BCON, or parsing JSON.

   Appending BSON
       A BSON document, represented as a bson_t in code, can be constructed one field at a time using  libbson's
       append functions.

       For example, to create a document like this:

          {
             born : ISODate("1906-12-09"),
             died : ISODate("1992-01-01"),
             name : {
                first : "Grace",
                last : "Hopper"
             },
             languages : [ "MATH-MATIC", "FLOW-MATIC", "COBOL" ],
             degrees: [ { degree: "BA", school: "Vassar" }, { degree: "PhD", school: "Yale" } ]
          }

       Use the following code:

          #include <bson.h>

          int
          main (int   argc,
                char *argv[])
          {
             struct tm   born = { 0 };
             struct tm   died = { 0 };
             const char *lang_names[] = {"MATH-MATIC", "FLOW-MATIC", "COBOL"};
             const char *schools[] = {"Vassar", "Yale"};
             const char *degrees[] = {"BA", "PhD"};
             uint32_t    i;
             char        buf[16];
             const       char *key;
             size_t      keylen;
             bson_t     *document;
             bson_t      child;
             bson_t      child2;
             char       *str;

             document = bson_new ();

             /*
              * Append { "born" : ISODate("1906-12-09") } to the document.
              * Passing -1 for the length argument tells libbson to calculate the string length.
              */
             born.tm_year = 6;  /* years are 1900-based */
             born.tm_mon = 11;  /* months are 0-based */
             born.tm_mday = 9;
             bson_append_date_time (document, "born", -1, mktime (&born) * 1000);

             /*
              * Append { "died" : ISODate("1992-01-01") } to the document.
              */
             died.tm_year = 92;
             died.tm_mon = 0;
             died.tm_mday = 1;

             /*
              * For convenience, this macro passes length -1 by default.
              */
             BSON_APPEND_DATE_TIME (document, "died", mktime (&died) * 1000);

             /*
              * Append a subdocument.
              */
             BSON_APPEND_DOCUMENT_BEGIN (document, "name", &child);
             BSON_APPEND_UTF8 (&child, "first", "Grace");
             BSON_APPEND_UTF8 (&child, "last", "Hopper");
             bson_append_document_end (document, &child);

             /*
              * Append array of strings. Generate keys "0", "1", "2".
              */
             BSON_APPEND_ARRAY_BEGIN (document, "languages", &child);
             for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) {
                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
                bson_append_utf8 (&child, key, (int) keylen, lang_names[i], -1);
             }
             bson_append_array_end (document, &child);

             /*
              * Array of subdocuments:
              *    degrees: [ { degree: "BA", school: "Vassar" }, ... ]
              */
             BSON_APPEND_ARRAY_BEGIN (document, "degrees", &child);
             for (i = 0; i < sizeof degrees / sizeof (char *); ++i) {
                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
                bson_append_document_begin (&child, key, (int) keylen, &child2);
                BSON_APPEND_UTF8 (&child2, "degree", degrees[i]);
                BSON_APPEND_UTF8 (&child2, "school", schools[i]);
                bson_append_document_end (&child, &child2);
             }
             bson_append_array_end (document, &child);

             /*
              * Print the document as a JSON string.
              */
             str = bson_as_canonical_extended_json (document, NULL);
             printf ("%s\n", str);
             bson_free (str);

             /*
              * Clean up allocated bson documents.
              */
             bson_destroy (document);
             return 0;
          }

       See the libbson documentation for all of the types that can be appended to a bson_t.

   Using BCON
       BSON  C Object Notation, BCON for short, is an alternative way of constructing BSON documents in a manner
       closer to the intended format. It has less type-safety than BSON's append functions but results  in  less
       code.

          #include <bson.h>

          int
          main (int   argc,
                char *argv[])
          {
             struct tm born = { 0 };
             struct tm died = { 0 };
             bson_t   *document;
             char     *str;

             born.tm_year = 6;
             born.tm_mon = 11;
             born.tm_mday = 9;

             died.tm_year = 92;
             died.tm_mon = 0;
             died.tm_mday = 1;

             document = BCON_NEW (
                "born", BCON_DATE_TIME (mktime (&born) * 1000),
                "died", BCON_DATE_TIME (mktime (&died) * 1000),
                "name", "{",
                "first", BCON_UTF8 ("Grace"),
                "last", BCON_UTF8 ("Hopper"),
                "}",
                "languages", "[",
                BCON_UTF8 ("MATH-MATIC"),
                BCON_UTF8 ("FLOW-MATIC"),
                BCON_UTF8 ("COBOL"),
                "]",
                "degrees", "[",
                "{", "degree", BCON_UTF8 ("BA"), "school", BCON_UTF8 ("Vassar"), "}",
                "{", "degree", BCON_UTF8 ("PhD"), "school", BCON_UTF8 ("Yale"), "}",
                "]");

             /*
              * Print the document as a JSON string.
              */
             str = bson_as_canonical_extended_json (document, NULL);
             printf ("%s\n", str);
             bson_free (str);

             /*
              * Clean up allocated bson documents.
              */
             bson_destroy (document);
             return 0;
          }

       Notice that BCON can create arrays, subdocuments and arbitrary fields.

   Creating BSON from JSON
       For single documents, BSON can be created from JSON strings via bson_new_from_json.

          #include <bson.h>

          int
          main (int   argc,
                char *argv[])
          {
             bson_error_t error;
             bson_t      *bson;
             char        *string;

             const char *json = "{\"name\": {\"first\":\"Grace\", \"last\":\"Hopper\"}}";
             bson = bson_new_from_json ((const uint8_t *)json, -1, &error);

             if (!bson) {
                fprintf (stderr, "%s\n", error.message);
                return EXIT_FAILURE;
             }

             string = bson_as_canonical_extended_json (bson, NULL);
             printf ("%s\n", string);
             bson_free (string);

             return 0;
          }

       To initialize BSON from a sequence of JSON documents, use bson_json_reader_t.

   Basic CRUD Operations
       This section demonstrates the basics of using the C Driver to interact with MongoDB.

   Inserting a Document
       To  insert  documents  into  a  collection,  first  obtain  a  handle  to  a  mongoc_collection_t  via  a
       mongoc_client_t. Then, use mongoc_collection_insert_one to add BSON documents  to  the  collection.  This
       example inserts into the database "mydb" and collection "mycoll".

       When finished, ensure that allocated structures are freed by using their respective destroy functions.

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int   argc,
                char *argv[])
          {
              mongoc_client_t *client;
              mongoc_collection_t *collection;
              bson_error_t error;
              bson_oid_t oid;
              bson_t *doc;

              mongoc_init ();

              client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
              collection = mongoc_client_get_collection (client, "mydb", "mycoll");

              doc = bson_new ();
              bson_oid_init (&oid, NULL);
              BSON_APPEND_OID (doc, "_id", &oid);
              BSON_APPEND_UTF8 (doc, "hello", "world");

              if (!mongoc_collection_insert_one (
                     collection, doc, NULL, NULL, &error)) {
                  fprintf (stderr, "%s\n", error.message);
              }

              bson_destroy (doc);
              mongoc_collection_destroy (collection);
              mongoc_client_destroy (client);
              mongoc_cleanup ();

              return 0;
          }

       Compile the code and run it:

          $ gcc -o insert insert.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./insert

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 insert.c
          C:\> insert

       To verify that the insert succeeded, connect with the MongoDB shell.

          $ mongo
          MongoDB shell version: 3.0.6
          connecting to: test
          > use mydb
          switched to db mydb
          > db.mycoll.find()
          { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" }
          >

   Finding a Document
       To  query  a  MongoDB  collection with the C driver, use the function mongoc_collection_find_with_opts().
       This returns a cursor to the matching documents.  The  following  examples  iterate  through  the  result
       cursors and print the matches to stdout as JSON strings.

       Use a document as a query specifier; for example,

          { "color" : "red" }

       will  match any document with a field named "color" with value "red". An empty document {} can be used to
       match all documents.

       This first example uses an empty query specifier to  find  all  documents  in  the  database  "mydb"  and
       collection "mycoll".

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             const bson_t *doc;
             bson_t *query;
             char *str;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=find-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
             query = bson_new ();
             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);

             while (mongoc_cursor_next (cursor, &doc)) {
                str = bson_as_canonical_extended_json (doc, NULL);
                printf ("%s\n", str);
                bson_free (str);
             }

             bson_destroy (query);
             mongoc_cursor_destroy (cursor);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o find find.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./find
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find.c
          C:\> find
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

       To look for a specific document, add a specifier to query. This example adds a call to BSON_APPEND_UTF8()
       to look for all documents matching {"hello" : "world"}.

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             const bson_t *doc;
             bson_t *query;
             char *str;

             mongoc_init ();

             client = mongoc_client_new (
                "mongodb://localhost:27017/?appname=find-specific-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
             query = bson_new ();
             BSON_APPEND_UTF8 (query, "hello", "world");

             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);

             while (mongoc_cursor_next (cursor, &doc)) {
                str = bson_as_canonical_extended_json (doc, NULL);
                printf ("%s\n", str);
                bson_free (str);
             }

             bson_destroy (query);
             mongoc_cursor_destroy (cursor);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

          $ gcc -o find-specific find-specific.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./find-specific
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find-specific.c
          C:\> find-specific
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

   Updating a Document
       This  code  snippet  gives  an  example of using mongoc_collection_update_one() to update the fields of a
       document.

       Using the "mydb"  database,  the  following  example  inserts  an  example  document  into  the  "mycoll"
       collection. Then, using its _id field, the document is updated with different values and a new field.

          #include <bcon.h>
          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_collection_t *collection;
             mongoc_client_t *client;
             bson_error_t error;
             bson_oid_t oid;
             bson_t *doc = NULL;
             bson_t *update = NULL;
             bson_t *query = NULL;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=update-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");

             bson_oid_init (&oid, NULL);
             doc = BCON_NEW ("_id", BCON_OID (&oid), "key", BCON_UTF8 ("old_value"));

             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
                fprintf (stderr, "%s\n", error.message);
                goto fail;
             }

             query = BCON_NEW ("_id", BCON_OID (&oid));
             update = BCON_NEW ("$set",
                                "{",
                                "key",
                                BCON_UTF8 ("new_value"),
                                "updated",
                                BCON_BOOL (true),
                                "}");

             if (!mongoc_collection_update_one (
                    collection, query, update, NULL, NULL, &error)) {
                fprintf (stderr, "%s\n", error.message);
                goto fail;
             }

          fail:
             if (doc)
                bson_destroy (doc);
             if (query)
                bson_destroy (query);
             if (update)
                bson_destroy (update);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o update update.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./update

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 update.c
          C:\> update
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

       To verify that the update succeeded, connect with the MongoDB shell.

          $ mongo
          MongoDB shell version: 3.0.6
          connecting to: test
          > use mydb
          switched to db mydb
          > db.mycoll.find({"updated" : true})
          { "_id" : ObjectId("55ef549236fe322f9490e17b"), "updated" : true, "key" : "new_value" }
          >

   Deleting a Document
       This example illustrates the use of mongoc_collection_delete_one() to delete a document.

       The  following  code inserts a sample document into the database "mydb" and collection "mycoll". Then, it
       deletes all documents matching {"hello" : "world"}.

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             bson_error_t error;
             bson_oid_t oid;
             bson_t *doc;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=delete-example");
             collection = mongoc_client_get_collection (client, "test", "test");

             doc = bson_new ();
             bson_oid_init (&oid, NULL);
             BSON_APPEND_OID (doc, "_id", &oid);
             BSON_APPEND_UTF8 (doc, "hello", "world");

             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
                fprintf (stderr, "Insert failed: %s\n", error.message);
             }

             bson_destroy (doc);

             doc = bson_new ();
             BSON_APPEND_OID (doc, "_id", &oid);

             if (!mongoc_collection_delete_one (
                    collection, doc, NULL, NULL, &error)) {
                fprintf (stderr, "Delete failed: %s\n", error.message);
             }

             bson_destroy (doc);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o delete delete.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./delete

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 delete.c
          C:\> delete

       Use the MongoDB shell to prove that the documents have been removed successfully.

          $ mongo
          MongoDB shell version: 3.0.6
          connecting to: test
          > use mydb
          switched to db mydb
          > db.mycoll.count({"hello" : "world"})
          0
          >

   Counting Documents
       Counting the number of documents in a MongoDB collection is similar to performing a find operation.  This
       example counts the number of documents matching {"hello" : "world"} in the database "mydb" and collection
       "mycoll".

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             bson_error_t error;
             bson_t *doc;
             int64_t count;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=count-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
             doc = bson_new_from_json (
                (const uint8_t *) "{\"hello\" : \"world\"}", -1, &error);

             count = mongoc_collection_count (
                collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);

             if (count < 0) {
                fprintf (stderr, "%s\n", error.message);
             } else {
                printf ("%" PRId64 "\n", count);
             }

             bson_destroy (doc);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o count count.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./count
          1

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 count.c
          C:\> count
          1

   Executing Commands
       The  driver  provides  helper functions for executing MongoDB commands on client, database and collection
       structures. These functions return cursors; the _simple variants return booleans  indicating  success  or
       failure.

       This example executes the collStats command against the collection "mycoll" in database "mydb".

          #include <bson.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             bson_error_t error;
             bson_t *command;
             bson_t reply;
             char *str;

             mongoc_init ();

             client = mongoc_client_new (
                "mongodb://localhost:27017/?appname=executing-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");

             command = BCON_NEW ("collStats", BCON_UTF8 ("mycoll"));
             if (mongoc_collection_command_simple (
                    collection, command, NULL, &reply, &error)) {
                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (stderr, "Failed to run command: %s\n", error.message);
             }

             bson_destroy (command);
             bson_destroy (&reply);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o executing executing.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./executing
          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 executing.c
          C:\> executing
          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }

   Threading
       The MongoDB C Driver is thread-unaware in the vast majority of its operations. This means it is up to the
       programmer to guarantee thread-safety.

       However,  mongoc_client_pool_t  is  thread-safe  and  is used to fetch a mongoc_client_t in a thread-safe
       manner. After retrieving a client from the pool, the client structure should be considered owned  by  the
       calling  thread.  When  the  thread  is  finished,  the  client  should  be  placed  back  into the pool.
       example-pool.c.INDENT 0.0

          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-pool [CONNECTION_STRING] */

          #include <mongoc.h>
          #include <pthread.h>
          #include <stdio.h>

          static pthread_mutex_t mutex;
          static bool in_shutdown = false;

          static void *
          worker (void *data)
          {
             mongoc_client_pool_t *pool = data;
             mongoc_client_t *client;
             bson_t ping = BSON_INITIALIZER;
             bson_error_t error;
             bool r;

             BSON_APPEND_INT32 (&ping, "ping", 1);

             while (true) {
                client = mongoc_client_pool_pop (pool);
                /* Do something with client. If you are writing an HTTP server, you
                 * probably only want to hold onto the client for the portion of the
                 * request performing database queries.
                 */
                r = mongoc_client_command_simple (
                   client, "admin", &ping, NULL, NULL, &error);

                if (!r) {
                   fprintf (stderr, "%s\n", error.message);
                }

                mongoc_client_pool_push (pool, client);

                pthread_mutex_lock (&mutex);
                if (in_shutdown || !r) {
                   pthread_mutex_unlock (&mutex);
                   break;
                }

                pthread_mutex_unlock (&mutex);
             }

             bson_destroy (&ping);
             return NULL;
          }

          int
          main (int argc, char *argv[])
          {
             const char *uristr = "mongodb://127.0.0.1/?appname=pool-example";
             mongoc_uri_t *uri;
             mongoc_client_pool_t *pool;
             pthread_t threads[10];
             unsigned i;
             void *ret;

             pthread_mutex_init (&mutex, NULL);
             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             uri = mongoc_uri_new (uristr);
             if (!uri) {
                fprintf (stderr, "Failed to parse URI: \"%s\".\n", uristr);
                return EXIT_FAILURE;
             }

             pool = mongoc_client_pool_new (uri);
             mongoc_client_pool_set_error_api (pool, 2);

             for (i = 0; i < 10; i++) {
                pthread_create (&threads[i], NULL, worker, pool);
             }

             sleep (10);
             pthread_mutex_lock (&mutex);
             in_shutdown = true;
             pthread_mutex_unlock (&mutex);

             for (i = 0; i < 10; i++) {
                pthread_join (threads[i], &ret);
             }

             mongoc_client_pool_destroy (pool);
             mongoc_uri_destroy (uri);

             mongoc_cleanup ();

             return 0;
          }

   Next Steps
       To find information on advanced topics, browse the rest of the C driver guide  or  the  official  MongoDB
       documentation.

       For  help with common issues, consult the Troubleshooting page. To report a bug or request a new feature,
       follow these instructions.

   Authentication
       This guide covers the use of authentication options with the MongoDB C Driver. Ensure  that  the  MongoDB
       server  is  also properly configured for authentication before making a connection. For more information,
       see the MongoDB security documentation.

       The MongoDB C driver supports several authentication mechanisms through the  use  of  MongoDB  connection
       URIs.

       By  default,  if  a  username and password are provided as part of the connection string (and an optional
       authentication database), they are used to connect  via  the  default  authentication  mechanism  of  the
       server.

       To select a specific authentication mechanism other than the default, see the list of supported mechanism
       below.

          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");

       Currently supported values for the authMechanism connection string option are:

       • SCRAM-SHA-1MONGODB-CRGSSAPIPLAINX509

   Basic Authentication (SCRAM-SHA-1)
       The  default  authentication  mechanism  when talking to MongoDB 3.0 and later is SCRAM-SHA-1 (RFC 5802).
       Using this authentication mechanism means that the password is never actually sent  over  the  wire  when
       authenticating,  but  rather  a  computed  proof that the client password is the same as the password the
       server knows.

          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1&authSource=mydb");

       NOTE:
          SCRAM-SHA-1 authenticates against the admin database by default. If the user  is  created  in  another
          database, then specifying the authSource is required.

   Legacy Authentication (MONGODB-CR)
       The  MONGODB-CR  authMechanism  is  a  challenge  response  authentication  mechanism. It was the default
       mechanism until MongoDB 3.0 and is being phased out. It is  strongly  suggested  that  users  upgrade  to
       SCRAM-SHA-1.

       NOTE:
          MONGODB-CR  authenticates  against  the  admin  database by default. If the user is created in another
          database, then specifying the authSource is required.

   GSSAPI (Kerberos) Authentication
       NOTE:
          Kerberos support requires compiling the  driver  against  cyrus-sasl  on  UNIX-like  environments.  On
          Windows, configure the driver to build against the Windows Native SSPI.

       GSSAPI (Kerberos) authentication is available in the Enterprise Edition of MongoDB. To authenticate using
       GSSAPI, the MongoDB C driver must be installed with SASL support.

       On UNIX-like environments, run the kinit command before using the following authentication methods:

          $ kinit mongodbuser@EXAMPLE.COM
          mongodbuser@EXAMPLE.COM's Password:
          $ klistCredentials cache: FILE:/tmp/krb5cc_1000
                  Principal: mongodbuser@EXAMPLE.COM

            Issued                Expires               Principal
          Feb  9 13:48:51 2013  Feb  9 23:48:51 2013  krbtgt/EXAMPLE.COM@EXAMPLE.COM

       Now authenticate using the MongoDB URI. GSSAPI authenticates against the $external virtual database, so a
       database does not need to be specified in the URI. Note that the Kerberos principal must be URL-encoded:

          mongoc_client_t *client;

          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI");

       NOTE:
          GSSAPI  authenticates  against  the  $external  database, so specifying the authSource database is not
          required.

       The driver supports these GSSAPI properties:

       • CANONICALIZE_HOST_NAME: This might  be  required  with  Cyrus-SASL  when  the  hosts  report  different
         hostnames than what is used in the Kerberos database. The default is "false".

       • SERVICE_NAME: Use a different service name than the default, "mongodb".

       Set properties in the URL:

          mongoc_client_t *client;

          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&"
                                      "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true");

       If  you  encounter  errors such as Invalid net address, check if the application is behind a NAT (Network
       Address Translation) firewall. If so, create a ticket that  uses  forwardable  and  addressless  Kerberos
       tickets. This can be done by passing -f -A to kinit.

          $ kinit -f -A mongodbuser@EXAMPLE.COM

   SASL Plain Authentication
       NOTE:
          The MongoDB C Driver must be compiled with SASL support in order to use SASL PLAIN authentication.

       MongoDB  Enterprise  Edition  supports  the  SASL  PLAIN authentication mechanism, initially intended for
       delegating authentication to an LDAP server. Using the SASL  PLAIN  mechanism  is  very  similar  to  the
       challenge  response  mechanism  with  usernames  and  passwords.  This  authentication mechanism uses the
       $external virtual database for LDAP support:

       NOTE:
          SASL PLAIN is a clear-text authentication mechanism. It is strongly recommended to connect to  MongoDB
          using SSL with certificate validation when using the PLAIN mechanism.

          mongoc_client_t *client;

          client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN");

       PLAIN  authenticates  against  the  $external  database,  so  specifying  the  authSource database is not
       required.

   X.509 Certificate Authentication
       NOTE:
          The MongoDB C Driver must be compiled with SSL support for X.509 authentication support. Once this  is
          done, start a server with the following options:

              $ mongod --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem

       The  MONGODB-X509  mechanism  authenticates a username derived from the distinguished subject name of the
       X.509 certificate presented by the driver during SSL negotiation. This authentication method requires the
       use of SSL connections with certificate validation.

          mongoc_client_t *client;
          mongoc_ssl_opt_t ssl_opts = { 0 };

          ssl_opts.pem_file = "mycert.pem";
          ssl_opts.pem_pwd = "mycertpassword";
          ssl_opts.ca_file = "myca.pem";
          ssl_opts.ca_dir = "trust_dir";
          ssl_opts.weak_cert_validation = false;

          client = mongoc_client_new ("mongodb://x509_derived_username@localhost/?authMechanism=MONGODB-X509");
          mongoc_client_set_ssl_opts (client, &ssl_opts);

       MONGODB-X509 authenticates against the $external database, so specifying the authSource database  is  not
       required. For more information on the x509_derived_username, see the MongoDB server x.509 tutorial.

       NOTE:
          The MongoDB C Driver will attempt to determine the x509 derived username when none is provided, and as
          of MongoDB 3.4 providing the username is not required at all.

   Basic Troubleshooting
   Troubleshooting Checklist
       The following is a short list of things to check when you have a problem.

       • Did you call mongoc_init() in main()? If not, you will likely see a segfault.

       • Have you leaked any clients or cursors as can be found with mongoc-stat <PID>?

       • Have packets been delivered to the server? See egress bytes from mongoc-stat <PID>.

       • Does  valgrind  show  any leaks? Ensure you call mongoc_cleanup() at the end of your process to cleanup
         lingering allocations from the MongoDB C driver.

       • If compiling your own copy of MongoDB C driver, consider configuring with  --enable-tracing  to  enable
         function tracing and hex dumps of network packets to STDERR and STDOUT.

   Performance Counters
       The  MongoDB  C driver comes with a unique feature to help developers and sysadmins troubleshoot problems
       in production.  Performance counters are available for each process using the driver.  The  counters  can
       be  accessed  outside  of  the  application process via a shared memory segment.  This means that you can
       graph statistics about your application process easily from tools like  Munin  or  Nagios.   Your  author
       often uses watch --interval=0.5 -d mongoc-stat $PID to monitor an application.

       Counters are currently available on UNIX-like platforms that support shared memory segments.

       • Active and Disposed Cursors

       • Active and Disposed Clients, Client Pools, and Socket Streams.

       • Number of operations sent and received, by type.

       • Bytes transferred and received.

       • Authentication successes and failures.

       • Number of wire protocol errors.

       To  access  counters  for  a  given  process,  simply  provide  the process id to the mongoc-stat program
       installed with the MongoDB C Driver.

          $ mongoc-stat 22203
             Operations : Egress Total        : The number of sent operations.                    : 13247
             Operations : Ingress Total       : The number of received operations.                : 13246
             Operations : Egress Queries      : The number of sent Query operations.              : 13247
             Operations : Ingress Queries     : The number of received Query operations.          : 0
             Operations : Egress GetMore      : The number of sent GetMore operations.            : 0
             Operations : Ingress GetMore     : The number of received GetMore operations.        : 0
             Operations : Egress Insert       : The number of sent Insert operations.             : 0
             Operations : Ingress Insert      : The number of received Insert operations.         : 0
             Operations : Egress Delete       : The number of sent Delete operations.             : 0
             Operations : Ingress Delete      : The number of received Delete operations.         : 0
             Operations : Egress Update       : The number of sent Update operations.             : 0
             Operations : Ingress Update      : The number of received Update operations.         : 0
             Operations : Egress KillCursors  : The number of sent KillCursors operations.        : 0
             Operations : Ingress KillCursors : The number of received KillCursors operations.    : 0
             Operations : Egress Msg          : The number of sent Msg operations.                : 0
             Operations : Ingress Msg         : The number of received Msg operations.            : 0
             Operations : Egress Reply        : The number of sent Reply operations.              : 0
             Operations : Ingress Reply       : The number of received Reply operations.          : 13246
                Cursors : Active              : The number of active cursors.                     : 1
                Cursors : Disposed            : The number of disposed cursors.                   : 13246
                Clients : Active              : The number of active clients.                     : 1
                Clients : Disposed            : The number of disposed clients.                   : 0
                Streams : Active              : The number of active streams.                     : 1
                Streams : Disposed            : The number of disposed streams.                   : 0
                Streams : Egress Bytes        : The number of bytes sent.                         : 794931
                Streams : Ingress Bytes       : The number of bytes received.                     : 589694
                Streams : N Socket Timeouts   : The number of socket timeouts.                    : 0
           Client Pools : Active              : The number of active client pools.                : 1
           Client Pools : Disposed            : The number of disposed client pools.              : 0
               Protocol : Ingress Errors      : The number of protocol errors on ingress.         : 0
                   Auth : Failures            : The number of failed authentication requests.     : 0
                   Auth : Success             : The number of successful authentication requests. : 0

   Submitting a Bug Report
       Think you've found a bug? Want to see a new feature in the MongoDB C driver? Please open a  case  in  our
       issue management tool, JIRA:

       • Create an account and login.

       • Navigate to the CDRIVER project.

       • Click  Create  Issue  -  Please provide as much information as possible about the issue type and how to
         reproduce it.

       Bug reports in JIRA for all driver projects (i.e. CDRIVER,  CSHARP,  JAVA)  and  the  Core  Server  (i.e.
       SERVER) project are public.

   Guides
   Common Tasks
       Drivers  for  some  other  languages  provide  helper functions to perform certain common tasks. In the C
       Driver we must explicitly build commands to send to the server.

       This snippet contains example code for the explain, copydb and cloneCollection commands.

   Setup
       First we'll write some code to insert sample data: doc-common-insert.c.INDENT 0.0

          /* Don't try to compile this file on its own. It's meant to be #included
             by example code */

          /* Insert some sample data */
          bool
          insert_data (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             enum N { ndocs = 4 };
             bson_t *docs[ndocs];
             bson_error_t error;
             int i = 0;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
             docs[2] = BCON_NEW (
                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");

             for (i = 0; i < ndocs; i++) {
                mongoc_bulk_operation_insert (bulk, docs[i]);
                bson_destroy (docs[i]);
                docs[i] = NULL;
             }

             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);

             if (!ret) {
                fprintf (stderr, "Error inserting data: %s\n", error.message);
             }

             mongoc_bulk_operation_destroy (bulk);
             return ret;
          }

          /* A helper which we'll use a lot later on */
          void
          print_res (const bson_t *reply)
          {
             BSON_ASSERT (reply);
             char *str = bson_as_canonical_extended_json (reply, NULL);
             printf ("%s\n", str);
             bson_free (str);
          }

   explain Command
       This is how to use the explain command in MongoDB 3.2+: explain.c.INDENT 0.0

          bool
          explain (mongoc_collection_t *collection)
          {
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;

             command = BCON_NEW ("explain",
                                 "{",
                                 "find",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "filter",
                                 "{",
                                 "x",
                                 BCON_INT32 (1),
                                 "}",
                                 "}");
             res = mongoc_collection_command_simple (
                collection, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with explain: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply */
             print_res (&reply);

          cleanup:
             bson_destroy (&reply);
             bson_destroy (command);
             return res;
          }

   copydb Command
       This example requires two instances of mongo to be running.

       Here's how to use the copydb command to copy a database from another instance of MongoDB: copydb.c.INDENT
       0.0

          bool
          copydb (mongoc_client_t *client, const char *other_host_and_port)
          {
             mongoc_database_t *admindb;
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;

             BSON_ASSERT (other_host_and_port);
             /* Must do this from the admin db */
             admindb = mongoc_client_get_database (client, "admin");

             command = BCON_NEW ("copydb",
                                 BCON_INT32 (1),
                                 "fromdb",
                                 BCON_UTF8 ("test"),
                                 "todb",
                                 BCON_UTF8 ("test2"),

                                 /* If you want from a different host */
                                 "fromhost",
                                 BCON_UTF8 (other_host_and_port));
             res =
                mongoc_database_command_simple (admindb, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with copydb: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply */
             print_res (&reply);

          cleanup:
             bson_destroy (&reply);
             bson_destroy (command);
             mongoc_database_destroy (admindb);

             return res;
          }

   cloneCollection Command
       This example requires two instances of mongo to be running.

       Here's an example of the cloneCollection command to clone a collection from another instance of  MongoDB:
       clone-collection.c.INDENT 0.0

          bool
          clone_collection (mongoc_database_t *database, const char *other_host_and_port)
          {
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;

             BSON_ASSERT (other_host_and_port);
             command = BCON_NEW ("cloneCollection",
                                 BCON_UTF8 ("test.remoteThings"),
                                 "from",
                                 BCON_UTF8 (other_host_and_port),
                                 "query",
                                 "{",
                                 "x",
                                 BCON_INT32 (1),
                                 "}");
             res =
                mongoc_database_command_simple (database, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with clone: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply */
             print_res (&reply);

          cleanup:
             bson_destroy (&reply);
             bson_destroy (command);

             return res;
          }

   Running the Examples
       common-operations.c.INDENT 0.0

          /*
           * Copyright 2016 MongoDB, Inc.
           *
           * Licensed under the Apache License, Version 2.0 (the "License");
           * you may not use this file except in compliance with the License.
           * You may obtain a copy of the License at
           *
           *   http://www.apache.org/licenses/LICENSE-2.0
           *
           * Unless required by applicable law or agreed to in writing, software
           * distributed under the License is distributed on an "AS IS" BASIS,
           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           * See the License for the specific language governing permissions and
           * limitations under the License.
           */

          #include <mongoc.h>
          #include <stdio.h>

          const char *COLLECTION_NAME = "things";

          #include "../doc-common-insert.c"
          #include "explain.c"
          #include "copydb.c"
          #include "clone-collection.c"

          int
          main (int argc, char *argv[])
          {
             mongoc_database_t *database = NULL;
             mongoc_client_t *client = NULL;
             mongoc_collection_t *collection = NULL;
             char *host_and_port;
             int res = 0;
             char *other_host_and_port = NULL;

             if (argc < 2 || argc > 3) {
                fprintf (stderr,
                         "usage: %s MONGOD-1-CONNECTION-STRING "
                         "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
                         argv[0]);
                fprintf (stderr,
                         "MONGOD-1-CONNECTION-STRING can be "
                         "of the following forms:\n");
                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
                fprintf (stderr,
                         "mongodb://user:pass@localhost:27017\t"
                         "local machine on port 27017, and authenticate with username "
                         "user and password pass\n");
                return 1;
             }

             mongoc_init ();

             if (strncmp (argv[1], "mongodb://", 10) == 0) {
                host_and_port = bson_strdup (argv[1]);
             } else {
                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
             }
             other_host_and_port = argc > 2 ? argv[2] : NULL;

             client = mongoc_client_new (host_and_port);

             if (!client) {
                fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port);
                res = 2;
                goto cleanup;
             }

             mongoc_client_set_error_api (client, 2);
             database = mongoc_client_get_database (client, "test");
             collection = mongoc_database_get_collection (database, COLLECTION_NAME);

             printf ("Inserting data\n");
             if (!insert_data (collection)) {
                res = 3;
                goto cleanup;
             }

             printf ("explain\n");
             if (!explain (collection)) {
                res = 4;
                goto cleanup;
             }

             if (other_host_and_port) {
                printf ("copydb\n");
                if (!copydb (client, other_host_and_port)) {
                   res = 5;
                   goto cleanup;
                }

                printf ("clone collection\n");
                if (!clone_collection (database, other_host_and_port)) {
                   res = 6;
                   goto cleanup;
                }
             }

          cleanup:
             if (collection) {
                mongoc_collection_destroy (collection);
             }

             if (database) {
                mongoc_database_destroy (database);
             }

             if (client) {
                mongoc_client_destroy (client);
             }

             bson_free (host_and_port);
             mongoc_cleanup ();
             return res;
          }
          $ mongod

          $ mkdir /tmp/db2$ mongod --dbpath /tmp/db2 --port 27018 # second instance

       Now compile and run the example program:

          $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
          Inserting data
          explain
          {
             "executionStats" : {
                "allPlansExecution" : [],
                "executionStages" : {
                   "advanced" : 19,
                   "direction" : "forward" ,
                   "docsExamined" : 76,
                   "executionTimeMillisEstimate" : 0,
                   "filter" : {
                      "x" : {
                         "$eq" : 1
                      }
                   },
                   "invalidates" : 0,
                   "isEOF" : 1,
                   "nReturned" : 19,
                   "needTime" : 58,
                   "needYield" : 0,
                   "restoreState" : 0,
                   "saveState" : 0,
                   "stage" : "COLLSCAN" ,
                   "works" : 78
                },
                "executionSuccess" : true,
                "executionTimeMillis" : 0,
                "nReturned" : 19,
                "totalDocsExamined" : 76,
                "totalKeysExamined" : 0
             },
             "ok" : 1,
             "queryPlanner" : {
                "indexFilterSet" : false,
                "namespace" : "test.things",
                "parsedQuery" : {
                   "x" : {
                      "$eq" : 1
                   }
                },
                "plannerVersion" : 1,
                "rejectedPlans" : [],
                "winningPlan" : {
                   "direction" : "forward" ,
                   "filter" : {
                      "x" : {
                         "$eq" : 1
                      }
                   },
                   "stage" : "COLLSCAN"
                }
             },
             "serverInfo" : {
                "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
                "host" : "MacBook-Pro-57.local",
                "port" : 27017,
                "version" : "3.2.6"
             }
          }
          copydb
          { "ok" : 1 }
          clone collection
          { "ok" : 1 }

   Advanced Connections
       The following guide contains information specific to certain types of MongoDB configurations.

       For  an  example of connecting to a simple standalone server, see the Tutorial. To establish a connection
       with authentication options enabled, see the Authentication page.

   Connecting to a Replica Set
       Connecting to a replica set is much like connecting to a standalone MongoDB server.  Simply  specify  the
       replica set name using the ?replicaSet=myreplset URI option.

          #include <bson.h>
          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;

             mongoc_init ();

             /* Create our MongoDB Client */
             client = mongoc_client_new (
                "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");

             /* Do some work */
             /* TODO */

             /* Clean up */
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       TIP:
          Multiple  hostnames  can  be  specified  in the MongoDB connection string URI, with a comma separating
          hosts in the seed list.

          It is recommended to use a seed list of members of the replica set to allow the driver to  connect  to
          any node.

   Connecting to a Sharded Cluster
       To connect to a sharded cluster, specify the mongos nodes the client should connect to. The C Driver will
       automatically detect that it has connected to a mongos sharding server.

       If  more  than  one  hostname  is  specified, a seed list will be created to attempt failover between the
       mongos instances.

       WARNING:
          Specifying the replicaSet parameter when connecting to a mongos sharding server is invalid.

          #include <bson.h>
          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;

             mongoc_init ();

             /* Create our MongoDB Client */
             client = mongoc_client_new ("mongodb://myshard01:27017/");

             /* Do something with client ... */

             /* Free the client */
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

   Connecting to an IPv6 Address
       The MongoDB C Driver will automatically resolve IPv6 addresses from host names. However,  to  specify  an
       IPv6 address directly, wrap the address in [].

          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");

   Connecting to a UNIX Domain Socket
       On  UNIX-like  systems, the C Driver can connect directly to a MongoDB server using a UNIX domain socket.
       Pass the URL-encoded path to the socket, which must be suffixed with .sock. For example, to connect to  a
       domain socket at /tmp/mongodb-27017.sock:

          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");

       Include username and password like so:

          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");

   Connecting to a server over SSL
       These are instructions for configuring TLS/SSL connections.

       To run a server locally (on port 27017, for example):

          $ mongod --port 27017 --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem

       Add /?ssl=true to the end of a client URI.

          mongoc_client_t *client = NULL;
          client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true");

       MongoDB  requires  client certificates by default, unless the --sslAllowConnectionsWithoutCertificates is
       provided. The C Driver can be configured to present a client certificate using a mongoc_ssl_opt_t:

          const mongoc_ssl_opt_t *ssl_default = mongoc_ssl_opt_get_default ();
          mongoc_ssl_opt_t ssl_opts = { 0 };

          /* optionally copy in a custom trust directory or file; otherwise the default is used. */
          memcpy (&ssl_opts, ssl_default, sizeof ssl_opts);
          ssl_opts.pem_file = "client.pem"

          mongoc_client_set_ssl_opts (client, &ssl_opts);

       The client certificate provided by pem_file must be issued by  one  of  the  server  trusted  Certificate
       Authorities  listed  in --sslCAFile, or issued by a CA in the native certificate store on the server when
       omitted.

       To verify the server certificate against a specific CA, provide a PEM armored file with a CA certificate,
       or concatenated list of CA certificates using the ca_file option, or c_rehash directory structure of CAs,
       pointed to using the ca_dir option. When no ca_file or ca_dir  is  provided,  the  driver  will  use  CAs
       provided by the native platform certificate store.

       See mongoc_ssl_opt_t for more information on the various SSL related options.

   Compressing data to and from MongoDB
       MongoDB 3.4 added Snappy compression support, and zlib compression in 3.6.  To enable compression support
       the client must be configured with which compressors to use:

          mongoc_client_t *client = NULL;
          client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib");

       The  compressors option specifies the priority order of compressors the client wants to use. Messages are
       compressed if the client and server share any compressors in common.

       Note that the compressor used by the server might not be the same compressor as  the  client  used.   For
       example,  if  the  client  uses  the  connection  string compressors=zlib,snappy the client will use zlib
       compression to send data (if possible), but the server might still reply using snappy, depending  on  how
       the server was configured.

       The  driver  must be built with zlib and/or snappy support to enable compression support, any unknown (or
       not compiled in) compressor value will be ignored.

   Additional Connection Options
       The full list of connection options can be found in the mongoc_uri_t docs.

       Certain socket/connection related options are not configurable:
                      ┌───────────────┬──────────────────────────────┬────────────────────────┐
                      │ Option        │ Description                  │ Value                  │
                      ├───────────────┼──────────────────────────────┼────────────────────────┤
                      │ SO_KEEPALIVE  │ TCP Keep Alive               │ Enabled                │
                      ├───────────────┼──────────────────────────────┼────────────────────────┤
                      │ TCP_KEEPIDLE  │ How long a connection  needs │ 300 seconds            │
                      │               │ to  remain  idle  before TCP │                        │
                      │               │ starts   sending   keepalive │                        │
                      │               │ probes                       │                        │
                      ├───────────────┼──────────────────────────────┼────────────────────────┤
                      │ TCP_KEEPINTVL │ The  time in seconds between │ 10 seconds             │
                      │               │ TCP probes                   │                        │
                      ├───────────────┼──────────────────────────────┼────────────────────────┤
                      │ TCP_KEEPCNT   │ How  many  probes  to  send, │ 9 probes               │
                      │               │ without     acknowledgement, │                        │
                      │               │ before     dropping      the │                        │
                      │               │ connection                   │                        │
                      ├───────────────┼──────────────────────────────┼────────────────────────┤
                      │ TCP_NODELAY   │ Send   packets  as  soon  as │ Enabled (no buffering) │
                      │               │ possible  or  buffer   small │                        │
                      │               │ packets (Nagle algorithm)    │                        │
                      └───────────────┴──────────────────────────────┴────────────────────────┘

   Connection Pooling
       The  MongoDB  C  driver  has  two  connection  modes: single-threaded and pooled. Single-threaded mode is
       optimized for embedding the driver within languages like PHP. Multi-threaded programs should  use  pooled
       mode: this mode minimizes the total connection count, and in pooled mode a background thread monitors the
       MongoDB server topology, so the program need not block to scan it.

   Single Mode
       In single mode, your program creates a mongoc_client_t directly:

          mongoc_client_t *client = mongoc_client_new (
             "mongodb://hostA,hostB/?replicaSet=my_rs");

       The  client  connects  on  demand  when  your  program  first  uses  it  for a MongoDB operation. Using a
       non-blocking socket per server, it begins a check on each server concurrently, and uses the  asynchronous
       poll  or  select  function to receive events from the sockets, until all have responded or timed out. Put
       another way, in single-threaded mode the C Driver fans out to begin all checks concurrently, then fans in
       once all checks have completed or timed out. Once the scan completes, the client executes your  program's
       operation and returns.

       In  single  mode,  the client re-scans the server topology roughly once per minute. If more than a minute
       has elapsed since the previous scan, the next operation  on  the  client  will  block  while  the  client
       completes  its  scan.  This  interval is configurable with heartbeatFrequencyMS in the connection string.
       (See mongoc_uri_t.)

       A single client opens one connection per server in your topology: these connections  are  used  both  for
       scanning the topology and performing normal operations.

   Pooled Mode
       To activate pooled mode, create a mongoc_client_pool_t:

          mongoc_uri_t *uri = mongoc_uri_new (
             "mongodb://hostA,hostB/?replicaSet=my_rs");

          mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);

       When  your  program  first  calls  mongoc_client_pool_pop,  the  pool  launches  a  background thread for
       monitoring. The thread fans out and connects to all servers in the connection string, using  non-blocking
       sockets  and a simple event loop. As it receives ismaster responses from the servers, it updates its view
       of the server topology. Each time the thread discovers a new server it begins connecting to it, and  adds
       the new socket to the list of non-blocking sockets in the event loop.

       Each thread that executes MongoDB operations must check out a client from the pool:

          mongoc_client_t *client = mongoc_client_pool_pop (pool);

          /* use the client for operations ... */

          mongoc_client_pool_push (pool, client);

       The mongoc_client_t object is not thread-safe, only the mongoc_client_pool_t is.

       When  the  driver  is  in  pooled  mode,  your  program's  operations are unblocked as soon as monitoring
       discovers a usable server. For example, if a thread in your program is waiting to execute an "insert"  on
       the  primary,  it  is  unblocked  as  soon  as  the  primary  is  discovered, rather than waiting for all
       secondaries to be checked as well.

       The pool opens one connection per server for monitoring, and each client opens its own connection to each
       server it uses for application operations. The background thread re-scans  the  server  topology  roughly
       every  10 seconds. This interval is configurable with heartbeatFrequencyMS in the connection string. (See
       mongoc_uri_t.)

       See connection_pool_options to configure pool size and behavior,  and  see  mongoc_client_pool_t  for  an
       extended example of a multi-threaded program that uses the driver in pooled mode.

   Cursors
   Handling Cursor Failures
       Cursors  exist  on  a  MongoDB  server.  However, the mongoc_cursor_t structure gives the local process a
       handle to the cursor. It is possible for errors to occur on the server while iterating a  cursor  on  the
       client.  Even  a  network  partition may occur. This means that applications should be robust in handling
       cursor failures.

       While iterating cursors, you should check to see if an error has occurred. See the following example  for
       how to robustly check for errors.

          static void
          print_all_documents (mongoc_collection_t *collection)
          {
             mongoc_cursor_t *cursor;
             const bson_t *doc;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             char *str;

             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);

             while (mongoc_cursor_next (cursor, &doc)) {
                str = bson_as_canonical_extended_json (doc, NULL);
                printf ("%s\n", str);
                bson_free (str);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
             }

             mongoc_cursor_destroy (cursor);
          }

   Destroying Server-Side Cursors
       The  MongoDB  C  driver  will  automatically destroy a server-side cursor when mongoc_cursor_destroy() is
       called. Failure to call this function when done with a cursor will leak memory client  side  as  well  as
       consume  extra memory server side. If the cursor was configured to never timeout, it will become a memory
       leak on the server.

   Tailable Cursors
       Tailable cursors are cursors that remain open even after they've returned a final result.  This  way,  if
       more  documents  are  added  to a collection (i.e., to the cursor's result set), then you can continue to
       call mongoc_cursor_next() to retrieve those additional results.

       Here's a complete test case that demonstrates the use of tailable cursors.

       NOTE:
          Tailable cursors are for capped collections only.

       An example to tail the oplog from a replica set.  mongoc-tail.c.INDENT 0.0

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>
          #include <stdlib.h>

          #ifdef _WIN32
          #define sleep(_n) Sleep ((_n) *1000)
          #endif

          static void
          print_bson (const bson_t *b)
          {
             char *str;

             str = bson_as_canonical_extended_json (b, NULL);
             fprintf (stdout, "%s\n", str);
             bson_free (str);
          }

          static mongoc_cursor_t *
          query_collection (mongoc_collection_t *collection, uint32_t last_time)
          {
             mongoc_cursor_t *cursor;
             bson_t query;
             bson_t gt;
             bson_t opts;

             BSON_ASSERT (collection);

             bson_init (&query);
             BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", &gt);
             BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
             bson_append_document_end (&query, &gt);

             bson_init (&opts);
             BSON_APPEND_BOOL (&opts, "tailable", true);
             BSON_APPEND_BOOL (&opts, "awaitData", true);

             cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);

             bson_destroy (&query);
             bson_destroy (&opts);

             return cursor;
          }

          static void
          tail_collection (mongoc_collection_t *collection)
          {
             mongoc_cursor_t *cursor;
             uint32_t last_time;
             const bson_t *doc;
             bson_error_t error;
             bson_iter_t iter;

             BSON_ASSERT (collection);

             last_time = (uint32_t) time (NULL);

             while (true) {
                cursor = query_collection (collection, last_time);
                while (!mongoc_cursor_error (cursor, &error) &&
                       mongoc_cursor_more (cursor)) {
                   if (mongoc_cursor_next (cursor, &doc)) {
                      if (bson_iter_init_find (&iter, doc, "ts") &&
                          BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
                         bson_iter_timestamp (&iter, &last_time, NULL);
                      }
                      print_bson (doc);
                   }
                }
                if (mongoc_cursor_error (cursor, &error)) {
                   if (error.domain == MONGOC_ERROR_SERVER) {
                      fprintf (stderr, "%s\n", error.message);
                      exit (1);
                   }
                }

                mongoc_cursor_destroy (cursor);
                sleep (1);
             }
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_collection_t *collection;
             mongoc_client_t *client;

             if (argc != 2) {
                fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
                return EXIT_FAILURE;
             }

             mongoc_init ();

             client = mongoc_client_new (argv[1]);
             if (!client) {
                fprintf (stderr, "Invalid URI: \"%s\"\n", argv[1]);
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api (client, 2);

             collection = mongoc_client_get_collection (client, "local", "oplog.rs");

             tail_collection (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             return 0;
          }
          $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
          {
              "h" : -8458503739429355503,
              "ns" : "test.test",
              "o" : {
                  "_id" : {
                      "$oid" : "5372ab0a25164be923d10d50"
                  }
              },
              "op" : "i",
              "ts" : {
                  "$timestamp" : {
                      "i" : 1,
                      "t" : 1400023818
                  }
              },
              "v" : 2
          }

       The line of output is a sample from performing db.test.insert({}) from the mongo  shell  on  the  replica
       set.

       See also mongoc_cursor_set_max_await_time_ms.

   Bulk Write Operations
       This tutorial explains how to take advantage of MongoDB C driver bulk write operation features. Executing
       write operations in batches reduces the number of network round trips, increasing write throughput.

   Bulk Insert
       First we need to fetch a bulk operation handle from the mongoc_collection_t.

          mongoc_bulk_operation_t *bulk =
             mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

       We  can  now start inserting documents to the bulk operation. These will be buffered until we execute the
       operation.

       The  bulk  operation  will  coalesce  insertions  as  a  single  batch  for  each  consecutive  call   to
       mongoc_bulk_operation_insert(). This creates a pipelined effect when possible.

       To   execute  the  bulk  operation  and  receive  the  result  we  call  mongoc_bulk_operation_execute().
       bulk1.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk1 (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;
             int i;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             for (i = 0; i < 10000; i++) {
                doc = BCON_NEW ("i", BCON_INT32 (i));
                mongoc_bulk_operation_insert (bulk, doc);
                bson_destroy (doc);
             }

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                fprintf (stderr, "Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk1-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk1 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document:

          {"nInserted"   : 10000,
           "nMatched"    : 0,
           "nModified"   : 0,
           "nRemoved"    : 0,
           "nUpserted"   : 0,
           "writeErrors" : []
           "writeConcernErrors" : [] }

   Mixed Bulk Write Operations
       MongoDB C driver also supports executing mixed bulk write operations. A  batch  of  insert,  update,  and
       remove operations can be executed together using the bulk write operations API.

   Ordered Bulk Write Operations
       Ordered  bulk  write  operations  are  batched  and  sent  to the server in the order provided for serial
       execution. The reply document describes the type and count of operations performed.  bulk2.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk2 (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *query;
             bson_t *doc;
             bson_t *opts;
             bson_t reply;
             char *str;
             bool ret;
             int i;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             /* Remove everything */
             query = bson_new ();
             mongoc_bulk_operation_remove (bulk, query);
             bson_destroy (query);

             /* Add a few documents */
             for (i = 1; i < 4; i++) {
                doc = BCON_NEW ("_id", BCON_INT32 (i));
                mongoc_bulk_operation_insert (bulk, doc);
                bson_destroy (doc);
             }

             /* {_id: 1} => {$set: {foo: "bar"}} */
             query = BCON_NEW ("_id", BCON_INT32 (1));
             doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
             bson_destroy (query);
             bson_destroy (doc);

             /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
             opts = BCON_NEW ("upsert", BCON_BOOL (true));
             query = BCON_NEW ("_id", BCON_INT32 (4));
             doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
             bson_destroy (query);
             bson_destroy (doc);
             bson_destroy (opts);

             /* replace {j:1} with {j:2} */
             query = BCON_NEW ("j", BCON_INT32 (1));
             doc = BCON_NEW ("j", BCON_INT32 (2));
             mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
             bson_destroy (query);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk2-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk2 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document:

          { "nInserted"   : 3,
            "nMatched"    : 2,
            "nModified"   : 2,
            "nRemoved"    : 10000,
            "nUpserted"   : 1,
            "upserted"    : [{"index" : 5, "_id" : 4}],
            "writeErrors" : []
            "writeConcernErrors" : [] }

       The index field in the upserted array is the 0-based index of the upsert operation; in this example,  the
       sixth operation of the overall bulk operation was an upsert, so its index is 5.

   Unordered Bulk Write Operations
       Unordered  bulk  write operations are batched and sent to the server in arbitrary order where they may be
       executed in parallel. Any errors that occur are reported after all operations are attempted.

       In the next example the first and third operations fail due to the unique constraint on _id. Since we are
       doing unordered execution the second and fourth operations succeed.  bulk3.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk3 (mongoc_collection_t *collection)
          {
             bson_t opts = BSON_INITIALIZER;
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *query;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             /* false indicates unordered */
             BSON_APPEND_BOOL (&opts, "ordered", false);
             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
             bson_destroy (&opts);

             /* Add a document */
             doc = BCON_NEW ("_id", BCON_INT32 (1));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* remove {_id: 2} */
             query = BCON_NEW ("_id", BCON_INT32 (2));
             mongoc_bulk_operation_remove_one (bulk, query);
             bson_destroy (query);

             /* insert {_id: 3} */
             doc = BCON_NEW ("_id", BCON_INT32 (3));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* replace {_id:4} {'i': 1} */
             query = BCON_NEW ("_id", BCON_INT32 (4));
             doc = BCON_NEW ("i", BCON_INT32 (1));
             mongoc_bulk_operation_replace_one (bulk, query, doc, false);
             bson_destroy (query);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
             bson_destroy (&opts);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk3-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk3 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document:

          { "nInserted"    : 0,
            "nMatched"     : 1,
            "nModified"    : 1,
            "nRemoved"     : 1,
            "nUpserted"    : 0,
            "writeErrors"  : [
              { "index"  : 0,
                "code"   : 11000,
                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
              { "index"  : 2,
                "code"   : 11000,
                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
            "writeConcernErrors" : [] }

          Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }

       The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.

   Bulk Operation Bypassing Document Validation
       This feature is only available when using MongoDB 3.2 and later.

       By default bulk operations are validated against the schema, if any is defined. In certain cases  however
       it may be necessary to bypass the document validation.  bulk5.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk5_fail (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             /* Two inserts */
             doc = BCON_NEW ("_id", BCON_INT32 (31));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_INT32 (32));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* The above documents do not comply to the schema validation rules
              * we created previously, so this will result in an error */
             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          static void
          bulk5_success (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             /* Allow this document to bypass document validation.
              * NOTE: When authentication is enabled, the authenticated user must have
              * either the "dbadmin" or "restore" roles to bypass document validation */
             mongoc_bulk_operation_set_bypass_document_validation (bulk, true);

             /* Two inserts */
             doc = BCON_NEW ("_id", BCON_INT32 (31));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_INT32 (32));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             bson_t *options;
             bson_error_t error;
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_database_t *database;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk5-example");
             mongoc_client_set_error_api (client, 2);
             database = mongoc_client_get_database (client, "testasdf");

             /* Create schema validator */
             options = BCON_NEW (
                "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
             collection =
                mongoc_database_create_collection (database, "collname", options, &error);

             if (collection) {
                bulk5_fail (collection);
                bulk5_success (collection);
                mongoc_collection_destroy (collection);
             } else {
                fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
             }

             bson_free (options);
             mongoc_database_destroy (database);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }
          { "nInserted" : 0,
            "nMatched" : 0,
            "nModified" : 0,
            "nRemoved" : 0,
            "nUpserted" : 0,
            "writeErrors" : [
              { "index" : 0,
                "code" : 121,
                "errmsg" : "Document failed validation" } ] }

          Error: Document failed validation

          { "nInserted" : 2,
            "nMatched" : 0,
            "nModified" : 0,
            "nRemoved" : 0,
            "nUpserted" : 0,
            "writeErrors" : [] }

       The bson_error_t domain is MONGOC_ERROR_COMMAND.

   Bulk Operation Write Concerns
       By  default  bulk  operations  are  executed  with  the write_concern of the collection they are executed
       against. A custom write concern can be passed to the  mongoc_collection_create_bulk_operation_with_opts()
       method.  Write  concern  errors  (e.g.  wtimeout)  will  be  reported after all operations are attempted,
       regardless of execution order.  bulk4.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk4 (mongoc_collection_t *collection)
          {
             bson_t opts = BSON_INITIALIZER;
             mongoc_write_concern_t *wc;
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             wc = mongoc_write_concern_new ();
             mongoc_write_concern_set_w (wc, 4);
             mongoc_write_concern_set_wtimeout (wc, 100); /* milliseconds */
             mongoc_write_concern_append (wc, &opts);

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);

             /* Two inserts */
             doc = BCON_NEW ("_id", BCON_INT32 (10));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_INT32 (11));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
             mongoc_write_concern_destroy (wc);
             bson_destroy (&opts);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk4-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk4 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document and error message:

          { "nInserted"    : 2,
            "nMatched"     : 0,
            "nModified"    : 0,
            "nRemoved"     : 0,
            "nUpserted"    : 0,
            "writeErrors"  : [],
            "writeConcernErrors" : [
              { "code"   : 64,
                "errmsg" : "waiting for replication timed out" }
          ] }

          Error: waiting for replication timed out

       The bson_error_t domain is MONGOC_ERROR_WRITE_CONCERN if there are write  concern  errors  and  no  write
       errors. Write errors indicate failed operations, so they take precedence over write concern errors, which
       mean merely that the write concern is not satisfied yet.

   Setting Collation Order
       This feature is only available when using MongoDB 3.4 and later.  bulk-collation.c.INDENT 0.0

          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk_collation (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_t *opts;
             bson_t *doc;
             bson_t *selector;
             bson_t *update;
             bson_error_t error;
             bson_t reply;
             char *str;
             uint32_t ret;

             /* insert {_id: "one"} and {_id: "One"} */
             bulk = mongoc_collection_create_bulk_operation_with_opts (
                collection, NULL);
             doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* "One" normally sorts before "one"; make "one" come first */
             opts = BCON_NEW ("collation",
                              "{",
                              "locale",
                              BCON_UTF8 ("en_US"),
                              "caseFirst",
                              BCON_UTF8 ("lower"),
                              "}");

             /* set x=1 on the document with _id "One", which now sorts after "one" */
             update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
             selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
             mongoc_bulk_operation_update_one_with_opts (
                bulk, selector, update, opts, &error);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             bson_destroy (update);
             bson_destroy (selector);
             bson_destroy (opts);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk-collation");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "db", "collection");
             bulk_collation (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }
          { "nInserted" : 2,
             "nMatched" : 1,
             "nModified" : 1,
             "nRemoved" : 0,
             "nUpserted" : 0,
             "writeErrors" : [  ]
          }

   Unacknowledged Bulk Writes
       Set  "w"  to  zero  for  an unacknowledged write. The driver sends unacknowledged writes using the legacy
       opcodes OP_INSERT, OP_UPDATE, and OP_DELETE.  bulk6.c.INDENT 0.0

          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk6 (mongoc_collection_t *collection)
          {
             bson_t opts = BSON_INITIALIZER;
             mongoc_write_concern_t *wc;
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t *selector;
             bson_t reply;
             char *str;
             bool ret;

             wc = mongoc_write_concern_new ();
             mongoc_write_concern_set_w (wc, 0);
             mongoc_write_concern_append (wc, &opts);

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);

             doc = BCON_NEW ("_id", BCON_INT32 (10));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             selector = BCON_NEW ("_id", BCON_INT32 (11));
             mongoc_bulk_operation_remove_one (bulk, selector);
             bson_destroy (selector);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
             mongoc_write_concern_destroy (wc);
             bson_destroy (&opts);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk6-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk6 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

The reply document is empty:

          { }

   Further Reading
       See the Driver Bulk API Spec, which describes bulk write operations for all MongoDB drivers.

   Aggregation Framework Examples
       This document provides a number of practical examples that display the capabilities  of  the  aggregation
       framework.

       The Aggregations using the Zip Codes Data Set examples uses a publicly available data set of all zipcodes
       and populations in the United States. These data are available at: zips.json.

   Requirements
       Let's check if everything is installed.

       Use the following command to load zips.json data set into mongod instance:

          $ mongoimport --drop -d test -c zipcodes zips.json

       Let's use the MongoDB shell to verify that everything was imported successfully.

          $ mongo test
          MongoDB shell version: 2.6.1
          connecting to: test
          > db.zipcodes.count()
          29467
          > db.zipcodes.findOne()
          {
                "_id" : "35004",
                "city" : "ACMAR",
                "loc" : [
                        -86.51557,
                        33.584132
                ],
                "pop" : 6055,
                "state" : "AL"
          }

   Aggregations using the Zip Codes Data Set
       Each document in this collection has the following form:

          {
            "_id" : "35004",
            "city" : "Acmar",
            "state" : "AL",
            "pop" : 6055,
            "loc" : [-86.51557, 33.584132]
          }

       In these documents:

       • The _id field holds the zipcode as a string.

       • The city field holds the city name.

       • The state field holds the two letter state abbreviation.

       • The pop field holds the population.

       • The loc field holds the location as a [latitude, longitude] array.

   States with Populations Over 10 Million
       To  get  all  states  with  a population greater than 10 million, use the following aggregation pipeline:
       aggregation1.c.INDENT 0.0

          #include <mongoc.h>
          #include <stdio.h>

          static void
          print_pipeline (mongoc_collection_t *collection)
          {
             mongoc_cursor_t *cursor;
             bson_error_t error;
             const bson_t *doc;
             bson_t *pipeline;
             char *str;

             pipeline = BCON_NEW ("pipeline",
                                  "[",
                                  "{",
                                  "$group",
                                  "{",
                                  "_id",
                                  "$state",
                                  "total_pop",
                                  "{",
                                  "$sum",
                                  "$pop",
                                  "}",
                                  "}",
                                  "}",
                                  "{",
                                  "$match",
                                  "{",
                                  "total_pop",
                                  "{",
                                  "$gte",
                                  BCON_INT32 (10000000),
                                  "}",
                                  "}",
                                  "}",
                                  "]");

             cursor = mongoc_collection_aggregate (
                collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);

             while (mongoc_cursor_next (cursor, &doc)) {
                str = bson_as_canonical_extended_json (doc, NULL);
                printf ("%s\n", str);
                bson_free (str);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "Cursor Failure: %s\n", error.message);
             }

             mongoc_cursor_destroy (cursor);
             bson_destroy (pipeline);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new (
                "mongodb://localhost:27017?appname=aggregation-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "zipcodes");

             print_pipeline (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }
          { "_id" : "PA", "total_pop" : 11881643 }
          { "_id" : "OH", "total_pop" : 10847115 }
          { "_id" : "NY", "total_pop" : 17990455 }
          { "_id" : "FL", "total_pop" : 12937284 }
          { "_id" : "TX", "total_pop" : 16986510 }
          { "_id" : "IL", "total_pop" : 11430472 }
          { "_id" : "CA", "total_pop" : 29760021 }

       The above aggregation pipeline is build from two pipeline operators: $group and $match.

       The $group pipeline operator requires _id field where we specify grouping; remaining fields  specify  how
       to  generate  composite  value  and  must  use one of the group aggregation functions: $addToSet, $first,
       $last, $max, $min, $avg, $push, $sum. The $match pipeline  operator  syntax  is  the  same  as  the  read
       operation query syntax.

       The $group process reads all documents and for each state it creates a separate document, for example:

          { "_id" : "WA", "total_pop" : 4866692 }

       The  total_pop field uses the $sum aggregation function to sum the values of all pop fields in the source
       documents.

       Documents created by $group are piped to the $match pipeline operator. It returns the documents with  the
       value of total_pop field greater than or equal to 10 million.

   Average City Population by State
       To  get  the  first  three  states  with  the  greatest  average  population  per city, use the following
       aggregation:

          pipeline = BCON_NEW ("pipeline", "[",
             "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
             "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
             "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
             "{", "$limit", BCON_INT32 (3) "}",
          "]");

       This aggregate pipeline produces:

          { "_id" : "DC", "avg_city_pop" : 303450.0 }
          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
          { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }

       The above aggregation pipeline is build from three pipeline operators: $group, $sort and $limit.

       The first $group operator creates the following documents:

          { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }

       Note, that the $group operator can't use nested documents except the _id field.

       The second $group uses these documents to create the following documents:

          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }

       These documents are sorted by the avg_city_pop field in descending order. Finally,  the  $limit  pipeline
       operator returns the first 3 documents from the sorted set.

   distinct and mapReduce
       This  document  provides  some  practical,  simple,  examples  to  demonstrate the distinct and mapReduce
       commands.

   Setup
       First we'll write some code to insert sample data: doc-common-insert.c.INDENT 0.0

          /* Don't try to compile this file on its own. It's meant to be #included
             by example code */

          /* Insert some sample data */
          bool
          insert_data (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             enum N { ndocs = 4 };
             bson_t *docs[ndocs];
             bson_error_t error;
             int i = 0;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
             docs[2] = BCON_NEW (
                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");

             for (i = 0; i < ndocs; i++) {
                mongoc_bulk_operation_insert (bulk, docs[i]);
                bson_destroy (docs[i]);
                docs[i] = NULL;
             }

             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);

             if (!ret) {
                fprintf (stderr, "Error inserting data: %s\n", error.message);
             }

             mongoc_bulk_operation_destroy (bulk);
             return ret;
          }

          /* A helper which we'll use a lot later on */
          void
          print_res (const bson_t *reply)
          {
             BSON_ASSERT (reply);
             char *str = bson_as_canonical_extended_json (reply, NULL);
             printf ("%s\n", str);
             bson_free (str);
          }

   distinct command
       This is how to use the distinct command to get the distinct  values  of  x  which  are  greater  than  1:
       distinct.c.INDENT 0.0

          bool
          distinct (mongoc_database_t *database)
          {
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;
             bson_iter_t iter;
             bson_iter_t array_iter;
             double val;

             command = BCON_NEW ("distinct",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "key",
                                 BCON_UTF8 ("x"),
                                 "query",
                                 "{",
                                 "x",
                                 "{",
                                 "$gt",
                                 BCON_DOUBLE (1.0),
                                 "}",
                                 "}");
             res =
                mongoc_database_command_simple (database, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with distinct: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with reply (in this case iterate through the values) */
             if (!(bson_iter_init_find (&iter, &reply, "values") &&
                   BSON_ITER_HOLDS_ARRAY (&iter) &&
                   bson_iter_recurse (&iter, &array_iter))) {
                fprintf (stderr, "Couldn't extract \"values\" field from response\n");
                goto cleanup;
             }

             while (bson_iter_next (&array_iter)) {
                if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
                   val = bson_iter_double (&array_iter);
                   printf ("Next double: %f\n", val);
                }
             }

          cleanup:
             /* cleanup */
             bson_destroy (command);
             bson_destroy (&reply);
             return res;
          }

   mapReduce - basic example
       A  simple  example  using  the  map reduce framework. It simply adds up the number of occurrences of each
       "tag".

       First define the map and reduce functions: constants.c.INDENT 0.0

          const char *const COLLECTION_NAME = "things";

          /* Our map function just emits a single (key, 1) pair for each tag
             in the array: */
          const char *const MAPPER = "function () {"
                                     "this.tags.forEach(function(z) {"
                                     "emit(z, 1);"
                                     "});"
                                     "}";

          /* The reduce function sums over all of the emitted values for a
             given key: */
          const char *const REDUCER = "function (key, values) {"
                                      "var total = 0;"
                                      "for (var i = 0; i < values.length; i++) {"
                                      "total += values[i];"
                                      "}"
                                      "return total;"
                                      "}";
          /* Note We can't just return values.length as the reduce function
             might be called iteratively on the results of other reduce
             steps. */

Run the mapReduce command: map-reduce-basic.c.INDENT 0.0

          bool
          map_reduce_basic (mongoc_database_t *database)
          {
             bson_t reply;
             bson_t *command;
             bool res;
             bson_error_t error;
             mongoc_cursor_t *cursor;
             const bson_t *doc;

             bool map_reduce_done = false;
             bool query_done = false;

             const char *out_collection_name = "outCollection";
             mongoc_collection_t *out_collection;

             /* Empty find query */
             bson_t find_query = BSON_INITIALIZER;

             /* Construct the mapReduce command */

             /* Other arguments can also be specified here, like "query" or
                "limit" and so on */
             command = BCON_NEW ("mapReduce",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "map",
                                 BCON_CODE (MAPPER),
                                 "reduce",
                                 BCON_CODE (REDUCER),
                                 "out",
                                 BCON_UTF8 (out_collection_name));
             res =
                mongoc_database_command_simple (database, command, NULL, &reply, &error);
             map_reduce_done = true;

             if (!res) {
                fprintf (stderr, "MapReduce failed: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply (it doesn't contain the mapReduce results) */
             print_res (&reply);

             /* Now we'll query outCollection to see what the results are */
             out_collection =
                mongoc_database_get_collection (database, out_collection_name);
             cursor = mongoc_collection_find_with_opts (
                out_collection, &find_query, NULL, NULL);
             query_done = true;

             /* Do something with the results */
             while (mongoc_cursor_next (cursor, &doc)) {
                print_res (doc);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "ERROR: %s\n", error.message);
                res = false;
                goto cleanup;
             }

          cleanup:
             /* cleanup */
             if (query_done) {
                mongoc_cursor_destroy (cursor);
                mongoc_collection_destroy (out_collection);
             }

             if (map_reduce_done) {
                bson_destroy (&reply);
                bson_destroy (command);
             }

             return res;
          }

   mapReduce - more complicated example
       You must have replica set running for this.

       In this example we contact a secondary in the replica set and do an "inline" map reduce, so  the  results
       are returned immediately: map-reduce-advanced.c.INDENT 0.0

          bool
          map_reduce_advanced (mongoc_database_t *database)
          {
             bson_t *command;
             bson_error_t error;
             bool res = true;
             mongoc_cursor_t *cursor;
             mongoc_read_prefs_t *read_pref;
             const bson_t *doc;

             /* Construct the mapReduce command */
             /* Other arguments can also be specified here, like "query" or "limit"
                and so on */

             /* Read the results inline from a secondary replica */
             command = BCON_NEW ("mapReduce",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "map",
                                 BCON_CODE (MAPPER),
                                 "reduce",
                                 BCON_CODE (REDUCER),
                                 "out",
                                 "{",
                                 "inline",
                                 "1",
                                 "}");

             read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
             cursor = mongoc_database_command (
                database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);

             /* Do something with the results */
             while (mongoc_cursor_next (cursor, &doc)) {
                print_res (doc);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "ERROR: %s\n", error.message);
                res = false;
             }

             mongoc_cursor_destroy (cursor);
             mongoc_read_prefs_destroy (read_pref);
             bson_destroy (command);

             return res;
          }

   Running the Examples
       Here's how to run the example code basic-aggregation.c.INDENT 0.0

          /*
           * Copyright 2016 MongoDB, Inc.
           *
           * Licensed under the Apache License, Version 2.0 (the "License");
           * you may not use this file except in compliance with the License.
           * You may obtain a copy of the License at
           *
           *   http://www.apache.org/licenses/LICENSE-2.0
           *
           * Unless required by applicable law or agreed to in writing, software
           * distributed under the License is distributed on an "AS IS" BASIS,
           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           * See the License for the specific language governing permissions and
           * limitations under the License.
           */

          #include <mongoc.h>
          #include <stdio.h>

          #include "constants.c"

          #include "../doc-common-insert.c"
          #include "distinct.c"
          #include "map-reduce-basic.c"
          #include "map-reduce-advanced.c"

          int
          main (int argc, char *argv[])
          {
             mongoc_database_t *database = NULL;
             mongoc_client_t *client = NULL;
             mongoc_collection_t *collection = NULL;
             char *host_and_port = NULL;
             int res = 0;

             if (argc != 2) {
                fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
                fprintf (stderr,
                         "the connection string can be of the following forms:\n");
                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
                fprintf (stderr,
                         "mongodb://user:pass@localhost:27017\t"
                         "local machine on port 27017, and authenticate with username "
                         "user and password pass\n");
                return 1;
             }

             mongoc_init ();

             if (strncmp (argv[1], "mongodb://", 10) == 0) {
                host_and_port = bson_strdup (argv[1]);
             } else {
                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
             }

             client = mongoc_client_new (host_and_port);

             if (!client) {
                fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port);
                res = 2;
                goto cleanup;
             }

             mongoc_client_set_error_api (client, 2);
             database = mongoc_client_get_database (client, "test");
             collection = mongoc_database_get_collection (database, COLLECTION_NAME);

             printf ("Inserting data\n");
             if (!insert_data (collection)) {
                res = 3;
                goto cleanup;
             }

             printf ("distinct\n");
             if (!distinct (database)) {
                res = 4;
                goto cleanup;
             }

             printf ("map reduce\n");
             if (!map_reduce_basic (database)) {
                res = 5;
                goto cleanup;
             }

             printf ("more complicated map reduce\n");
             if (!map_reduce_advanced (database)) {
                res = 6;
                goto cleanup;
             }

          cleanup:
             if (collection) {
                mongoc_collection_destroy (collection);
             }

             if (database) {
                mongoc_database_destroy (database);
             }

             if (client) {
                mongoc_client_destroy (client);
             }

             if (host_and_port) {
                bson_free (host_and_port);
             }

             mongoc_cleanup ();
             return res;
          }
to do this can be found here).
          $ mongod

       Now compile and run the example program:

          $ cd examples/basic_aggregation/
          $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./agg-example localhost

          Inserting data
          distinct
          Next double: 2.000000
          Next double: 3.000000
          map reduce
          { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
          { "_id" : "cat", "value" : 63 }
          { "_id" : "dog", "value" : 42 }
          { "_id" : "mouse", "value" : 21 }
          more complicated map reduce
          { "results" : [ { "_id" : "cat", "value" : 63 }, { "_id" : "dog", "value" : 42 }, { "_id" : "mouse", "value" : 21 } ], "timeMillis" : 14, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }

   Using libmongoc in a Microsoft Visual Studio project
       Download and install libmongoc on your system, then open Visual Studio, select "File→New→Project...", and
       create a new Win32 Console Application.  [image]

       Remember to switch the platform from 32-bit to 64-bit: [image]

       Right-click on your console application in the Solution Explorer and select "Properties". Choose to  edit
       properties  for  "All  Configurations",  expand  the  "C/C++"  options  and  choose "General". Add to the
       "Additional Include Directories" these paths:

          C:\mongo-c-driver\include\libbson-1.0
          C:\mongo-c-driver\include\libmongoc-1.0
       [image]

       (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your include paths will be different.)

       Also in the Properties dialog, expand the "Linker" options and choose "Input", and add to the "Additional
       Dependencies" these libraries:

          C:\mongo-c-driver\lib\bson-1.0.lib
          C:\mongo-c-driver\lib\mongoc-1.0.lib
       [image]

       Adding these libraries as dependencies provides linker symbols to build your application, but to actually
       run it, libbson's and libmongoc's DLLs must be  in  your  executable  path.  Select  "Debugging"  in  the
       Properties dialog, and set the "Environment" option to:

          PATH=c:/mongo-c-driver/bin
       [image]

       Finally, include "mongoc.h" in your project's "stdafx.h":

          #include <mongoc.h>

   Static linking
       Following  the  instructions  above,  you  have  dynamically  linked  your application to the libbson and
       libmongoc DLLs. This is usually the right choice. If you want to link  statically  instead,  update  your
       "Additional  Dependencies" list by removing bson-1.0.lib and mongoc-1.0.lib and replacing them with these
       libraries:

          C:\mongo-c-driver\lib\bson-static-1.0.lib
          C:\mongo-c-driver\lib\mongoc-static-1.0.lib
          ws2_32.lib
          Secur32.lib
          Crypt32.lib
          BCrypt.lib
       [image]

       (To explain the purpose  of  each  library:  bson-static-1.0.lib  and  mongoc-static-1.0.lib  are  static
       archives  of  the  driver  code.  The socket library ws2_32 is required by libbson, which uses the socket
       routine gethostname to help guarantee ObjectId uniqueness. The BCrypt library is used  by  libmongoc  for
       SSL  connections  to  MongoDB, and Secur32 and Crypt32 are required for enterprise authentication methods
       like Kerberos.)

       Finally, define two preprocessor symbols before including mongoc.h in your stdafx.h:

          #define BSON_STATIC
          #define MONGOC_STATIC
          #include <mongoc.h>

       Making these changes to your  project  is  only  required  for  static  linking;  for  most  people,  the
       dynamic-linking instructions above are preferred.

   Next Steps
       Now  you  can  build  and  debug applications in Visual Studio that use libbson and libmongoc. Proceed to
       making-a-connection in the tutorial to learn how connect to MongoDB and perform operations.

   Creating Indexes
       To   create   indexes   on   a   MongoDB   collection,   execute   the   createIndexes    command    with
       mongoc_database_write_command_with_opts.  See  the MongoDB Manual entry for the createIndexes command for
       details.

   Example
       example-create-indexes.c.INDENT 0.0

          /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
           * --libs libmongoc-1.0) */

          /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */

          #include <mongoc.h>
          #include <stdio.h>
          #include <stdlib.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_database_t *db;
             const char *uristr = "mongodb://127.0.0.1/?appname=create-indexes-example";
             const char *collection_name = "test";
             bson_t keys;
             char *index_name;
             bson_t *create_indexes;
             bson_t reply;
             char *reply_str;
             bson_error_t error;
             bool r;

             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             if (argc > 2) {
                collection_name = argv[2];
             }

             client = mongoc_client_new (uristr);

             if (!client) {
                fprintf (stderr, "Failed to parse URI.\n");
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api (client, 2);
             db = mongoc_client_get_database (client, "test");

             /* ascending index on field "x" */
             bson_init (&keys);
             BSON_APPEND_INT32 (&keys, "x", 1);
             index_name = mongoc_collection_keys_to_index_string (&keys);
             create_indexes = BCON_NEW ("createIndexes",
                                        BCON_UTF8 (collection_name),
                                        "indexes",
                                        "[",
                                        "{",
                                        "key",
                                        BCON_DOCUMENT (&keys),
                                        "name",
                                        BCON_UTF8 (index_name),
                                        "}",
                                        "]");

             r = mongoc_database_write_command_with_opts (
                db, create_indexes, NULL /* opts */, &reply, &error);

             reply_str = bson_as_json (&reply, NULL);
             printf ("%s\n", reply_str);

             if (!r) {
                fprintf (stderr, "Error in createIndexes: %s\n", error.message);
             }

             bson_free (index_name);
             bson_free (reply_str);
             bson_destroy (&reply);
             bson_destroy (create_indexes);
             mongoc_database_destroy (db);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return r ? EXIT_SUCCESS : EXIT_FAILURE;
          }

   API Reference
   Initialization and cleanup
   Synopsis
       Initialize the MongoDB C Driver by calling mongoc_init exactly once at the beginning of your program.  It
       is responsible for initializing global state such as process counters, SSL, and threading primitives.

       Call  mongoc_cleanup  exactly  once  at the end of your program to release all memory and other resources
       allocated by the driver. You must not call any other MongoDB C  Driver  functions  after  mongoc_cleanup.
       Note that mongoc_init does not reinitialize the driver after mongoc_cleanup.

   Deprecated feature: automatic initialization and cleanup
       On  some  platforms the driver can automatically call mongoc_init before main, and call mongoc_cleanup as
       the process exits. This is problematic in situations where related libraries also execute cleanup code on
       shutdown, and it creates inconsistent rules across platforms. Therefore the automatic initialization  and
       cleanup feature is deprecated, and will be dropped in version 2.0. Meanwhile, for backward compatibility,
       the feature is enabled by default on platforms where it is available.

       For  portable,  future-proof code, always call mongoc_init and mongoc_cleanup yourself, and configure the
       driver like:

          ./configure --disable-automatic-init-and-cleanup

       Or with CMake:

          cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO

   Logging
       MongoDB C driver Logging Abstraction

   Synopsis
          typedef enum {
             MONGOC_LOG_LEVEL_ERROR,
             MONGOC_LOG_LEVEL_CRITICAL,
             MONGOC_LOG_LEVEL_WARNING,
             MONGOC_LOG_LEVEL_MESSAGE,
             MONGOC_LOG_LEVEL_INFO,
             MONGOC_LOG_LEVEL_DEBUG,
             MONGOC_LOG_LEVEL_TRACE,
          } mongoc_log_level_t;

          #define MONGOC_ERROR(...)
          #define MONGOC_CRITICAL(...)
          #define MONGOC_WARNING(...)
          #define MONGOC_MESSAGE(...)
          #define MONGOC_INFO(...)
          #define MONGOC_DEBUG(...)

          typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
                                             const char *log_domain,
                                             const char *message,
                                             void *user_data);

          void
          mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
          void
          mongoc_log (mongoc_log_level_t log_level,
                      const char *log_domain,
                      const char *format,
                      ...) BSON_GNUC_PRINTF (3, 4);
          const char *
          mongoc_log_level_str (mongoc_log_level_t log_level);
          void
          mongoc_log_default_handler (mongoc_log_level_t log_level,
                                      const char *log_domain,
                                      const char *message,
                                      void *user_data);
          void
          mongoc_log_trace_enable (void);
          void
          mongoc_log_trace_disable (void);

       The MongoDB C driver comes with an abstraction for logging that you  can  use  in  your  application,  or
       integrate with an existing logging system.

   Macros
       To make logging a little less painful, various helper macros are provided. See the following example.

          #undef MONGOC_LOG_DOMAIN
          #define MONGOC_LOG_DOMAIN "my-custom-domain"

          MONGOC_WARNING ("An error occurred: %s", strerror (errno));

   Custom Log Handlers
       The default log handler prints a timestamp and the log message to stdout, or to stderr for warnings,
       critical messages, and errors.
              You  can override the handler with mongoc_log_set_handler().  Your handler function is called in a
              mutex for thread safety.

       For example, you could register a custom handler to suppress messages at INFO level and below:

          void
          my_logger (mongoc_log_level_t log_level,
                     const char *log_domain,
                     const char *message,
                     void *user_data)
          {
             /* smaller values are more important */
             if (log_level < MONGOC_LOG_LEVEL_INFO) {
                mongoc_log_default_handler (log_level, log_domain, message, user_data);
             }
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_init ();
             mongoc_log_set_handler (my_logger, NULL);

             /* ... your code ...  */

             mongoc_cleanup ();
             return 0;
          }

       To restore the default handler:

          mongoc_log_set_handler (mongoc_log_default_handler, NULL);

   Disable logging
       To disable all logging, including warnings, critical messages and errors, provide an empty log handler:

          mongoc_log_set_handler (NULL, NULL);

   Tracing
       If compiling your own copy of the MongoDB C driver, consider configuring with --enable-tracing to  enable
       function tracing and hex dumps of network packets to STDERR and STDOUT during development and debugging.

       This is especially useful when debugging what may be going on internally in the driver.

       Trace    messages    can   be   enabled   and   disabled   by   calling   mongoc_log_trace_enable()   and
       mongoc_log_trace_disable()

       NOTE:
          Compiling the driver with  --enable-tracing  will  affect  its  performance.  Disabling  tracing  with
          mongoc_log_trace_disable() significantly reduces the overhead, but cannot remove it completely.
       « index

   Error Reporting
   Description
       Many  C  Driver functions report errors by returning false or -1 and filling out a bson_error_t structure
       with an error domain, error code, and message. Use domain to  determine  which  subsystem  generated  the
       error, and code for the specific error. message is a human-readable error description.

       See also: Handling Errors in libbson.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    Domain                          Code                                         Description
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_CLIENT             MONGOC_ERROR_CLIENT_TOO_BIG                  You  tried to send a message
                                                                                 larger than the server's max
                                                                                 message size.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_CLIENT_AUTHENTICATE             Wrong    credentials,     or
                                                                                 failure sending or receiving
                                                                                 authentication messages.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER       You  tried an SSL connection
                                                                                 but the driver was not built
                                                                                 with SSL.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_CLIENT_IN_EXHAUST               You   began   iterating   an
                                                                                 exhaust  cursor,  then tried
                                                                                 to begin  another  operation
                                                                                 with         the        same
                                                                                 mongoc_client_t.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_CLIENT_SESSION_FAILURE          Failure related to  creating
                                                                                 or using a logical session.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_STREAM             MONGOC_ERROR_STREAM_NAME_RESOLUTION          DNS failure.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_STREAM_SOCKET                   Timeout  communicating  with
                                                                                 server,    or     connection
                                                                                 closed.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_STREAM_CONNECT                  Failed to connect to server.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_PROTOCOL           MONGOC_ERROR_PROTOCOL_INVALID_REPLY          Corrupt     response    from
                                                                                 server.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION       The server  version  is  too
                                                                                 old    or    too    new   to
                                                                                 communicate with the driver.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_CURSOR             MONGOC_ERROR_CURSOR_INVALID_CURSOR           You passed bad arguments  to
                                                                                 mongoc_collection_find_with_opts,
                                                                                 or         you        called
                                                                                 mongoc_cursor_next   on    a
                                                                                 completed  or failed cursor,
                                                                                 or the cursor timed  out  on
                                                                                 the server.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN   A  resume  token was not returned
                                                                                 in   a   document   found    with
                                                                                 mongoc_change_stream_next
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_QUERY              MONGOC_ERROR_QUERY_FAILURE                   Error API Version 1: Server error
                                                                                 from command or query. The server
                                                                                 error message is in message.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_SERVER             MONGOC_ERROR_QUERY_FAILURE                   Error API Version 2: Server error
                                                                                 from command or query. The server
                                                                                 error message is in message.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_SASL               A SASL error code.                           man  sasl_errors  for  a  list of
                                                                                 codes.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_BSON               MONGOC_ERROR_BSON_INVALID                    You   passed   an   invalid    or
                                                                                 oversized   BSON  document  as  a
                                                                                 parameter,       or        called
                                                                                 mongoc_collection_create_index
                                                                                 with  invalid keys, or the server
                                                                                 reply was corrupt.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_NAMESPACE          MONGOC_ERROR_NAMESPACE_INVALID               You tried to create a  collection
                                                                                 with an invalid name.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_COMMAND            MONGOC_ERROR_COMMAND_INVALID_ARG             Many  functions  set  this  error
                                                                                 code when passed bad  parameters.
                                                                                 Print   the   error  message  for
                                                                                 details.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION       You tried to use a command option
                                                                                 the server does not support.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_DUPLICATE_KEY                   An  insert   or   update   failed
                                                                                 because  because  of  a duplicate
                                                                                 _id   or    other    unique-index
                                                                                 violation.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_COMMAND            Error code from server.                      Error API Version 1: Server error
                                                                                 from  a command. The server error
                                                                                 message is in message.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_SERVER             Error code from server.                      Error API Version 2: Server error
                                                                                 from a command. The server  error
                                                                                 message is in message.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_COLLECTION         MONGOC_ERROR_COLLECTION_INSERT_FAILED,       Invalid   or   empty   input   to
                                    MONGOC_ERROR_COLLECTION_UPDATE_FAILED,       mongoc_collection_insert_one,
                                    MONGOC_ERROR_COLLECTION_DELETE_FAILED.       mongoc_collection_insert_bulk,
                                                                                 mongoc_collection_update_one,
                                                                                 mongoc_collection_update_many,
                                                                                 mongoc_collection_replace_one,
                                                                                 mongoc_collection_delete_one,  or
                                                                                 mongoc_collection_delete_many.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_COLLECTION         Error code from server.                      Error API Version 1: Server error
                                                                                 from
                                                                                 mongoc_collection_insert_one,
                                                                                 mongoc_collection_insert_bulk,
                                                                                 mongoc_collection_update_one,
                                                                                 mongoc_collection_update_many,
                                                                                 mongoc_collection_replace_one,
                                                                                 mongoc_collection_delete_one,  or
                                                                                 mongoc_collection_delete_many.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_SERVER             Error code from server.                      Error API Version 2: Server error
                                                                                 from
                                                                                 mongoc_collection_insert_one,
                                                                                 mongoc_collection_insert_bulk,
                                                                                 mongoc_collection_update_one,
                                                                                 mongoc_collection_update_many,
                                                                                 mongoc_collection_replace_one,
                                                                                 mongoc_collection_delete_one,  or
                                                                                 mongoc_collection_delete_many.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_GRIDFS             MONGOC_ERROR_GRIDFS_CHUNK_MISSING            The  GridFS  file  is  missing  a
                                                                                 document    in     its     chunks
                                                                                 collection.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_GRIDFS_INVALID_FILENAME         You  passed  a  NULL  filename to
                                                                                 mongoc_gridfs_remove_by_filename.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                    MONGOC_ERROR_GRIDFS_PROTOCOL_ERROR           You                        called
                                                                                 mongoc_gridfs_file_set_id   after
                                                                                 mongoc_gridfs_file_save.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_SCRAM              MONGOC_ERROR_SCRAM_PROTOCOL_ERROR            Failure      in       SCRAM-SHA-1
                                                                                 authentication.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_SERVER_SELECTION   MONGOC_ERROR_SERVER_SELECTION_FAILURE        No  replica  set member or mongos
                                                                                 is  available,  or  none  matches
                                                                                 your   read  preference,  or  you
                                                                                 supplied        an        invalid
                                                                                 mongoc_read_prefs_t.
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    MONGOC_ERROR_WRITE_CONCERN      Error code from server.                      There  was  a write concern error
                                                                                 or timeout from the server.
  ┌───────────────────────────────┬────────────────────────────────────────────┬───────────────────────────────────┐
  │                               │                                            │                                   │
  │Setting the Error API Version  │                                            │                                   │
--

AUTHOR

       MongoDB, Inc

COPYRIGHT

       2018, MongoDB, Inc

1.9.3-dev                                         Feb 05, 2018                               MONGOC_REFERENCE(3)