1MONGOC_REFERENCE(3) libmongoc MONGOC_REFERENCE(3)
2
3
4
6 mongoc_reference - Index
7
9 A Cross Platform MongoDB Client Library for C
10
11 Introduction
12 The MongoDB C Driver, also known as "libmongoc", is a library for using
13 MongoDB from C applications, and for writing MongoDB drivers in
14 higher-level languages.
15
16 It depends on libbson to generate and parse BSON documents, the native
17 data format of MongoDB.
18
19 Installing the MongoDB C Driver (libmongoc) and BSON library (libbson)
20 The following guide will step you through the process of downloading,
21 building, and installing the current release of the MongoDB C Driver
22 (libmongoc) and BSON library (libbson).
23
24 Supported Platforms
25 The MongoDB C Driver is continuously tested on a variety of platforms
26 including:
27
28 · Archlinux
29
30 · Debian 9.2, 10.0
31
32 · macOS 10.14
33
34 · Microsoft Windows Server 2008, 2016
35
36 · RHEL 6.2, 7.0, 7.1, 8.2
37
38 · Ubuntu 16.04, 18.04
39
40 · Clang 3.4, 3.5, 3.7, 3.8, 6.0
41
42 · GCC 4.8, 4.9, 5.4, 6.3, 8.2, 8.3
43
44 · MinGW-W64
45
46 · Visual Studio 2013, 2015, 2017
47
48 · x86, x86_64, ARM (aarch64), Power8 (ppc64le), zSeries (s390x)
49
50 Install libmongoc with a Package Manager
51 Several Linux distributions provide packages for libmongoc and its
52 dependencies. One advantage of installing libmongoc with a package man‐
53 ager is that its dependencies (including libbson) will be installed
54 automatically. If you choose to install libmongoc from distribution
55 packages, use the package manager to confirm the version being
56 installed is sufficient for your needs.
57
58 The libmongoc package is available on recent versions of Debian and
59 Ubuntu.
60
61 $ apt-get install libmongoc-1.0-0
62
63 On Fedora, a mongo-c-driver package is available in the default reposi‐
64 tories and can be installed with:
65
66 $ dnf install mongo-c-driver
67
68 On recent Red Hat systems, such as CentOS and RHEL 7, a mongo-c-driver
69 package is available in the EPEL repository. To check which version is
70 available, see https://apps.fedoraproject.org/packages/mongo-c-driver.
71 The package can be installed with:
72
73 $ yum install mongo-c-driver
74
75 On macOS systems with Homebrew, the mongo-c-driver package can be
76 installed with:
77
78 $ brew install mongo-c-driver
79
80 Install libbson with a Package Manager
81 The libbson package is available on recent versions of Debian and
82 Ubuntu. If you have installed libmongoc, then libbson will have already
83 been installed as a dependency. It is also possible to install libbson
84 without libmongoc.
85
86 $ apt-get install libbson-1.0-0
87
88 On Fedora, a libbson package is available in the default repositories
89 and can be installed with:
90
91 $ dnf install libbson
92
93 On recent Red Hat systems, such as CentOS and RHEL 7, a libbson package
94 is available in the EPEL repository. To check which version is avail‐
95 able, see https://apps.fedoraproject.org/packages/libbson. The package
96 can be installed with:
97
98 $ yum install libbson
99
100 Build environment
101 Build environment on Unix
102 Prerequisites for libmongoc
103 OpenSSL is required for authentication or for TLS connections to Mon‐
104 goDB. Kerberos or LDAP support requires Cyrus SASL.
105
106 To install all optional dependencies on RedHat / Fedora:
107
108 $ sudo yum install cmake openssl-devel cyrus-sasl-devel
109
110 On Debian / Ubuntu:
111
112 $ sudo apt-get install cmake libssl-dev libsasl2-dev
113
114 On FreeBSD:
115
116 $ su -c 'pkg install cmake openssl cyrus-sasl'
117
118 Prerequisites for libbson
119 The only prerequisite for building libbson is cmake. The command lines
120 above can be adjusted to install only cmake.
121
122 Build environment on macOS
123 Install the XCode Command Line Tools:
124
125 $ xcode-select --install
126
127 The cmake utility is also required. First install Homebrew according to
128 its instructions, then:
129
130 $ brew install cmake
131
132 Build environment on Windows with Visual Studio
133 Building on Windows requires Windows Vista or newer and Visual Studio
134 2010 or newer. Additionally, cmake is required to generate Visual Stu‐
135 dio project files. Installation of these components on Windows is
136 beyond the scope of this document.
137
138 Build environment on Windows with MinGW-W64 and MSYS2
139 Install MSYS2 from msys2.github.io. Choose the x86_64 version, not
140 i686.
141
142 Open the MingGW shell with c:\msys64\ming64.exe (not the msys2_shell).
143 Install dependencies:
144
145 $ pacman --noconfirm -Syu
146 $ pacman --noconfirm -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake
147 $ pacman --noconfirm -S mingw-w64-x86_64-extra-cmake-modules make tar
148 $ pacman --noconfirm -S mingw64/mingw-w64-x86_64-cyrus-sasl
149
150 Configuring the build
151 Before building libmongoc and/or libbson, it is necessary to configure,
152 or prepare, the build. The steps to prepare the build depend on how
153 you obtained the source code and the build platform.
154
155 Preparing a build from a release tarball
156 The most recent release of libmongoc and libbson, both of which are
157 included in mongo-c-driver, can be downloaded here. The instructions in
158 this document utilize cmake's out-of-source build feature to keep build
159 artifacts separate from source files. While the $ prompt is used
160 throughout, the instructions below will work on Linux, macOS, and Win‐
161 dows (assuming that CMake is in the user's shell path in all cases).
162 See the subsequent sections for additional platform-specific instruc‐
163 tions.
164
165 The following snippet will download and extract the driver, and config‐
166 ure it:
167
168 $ wget https://github.com/mongodb/mongo-c-driver/releases/download/1.17.4/mongo-c-driver-1.17.4.tar.gz
169 $ tar xzf mongo-c-driver-1.17.4.tar.gz
170 $ cd mongo-c-driver-1.17.4
171 $ mkdir cmake-build
172 $ cd cmake-build
173 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
174
175 The -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF option is recommended, see
176 init-cleanup. Another useful cmake option is -DCMAKE_BUILD_TYPE=Release
177 for a release optimized build and -DCMAKE_BUILD_TYPE=Debug for a debug
178 build. For a list of all configure options, run cmake -L ...
179
180 If cmake completed successfully, you will see a considerable amount of
181 output describing your build configuration. The final line of output
182 should look something like this:
183
184 -- Build files have been written to: /home/user/mongo-c-driver-1.17.4/cmake-build
185
186 If cmake concludes with anything different, then it is likely an error
187 occurred.
188
189 mongo-c-driver contains a copy of libbson, in case your system does not
190 already have libbson installed. The configuration will detect if libb‐
191 son is not installed and use the bundled libbson.
192
193 Additionally, it is possible to build only libbson by setting the -DEN‐
194 ABLE_MONGOC=OFF option:
195
196 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=OFF ..
197
198 A build configuration description similar to the one above will be dis‐
199 played, though with fewer entries. Once the configuration is complete,
200 the selected items can be built and installed with these commands:
201
202 Preparing a build from a git repository clone
203 Clone the repository and prepare the build on the current master branch
204 or a particular release tag:
205
206 $ git clone https://github.com/mongodb/mongo-c-driver.git
207 $ cd mongo-c-driver
208 $ git checkout 1.17.4 # To build a particular release
209 $ python build/calc_release_version.py > VERSION_CURRENT
210 $ mkdir cmake-build
211 $ cd cmake-build
212 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
213
214 Preparing a build on Windows with Visual Studio
215 On the Windows platform with Visual Studio, it may be necessary to
216 specify the CMake generator to use. This is especially important if
217 multiple versions of Visual Studio are installed on the system or if
218 alternate build tools (e.g., MinGW, MSYS2, Cygwin, etc.) are present on
219 the system. Specifying the generator will ensure that the build con‐
220 figuration is known with certainty, rather than relying on the
221 toolchain that CMake happens to find.
222
223 Start by generating Visual Studio project files. The following assumes
224 you are compiling for 64-bit Windows using Visual Studio 2015 Express,
225 which can be freely downloaded from Microsoft. The sample commands uti‐
226 lize cmake's out-of-source build feature to keep build artifacts sepa‐
227 rate from source files.
228
229 $ cd mongo-c-driver-1.17.4
230 $ mkdir cmake-build
231 $ cd cmake-build
232 $ cmake -G "Visual Studio 14 2015 Win64" \
233 "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \
234 "-DCMAKE_PREFIX_PATH=C:\mongo-c-driver" \
235 ..
236
237 (Run cmake -LH .. for a list of other options.)
238
239 To see a complete list of the CMake generators available on your spe‐
240 cific system, use a command like this:
241
242 $ cmake --help
243
244 Executing a build
245 Building on Unix, macOS, and Windows (MinGW-W64 and MSYS2)
246 $ cmake --build .
247 $ sudo cmake --build . --target install
248
249 (Note that the sudo command may not be applicable or available depend‐
250 ing on the configuration of your system.)
251
252 In the above commands, the first relies on the default target which
253 builds all configured components. For fine grained control over what
254 gets built, the following command can be used (for Ninja and Make‐
255 file-based build systems) to list all available targets:
256
257 $ cmake --build . help
258
259 Building on Windows with Visual Studio
260 Once the project files are generated, the project can be opened
261 directly in Visual Studio or compiled from the command line.
262
263 Build using the CMake build tool mode:
264
265 $ cmake --build . --config RelWithDebInfo
266
267 Visual Studio's default build type is Debug, but we recommend a release
268 build with debug info for production use. Now that libmongoc and libb‐
269 son are compiled, install them. Components will be installed to the
270 path specified by CMAKE_INSTALL_PREFIX.
271
272 $ cmake --build . --config RelWithDebInfo --target install
273
274 You should now see libmongoc and libbson installed in C:\mongo-c-driver
275
276 For Visual Studio 2019 (16.4 and newer), this command can be used to
277 list all available targets:
278
279 $ cmake --build . -- /targets
280
281 Alternately, you can examine the files matching the glob *.vcxproj in
282 the cmake-build directory.
283
284 To use the driver libraries in your program, see visual-studio-guide.
285
286 Generating the documentation
287 Install Sphinx, then:
288
289 $ cmake -DENABLE_MAN_PAGES=ON -DENABLE_HTML_DOCS=ON ..
290 $ cmake --build . --target mongoc-doc
291
292 To build only the libbson documentation:
293
294 $ cmake -DENABLE_MAN_PAGES=ON -DENABLE_HTML_DOCS=ON ..
295 $ cmake --build . --target bson-doc
296
297 The -DENABLE_MAN_PAGES=ON and -DENABLE_HTML_DOCS=ON can also be added
298 as options to a normal build from a release tarball or from git so that
299 the documentation is built at the same time as other components.
300
301 Uninstalling the installed components
302 There are two ways to uninstall the components that have been
303 installed. The first is to invoke the uninstall program directly. On
304 Linux/Unix:
305
306 $ sudo /usr/local/share/mongo-c-driver/uninstall.sh
307
308 On Windows:
309
310 $ C:\mongo-c-driver\share\mongo-c-driver\uninstall.bat
311
312 The second way to uninstall is from within the build directory, assum‐
313 ing that it is in the exact same state as when the install command was
314 invoked:
315
316 $ sudo cmake --build . --target uninstall
317
318 The second approach simply invokes the uninstall program referenced in
319 the first approach.
320
321 Additional Options for Integrators
322 In the event that you are building the BSON library and/or the C driver
323 to embed with other components and you wish to avoid the potential for
324 collision with components installed from a standard build or from a
325 distribution package manager, you can make use of the BSON_OUTPUT_BASE‐
326 NAME and MONGOC_OUTPUT_BASENAME options to cmake.
327
328 $ cmake -DBSON_OUTPUT_BASENAME=custom_bson -DMONGOC_OUTPUT_BASENAME=custom_mongoc ..
329
330 The above command would produce libraries named libcustom_bson.so and
331 libcustom_mongoc.so (or with the extension appropriate for the build
332 platform). Those libraries could be placed in a standard system direc‐
333 tory or in an alternate location and could be linked to by specifying
334 something like -lcustom_mongoc -lcustom_bson on the linker command line
335 (possibly adjusting the specific flags to those required by your
336 linker).
337
338 Tutorial
339 This guide offers a brief introduction to the MongoDB C Driver.
340
341 For more information on the C API, please refer to the api.
342
343 Contents
344 · Tutorial
345
346 · Installing
347
348 · Starting MongoDB
349
350 · Include and link libmongoc in your C program
351
352 · Use libmongoc in a Microsoft Visual Studio Project
353
354 · Making a Connection
355
356 · Creating BSON Documents
357
358 · Basic CRUD Operations
359
360 · Executing Commands
361
362 · Threading
363
364 · Next Steps
365
366 Installing
367 For detailed instructions on installing the MongoDB C Driver on a par‐
368 ticular platform, please see the installation guide.
369
370 Starting MongoDB
371 To run the examples in this tutorial, MongoDB must be installed and
372 running on localhost on the default port, 27017. To check if it is up
373 and running, connect to it with the MongoDB shell.
374
375 $ mongo --host localhost --port 27017
376 MongoDB shell version: 3.0.6
377 connecting to: localhost:27017/test
378 >
379
380 Include and link libmongoc in your C program
381 Include mongoc.h
382 All libmongoc's functions and types are available in one header file.
383 Simply include mongoc/mongoc.h:
384
385 #include <mongoc/mongoc.h>
386
387 CMake
388 The libmongoc installation includes a CMake config-file package, so you
389 can use CMake's find_package command to import libmongoc's CMake target
390 and link to libmongoc (as a shared library):
391
392 CMakeLists.txt
393
394 # Specify the minimum version you require.
395 find_package (mongoc-1.0 1.7 REQUIRED)
396
397 # The "hello_mongoc.c" sample program is shared among four tests.
398 add_executable (hello_mongoc ../../hello_mongoc.c)
399 target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_shared)
400
401
402 You can also use libmongoc as a static library instead: Use the
403 mongo::mongoc_static CMake target:
404
405 # Specify the minimum version you require.
406 find_package (mongoc-1.0 1.7 REQUIRED)
407
408 # The "hello_mongoc.c" sample program is shared among four tests.
409 add_executable (hello_mongoc ../../hello_mongoc.c)
410 target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_static)
411
412
413 pkg-config
414 If you're not using CMake, use pkg-config on the command line to set
415 header and library paths:
416
417 gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0)
418
419
420 Or to statically link to libmongoc:
421
422 gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0)
423
424
425 Specifying header and include paths manually
426 If you aren't using CMake or pkg-config, paths and libraries can be
427 managed manually.
428
429 $ gcc -o hello_mongoc hello_mongoc.c \
430 -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \
431 -lmongoc-1.0 -lbson-1.0
432 $ ./hello_mongoc
433 { "ok" : 1.000000 }
434
435 For Windows users, the code can be compiled and run with the following
436 commands. (This assumes that the MongoDB C Driver has been installed to
437 C:\mongo-c-driver; change the include directory as needed.)
438
439 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 hello_mongoc.c
440 C:\> hello_mongoc
441 { "ok" : 1.000000 }
442
443 Use libmongoc in a Microsoft Visual Studio Project
444 See the libmongoc and Visual Studio guide.
445
446 Making a Connection
447 Access MongoDB with a mongoc_client_t. It transparently connects to
448 standalone servers, replica sets and sharded clusters on demand. To
449 perform operations on a database or collection, create a mongoc_data‐
450 base_t or mongoc_collection_t struct from the mongoc_client_t.
451
452 At the start of an application, call mongoc_init before any other lib‐
453 mongoc functions. At the end, call the appropriate destroy function for
454 each collection, database, or client handle, in reverse order from how
455 they were constructed. Call mongoc_cleanup before exiting.
456
457 The example below establishes a connection to a standalone server on
458 localhost, registers the client application as "connect-example," and
459 performs a simple command.
460
461 More information about database operations can be found in the CRUD
462 Operations and Executing Commands sections. Examples of connecting to
463 replica sets and sharded clusters can be found on the Advanced Connec‐
464 tions page.
465
466 hello_mongoc.c
467
468 #include <mongoc/mongoc.h>
469
470 int
471 main (int argc, char *argv[])
472 {
473 const char *uri_string = "mongodb://localhost:27017";
474 mongoc_uri_t *uri;
475 mongoc_client_t *client;
476 mongoc_database_t *database;
477 mongoc_collection_t *collection;
478 bson_t *command, reply, *insert;
479 bson_error_t error;
480 char *str;
481 bool retval;
482
483 /*
484 * Required to initialize libmongoc's internals
485 */
486 mongoc_init ();
487
488 /*
489 * Optionally get MongoDB URI from command line
490 */
491 if (argc > 1) {
492 uri_string = argv[1];
493 }
494
495 /*
496 * Safely create a MongoDB URI object from the given string
497 */
498 uri = mongoc_uri_new_with_error (uri_string, &error);
499 if (!uri) {
500 fprintf (stderr,
501 "failed to parse URI: %s\n"
502 "error message: %s\n",
503 uri_string,
504 error.message);
505 return EXIT_FAILURE;
506 }
507
508 /*
509 * Create a new client instance
510 */
511 client = mongoc_client_new_from_uri (uri);
512 if (!client) {
513 return EXIT_FAILURE;
514 }
515
516 /*
517 * Register the application name so we can track it in the profile logs
518 * on the server. This can also be done from the URI (see other examples).
519 */
520 mongoc_client_set_appname (client, "connect-example");
521
522 /*
523 * Get a handle on the database "db_name" and collection "coll_name"
524 */
525 database = mongoc_client_get_database (client, "db_name");
526 collection = mongoc_client_get_collection (client, "db_name", "coll_name");
527
528 /*
529 * Do work. This example pings the database, prints the result as JSON and
530 * performs an insert
531 */
532 command = BCON_NEW ("ping", BCON_INT32 (1));
533
534 retval = mongoc_client_command_simple (
535 client, "admin", command, NULL, &reply, &error);
536
537 if (!retval) {
538 fprintf (stderr, "%s\n", error.message);
539 return EXIT_FAILURE;
540 }
541
542 str = bson_as_json (&reply, NULL);
543 printf ("%s\n", str);
544
545 insert = BCON_NEW ("hello", BCON_UTF8 ("world"));
546
547 if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) {
548 fprintf (stderr, "%s\n", error.message);
549 }
550
551 bson_destroy (insert);
552 bson_destroy (&reply);
553 bson_destroy (command);
554 bson_free (str);
555
556 /*
557 * Release our handles and clean up libmongoc
558 */
559 mongoc_collection_destroy (collection);
560 mongoc_database_destroy (database);
561 mongoc_uri_destroy (uri);
562 mongoc_client_destroy (client);
563 mongoc_cleanup ();
564
565 return EXIT_SUCCESS;
566 }
567
568
569 Creating BSON Documents
570 Documents are stored in MongoDB's data format, BSON. The C driver uses
571 libbson to create BSON documents. There are several ways to construct
572 them: appending key-value pairs, using BCON, or parsing JSON.
573
574 Appending BSON
575 A BSON document, represented as a bson_t in code, can be constructed
576 one field at a time using libbson's append functions.
577
578 For example, to create a document like this:
579
580 {
581 born : ISODate("1906-12-09"),
582 died : ISODate("1992-01-01"),
583 name : {
584 first : "Grace",
585 last : "Hopper"
586 },
587 languages : [ "MATH-MATIC", "FLOW-MATIC", "COBOL" ],
588 degrees: [ { degree: "BA", school: "Vassar" }, { degree: "PhD", school: "Yale" } ]
589 }
590
591 Use the following code:
592
593 #include <bson/bson.h>
594
595 int
596 main (int argc,
597 char *argv[])
598 {
599 struct tm born = { 0 };
600 struct tm died = { 0 };
601 const char *lang_names[] = {"MATH-MATIC", "FLOW-MATIC", "COBOL"};
602 const char *schools[] = {"Vassar", "Yale"};
603 const char *degrees[] = {"BA", "PhD"};
604 uint32_t i;
605 char buf[16];
606 const char *key;
607 size_t keylen;
608 bson_t *document;
609 bson_t child;
610 bson_t child2;
611 char *str;
612
613 document = bson_new ();
614
615 /*
616 * Append { "born" : ISODate("1906-12-09") } to the document.
617 * Passing -1 for the length argument tells libbson to calculate the string length.
618 */
619 born.tm_year = 6; /* years are 1900-based */
620 born.tm_mon = 11; /* months are 0-based */
621 born.tm_mday = 9;
622 bson_append_date_time (document, "born", -1, mktime (&born) * 1000);
623
624 /*
625 * Append { "died" : ISODate("1992-01-01") } to the document.
626 */
627 died.tm_year = 92;
628 died.tm_mon = 0;
629 died.tm_mday = 1;
630
631 /*
632 * For convenience, this macro passes length -1 by default.
633 */
634 BSON_APPEND_DATE_TIME (document, "died", mktime (&died) * 1000);
635
636 /*
637 * Append a subdocument.
638 */
639 BSON_APPEND_DOCUMENT_BEGIN (document, "name", &child);
640 BSON_APPEND_UTF8 (&child, "first", "Grace");
641 BSON_APPEND_UTF8 (&child, "last", "Hopper");
642 bson_append_document_end (document, &child);
643
644 /*
645 * Append array of strings. Generate keys "0", "1", "2".
646 */
647 BSON_APPEND_ARRAY_BEGIN (document, "languages", &child);
648 for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) {
649 keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
650 bson_append_utf8 (&child, key, (int) keylen, lang_names[i], -1);
651 }
652 bson_append_array_end (document, &child);
653
654 /*
655 * Array of subdocuments:
656 * degrees: [ { degree: "BA", school: "Vassar" }, ... ]
657 */
658 BSON_APPEND_ARRAY_BEGIN (document, "degrees", &child);
659 for (i = 0; i < sizeof degrees / sizeof (char *); ++i) {
660 keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
661 bson_append_document_begin (&child, key, (int) keylen, &child2);
662 BSON_APPEND_UTF8 (&child2, "degree", degrees[i]);
663 BSON_APPEND_UTF8 (&child2, "school", schools[i]);
664 bson_append_document_end (&child, &child2);
665 }
666 bson_append_array_end (document, &child);
667
668 /*
669 * Print the document as a JSON string.
670 */
671 str = bson_as_canonical_extended_json (document, NULL);
672 printf ("%s\n", str);
673 bson_free (str);
674
675 /*
676 * Clean up allocated bson documents.
677 */
678 bson_destroy (document);
679 return 0;
680 }
681
682 See the libbson documentation for all of the types that can be appended
683 to a bson_t.
684
685 Using BCON
686 BSON C Object Notation, BCON for short, is an alternative way of con‐
687 structing BSON documents in a manner closer to the intended format. It
688 has less type-safety than BSON's append functions but results in less
689 code.
690
691 #include <bson/bson.h>
692
693 int
694 main (int argc,
695 char *argv[])
696 {
697 struct tm born = { 0 };
698 struct tm died = { 0 };
699 bson_t *document;
700 char *str;
701
702 born.tm_year = 6;
703 born.tm_mon = 11;
704 born.tm_mday = 9;
705
706 died.tm_year = 92;
707 died.tm_mon = 0;
708 died.tm_mday = 1;
709
710 document = BCON_NEW (
711 "born", BCON_DATE_TIME (mktime (&born) * 1000),
712 "died", BCON_DATE_TIME (mktime (&died) * 1000),
713 "name", "{",
714 "first", BCON_UTF8 ("Grace"),
715 "last", BCON_UTF8 ("Hopper"),
716 "}",
717 "languages", "[",
718 BCON_UTF8 ("MATH-MATIC"),
719 BCON_UTF8 ("FLOW-MATIC"),
720 BCON_UTF8 ("COBOL"),
721 "]",
722 "degrees", "[",
723 "{", "degree", BCON_UTF8 ("BA"), "school", BCON_UTF8 ("Vassar"), "}",
724 "{", "degree", BCON_UTF8 ("PhD"), "school", BCON_UTF8 ("Yale"), "}",
725 "]");
726
727 /*
728 * Print the document as a JSON string.
729 */
730 str = bson_as_canonical_extended_json (document, NULL);
731 printf ("%s\n", str);
732 bson_free (str);
733
734 /*
735 * Clean up allocated bson documents.
736 */
737 bson_destroy (document);
738 return 0;
739 }
740
741 Notice that BCON can create arrays, subdocuments and arbitrary fields.
742
743 Creating BSON from JSON
744 For single documents, BSON can be created from JSON strings via
745 bson_new_from_json.
746
747 #include <bson/bson.h>
748
749 int
750 main (int argc,
751 char *argv[])
752 {
753 bson_error_t error;
754 bson_t *bson;
755 char *string;
756
757 const char *json = "{\"name\": {\"first\":\"Grace\", \"last\":\"Hopper\"}}";
758 bson = bson_new_from_json ((const uint8_t *)json, -1, &error);
759
760 if (!bson) {
761 fprintf (stderr, "%s\n", error.message);
762 return EXIT_FAILURE;
763 }
764
765 string = bson_as_canonical_extended_json (bson, NULL);
766 printf ("%s\n", string);
767 bson_free (string);
768
769 return 0;
770 }
771
772 To initialize BSON from a sequence of JSON documents, use
773 bson_json_reader_t.
774
775 Basic CRUD Operations
776 This section demonstrates the basics of using the C Driver to interact
777 with MongoDB.
778
779 Inserting a Document
780 To insert documents into a collection, first obtain a handle to a mon‐
781 goc_collection_t via a mongoc_client_t. Then, use mongoc_collec‐
782 tion_insert_one to add BSON documents to the collection. This example
783 inserts into the database "mydb" and collection "mycoll".
784
785 When finished, ensure that allocated structures are freed by using
786 their respective destroy functions.
787
788 #include <bson/bson.h>
789 #include <mongoc/mongoc.h>
790 #include <stdio.h>
791
792 int
793 main (int argc,
794 char *argv[])
795 {
796 mongoc_client_t *client;
797 mongoc_collection_t *collection;
798 bson_error_t error;
799 bson_oid_t oid;
800 bson_t *doc;
801
802 mongoc_init ();
803
804 client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
805 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
806
807 doc = bson_new ();
808 bson_oid_init (&oid, NULL);
809 BSON_APPEND_OID (doc, "_id", &oid);
810 BSON_APPEND_UTF8 (doc, "hello", "world");
811
812 if (!mongoc_collection_insert_one (
813 collection, doc, NULL, NULL, &error)) {
814 fprintf (stderr, "%s\n", error.message);
815 }
816
817 bson_destroy (doc);
818 mongoc_collection_destroy (collection);
819 mongoc_client_destroy (client);
820 mongoc_cleanup ();
821
822 return 0;
823 }
824
825 Compile the code and run it:
826
827 $ gcc -o insert insert.c $(pkg-config --cflags --libs libmongoc-1.0)
828 $ ./insert
829
830 On Windows:
831
832 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 insert.c
833 C:\> insert
834
835 To verify that the insert succeeded, connect with the MongoDB shell.
836
837 $ mongo
838 MongoDB shell version: 3.0.6
839 connecting to: test
840 > use mydb
841 switched to db mydb
842 > db.mycoll.find()
843 { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" }
844 >
845
846 Finding a Document
847 To query a MongoDB collection with the C driver, use the function mon‐
848 goc_collection_find_with_opts(). This returns a cursor to the matching
849 documents. The following examples iterate through the result cursors
850 and print the matches to stdout as JSON strings.
851
852 Use a document as a query specifier; for example,
853
854 { "color" : "red" }
855
856 will match any document with a field named "color" with value "red". An
857 empty document {} can be used to match all documents.
858
859 This first example uses an empty query specifier to find all documents
860 in the database "mydb" and collection "mycoll".
861
862 #include <bson/bson.h>
863 #include <mongoc/mongoc.h>
864 #include <stdio.h>
865
866 int
867 main (int argc, char *argv[])
868 {
869 mongoc_client_t *client;
870 mongoc_collection_t *collection;
871 mongoc_cursor_t *cursor;
872 const bson_t *doc;
873 bson_t *query;
874 char *str;
875
876 mongoc_init ();
877
878 client =
879 mongoc_client_new ("mongodb://localhost:27017/?appname=find-example");
880 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
881 query = bson_new ();
882 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
883
884 while (mongoc_cursor_next (cursor, &doc)) {
885 str = bson_as_canonical_extended_json (doc, NULL);
886 printf ("%s\n", str);
887 bson_free (str);
888 }
889
890 bson_destroy (query);
891 mongoc_cursor_destroy (cursor);
892 mongoc_collection_destroy (collection);
893 mongoc_client_destroy (client);
894 mongoc_cleanup ();
895
896 return 0;
897 }
898
899 Compile the code and run it:
900
901 $ gcc -o find find.c $(pkg-config --cflags --libs libmongoc-1.0)
902 $ ./find
903 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
904
905 On Windows:
906
907 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find.c
908 C:\> find
909 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
910
911 To look for a specific document, add a specifier to query. This example
912 adds a call to BSON_APPEND_UTF8() to look for all documents matching
913 {"hello" : "world"}.
914
915 #include <bson/bson.h>
916 #include <mongoc/mongoc.h>
917 #include <stdio.h>
918
919 int
920 main (int argc, char *argv[])
921 {
922 mongoc_client_t *client;
923 mongoc_collection_t *collection;
924 mongoc_cursor_t *cursor;
925 const bson_t *doc;
926 bson_t *query;
927 char *str;
928
929 mongoc_init ();
930
931 client = mongoc_client_new (
932 "mongodb://localhost:27017/?appname=find-specific-example");
933 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
934 query = bson_new ();
935 BSON_APPEND_UTF8 (query, "hello", "world");
936
937 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
938
939 while (mongoc_cursor_next (cursor, &doc)) {
940 str = bson_as_canonical_extended_json (doc, NULL);
941 printf ("%s\n", str);
942 bson_free (str);
943 }
944
945 bson_destroy (query);
946 mongoc_cursor_destroy (cursor);
947 mongoc_collection_destroy (collection);
948 mongoc_client_destroy (client);
949 mongoc_cleanup ();
950
951 return 0;
952 }
953
954 $ gcc -o find-specific find-specific.c $(pkg-config --cflags --libs libmongoc-1.0)
955 $ ./find-specific
956 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
957
958 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find-specific.c
959 C:\> find-specific
960 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
961
962 Updating a Document
963 This code snippet gives an example of using mongoc_collec‐
964 tion_update_one() to update the fields of a document.
965
966 Using the "mydb" database, the following example inserts an example
967 document into the "mycoll" collection. Then, using its _id field, the
968 document is updated with different values and a new field.
969
970 #include <bson/bson.h>
971 #include <mongoc/mongoc.h>
972 #include <stdio.h>
973
974 int
975 main (int argc, char *argv[])
976 {
977 mongoc_collection_t *collection;
978 mongoc_client_t *client;
979 bson_error_t error;
980 bson_oid_t oid;
981 bson_t *doc = NULL;
982 bson_t *update = NULL;
983 bson_t *query = NULL;
984
985 mongoc_init ();
986
987 client =
988 mongoc_client_new ("mongodb://localhost:27017/?appname=update-example");
989 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
990
991 bson_oid_init (&oid, NULL);
992 doc = BCON_NEW ("_id", BCON_OID (&oid), "key", BCON_UTF8 ("old_value"));
993
994 if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
995 fprintf (stderr, "%s\n", error.message);
996 goto fail;
997 }
998
999 query = BCON_NEW ("_id", BCON_OID (&oid));
1000 update = BCON_NEW ("$set",
1001 "{",
1002 "key",
1003 BCON_UTF8 ("new_value"),
1004 "updated",
1005 BCON_BOOL (true),
1006 "}");
1007
1008 if (!mongoc_collection_update_one (
1009 collection, query, update, NULL, NULL, &error)) {
1010 fprintf (stderr, "%s\n", error.message);
1011 goto fail;
1012 }
1013
1014 fail:
1015 if (doc)
1016 bson_destroy (doc);
1017 if (query)
1018 bson_destroy (query);
1019 if (update)
1020 bson_destroy (update);
1021
1022 mongoc_collection_destroy (collection);
1023 mongoc_client_destroy (client);
1024 mongoc_cleanup ();
1025
1026 return 0;
1027 }
1028
1029 Compile the code and run it:
1030
1031 $ gcc -o update update.c $(pkg-config --cflags --libs libmongoc-1.0)
1032 $ ./update
1033
1034 On Windows:
1035
1036 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 update.c
1037 C:\> update
1038 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1039
1040 To verify that the update succeeded, connect with the MongoDB shell.
1041
1042 $ mongo
1043 MongoDB shell version: 3.0.6
1044 connecting to: test
1045 > use mydb
1046 switched to db mydb
1047 > db.mycoll.find({"updated" : true})
1048 { "_id" : ObjectId("55ef549236fe322f9490e17b"), "updated" : true, "key" : "new_value" }
1049 >
1050
1051 Deleting a Document
1052 This example illustrates the use of mongoc_collection_delete_one() to
1053 delete a document.
1054
1055 The following code inserts a sample document into the database "mydb"
1056 and collection "mycoll". Then, it deletes all documents matching
1057 {"hello" : "world"}.
1058
1059 #include <bson/bson.h>
1060 #include <mongoc/mongoc.h>
1061 #include <stdio.h>
1062
1063 int
1064 main (int argc, char *argv[])
1065 {
1066 mongoc_client_t *client;
1067 mongoc_collection_t *collection;
1068 bson_error_t error;
1069 bson_oid_t oid;
1070 bson_t *doc;
1071
1072 mongoc_init ();
1073
1074 client =
1075 mongoc_client_new ("mongodb://localhost:27017/?appname=delete-example");
1076 collection = mongoc_client_get_collection (client, "test", "test");
1077
1078 doc = bson_new ();
1079 bson_oid_init (&oid, NULL);
1080 BSON_APPEND_OID (doc, "_id", &oid);
1081 BSON_APPEND_UTF8 (doc, "hello", "world");
1082
1083 if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
1084 fprintf (stderr, "Insert failed: %s\n", error.message);
1085 }
1086
1087 bson_destroy (doc);
1088
1089 doc = bson_new ();
1090 BSON_APPEND_OID (doc, "_id", &oid);
1091
1092 if (!mongoc_collection_delete_one (
1093 collection, doc, NULL, NULL, &error)) {
1094 fprintf (stderr, "Delete failed: %s\n", error.message);
1095 }
1096
1097 bson_destroy (doc);
1098 mongoc_collection_destroy (collection);
1099 mongoc_client_destroy (client);
1100 mongoc_cleanup ();
1101
1102 return 0;
1103 }
1104
1105 Compile the code and run it:
1106
1107 $ gcc -o delete delete.c $(pkg-config --cflags --libs libmongoc-1.0)
1108 $ ./delete
1109
1110 On Windows:
1111
1112 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 delete.c
1113 C:\> delete
1114
1115 Use the MongoDB shell to prove that the documents have been removed
1116 successfully.
1117
1118 $ mongo
1119 MongoDB shell version: 3.0.6
1120 connecting to: test
1121 > use mydb
1122 switched to db mydb
1123 > db.mycoll.count({"hello" : "world"})
1124 0
1125 >
1126
1127 Counting Documents
1128 Counting the number of documents in a MongoDB collection is similar to
1129 performing a find operation. This example counts the number of docu‐
1130 ments matching {"hello" : "world"} in the database "mydb" and collec‐
1131 tion "mycoll".
1132
1133 #include <bson/bson.h>
1134 #include <mongoc/mongoc.h>
1135 #include <stdio.h>
1136
1137 int
1138 main (int argc, char *argv[])
1139 {
1140 mongoc_client_t *client;
1141 mongoc_collection_t *collection;
1142 bson_error_t error;
1143 bson_t *doc;
1144 int64_t count;
1145
1146 mongoc_init ();
1147
1148 client =
1149 mongoc_client_new ("mongodb://localhost:27017/?appname=count-example");
1150 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1151 doc = bson_new_from_json (
1152 (const uint8_t *) "{\"hello\" : \"world\"}", -1, &error);
1153
1154 count = mongoc_collection_count (
1155 collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
1156
1157 if (count < 0) {
1158 fprintf (stderr, "%s\n", error.message);
1159 } else {
1160 printf ("%" PRId64 "\n", count);
1161 }
1162
1163 bson_destroy (doc);
1164 mongoc_collection_destroy (collection);
1165 mongoc_client_destroy (client);
1166 mongoc_cleanup ();
1167
1168 return 0;
1169 }
1170
1171 Compile the code and run it:
1172
1173 $ gcc -o count count.c $(pkg-config --cflags --libs libmongoc-1.0)
1174 $ ./count
1175 1
1176
1177 On Windows:
1178
1179 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 count.c
1180 C:\> count
1181 1
1182
1183 Executing Commands
1184 The driver provides helper functions for executing MongoDB commands on
1185 client, database and collection structures. These functions return cur‐
1186 sors; the _simple variants return booleans indicating success or fail‐
1187 ure.
1188
1189 This example executes the collStats command against the collection
1190 "mycoll" in database "mydb".
1191
1192 #include <bson/bson.h>
1193 #include <mongoc/mongoc.h>
1194 #include <stdio.h>
1195
1196 int
1197 main (int argc, char *argv[])
1198 {
1199 mongoc_client_t *client;
1200 mongoc_collection_t *collection;
1201 bson_error_t error;
1202 bson_t *command;
1203 bson_t reply;
1204 char *str;
1205
1206 mongoc_init ();
1207
1208 client = mongoc_client_new (
1209 "mongodb://localhost:27017/?appname=executing-example");
1210 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1211
1212 command = BCON_NEW ("collStats", BCON_UTF8 ("mycoll"));
1213 if (mongoc_collection_command_simple (
1214 collection, command, NULL, &reply, &error)) {
1215 str = bson_as_canonical_extended_json (&reply, NULL);
1216 printf ("%s\n", str);
1217 bson_free (str);
1218 } else {
1219 fprintf (stderr, "Failed to run command: %s\n", error.message);
1220 }
1221
1222 bson_destroy (command);
1223 bson_destroy (&reply);
1224 mongoc_collection_destroy (collection);
1225 mongoc_client_destroy (client);
1226 mongoc_cleanup ();
1227
1228 return 0;
1229 }
1230
1231 Compile the code and run it:
1232
1233 $ gcc -o executing executing.c $(pkg-config --cflags --libs libmongoc-1.0)
1234 $ ./executing
1235 { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
1236 "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
1237 "indexDetails" : { }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }
1238
1239 On Windows:
1240
1241 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 executing.c
1242 C:\> executing
1243 { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
1244 "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
1245 "indexDetails" : { }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }
1246
1247 Threading
1248 The MongoDB C Driver is thread-unaware in the vast majority of its
1249 operations. This means it is up to the programmer to guarantee
1250 thread-safety.
1251
1252 However, mongoc_client_pool_t is thread-safe and is used to fetch a
1253 mongoc_client_t in a thread-safe manner. After retrieving a client from
1254 the pool, the client structure should be considered owned by the call‐
1255 ing thread. When the thread is finished, the client should be placed
1256 back into the pool.
1257
1258 example-pool.c
1259
1260 /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
1261 * libmongoc-1.0) */
1262
1263 /* ./example-pool [CONNECTION_STRING] */
1264
1265 #include <mongoc/mongoc.h>
1266 #include <pthread.h>
1267 #include <stdio.h>
1268
1269 static pthread_mutex_t mutex;
1270 static bool in_shutdown = false;
1271
1272 static void *
1273 worker (void *data)
1274 {
1275 mongoc_client_pool_t *pool = data;
1276 mongoc_client_t *client;
1277 bson_t ping = BSON_INITIALIZER;
1278 bson_error_t error;
1279 bool r;
1280
1281 BSON_APPEND_INT32 (&ping, "ping", 1);
1282
1283 while (true) {
1284 client = mongoc_client_pool_pop (pool);
1285 /* Do something with client. If you are writing an HTTP server, you
1286 * probably only want to hold onto the client for the portion of the
1287 * request performing database queries.
1288 */
1289 r = mongoc_client_command_simple (
1290 client, "admin", &ping, NULL, NULL, &error);
1291
1292 if (!r) {
1293 fprintf (stderr, "%s\n", error.message);
1294 }
1295
1296 mongoc_client_pool_push (pool, client);
1297
1298 pthread_mutex_lock (&mutex);
1299 if (in_shutdown || !r) {
1300 pthread_mutex_unlock (&mutex);
1301 break;
1302 }
1303
1304 pthread_mutex_unlock (&mutex);
1305 }
1306
1307 bson_destroy (&ping);
1308 return NULL;
1309 }
1310
1311 int
1312 main (int argc, char *argv[])
1313 {
1314 const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
1315 mongoc_uri_t *uri;
1316 bson_error_t error;
1317 mongoc_client_pool_t *pool;
1318 pthread_t threads[10];
1319 unsigned i;
1320 void *ret;
1321
1322 pthread_mutex_init (&mutex, NULL);
1323 mongoc_init ();
1324
1325 if (argc > 1) {
1326 uri_string = argv[1];
1327 }
1328
1329 uri = mongoc_uri_new_with_error (uri_string, &error);
1330 if (!uri) {
1331 fprintf (stderr,
1332 "failed to parse URI: %s\n"
1333 "error message: %s\n",
1334 uri_string,
1335 error.message);
1336 return EXIT_FAILURE;
1337 }
1338
1339 pool = mongoc_client_pool_new (uri);
1340 mongoc_client_pool_set_error_api (pool, 2);
1341
1342 for (i = 0; i < 10; i++) {
1343 pthread_create (&threads[i], NULL, worker, pool);
1344 }
1345
1346 sleep (10);
1347 pthread_mutex_lock (&mutex);
1348 in_shutdown = true;
1349 pthread_mutex_unlock (&mutex);
1350
1351 for (i = 0; i < 10; i++) {
1352 pthread_join (threads[i], &ret);
1353 }
1354
1355 mongoc_client_pool_destroy (pool);
1356 mongoc_uri_destroy (uri);
1357
1358 mongoc_cleanup ();
1359
1360 return EXIT_SUCCESS;
1361 }
1362
1363
1364 Next Steps
1365 To find information on advanced topics, browse the rest of the C driver
1366 guide or the official MongoDB documentation.
1367
1368 For help with common issues, consult the Troubleshooting page. To
1369 report a bug or request a new feature, follow these instructions.
1370
1371 Authentication
1372 This guide covers the use of authentication options with the MongoDB C
1373 Driver. Ensure that the MongoDB server is also properly configured for
1374 authentication before making a connection. For more information, see
1375 the MongoDB security documentation.
1376
1377 The MongoDB C driver supports several authentication mechanisms through
1378 the use of MongoDB connection URIs.
1379
1380 By default, if a username and password are provided as part of the con‐
1381 nection string (and an optional authentication database), they are used
1382 to connect via the default authentication mechanism of the server.
1383
1384 To select a specific authentication mechanism other than the default,
1385 see the list of supported mechanism below.
1386
1387 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
1388
1389 Currently supported values for the authMechanism connection string
1390 option are:
1391
1392 · SCRAM-SHA-1
1393
1394 · MONGODB-CR (deprecated)
1395
1396 · GSSAPI
1397
1398 · PLAIN
1399
1400 · X509
1401
1402 · MONGODB-AWS
1403
1404 Basic Authentication (SCRAM-SHA-256)
1405 MongoDB 4.0 introduces support for authenticating using the SCRAM pro‐
1406 tocol with the more secure SHA-256 hash described in RFC 7677. Using
1407 this authentication mechanism means that the password is never actually
1408 sent over the wire when authenticating, but rather a computed proof
1409 that the client password is the same as the password the server knows.
1410 In MongoDB 4.0, the C driver can determine the correct default authen‐
1411 tication mechanism for users with stored SCRAM-SHA-1 and SCRAM-SHA-256
1412 credentials:
1413
1414 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
1415 /* the correct authMechanism is negotiated between the driver and server. */
1416
1417 Alternatively, SCRAM-SHA-256 can be explicitly specified as an auth‐
1418 Mechanism.
1419
1420 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-256&authSource=mydb");
1421
1422 Passwords for SCRAM-SHA-256 undergo the preprocessing step known as
1423 SASLPrep specified in RFC 4013. SASLPrep will only be performed for
1424 passwords containing non-ASCII characters. SASLPrep requires libicu.
1425 If libicu is not available, attempting to authenticate over
1426 SCRAM-SHA-256 with non-ASCII passwords will result in error.
1427
1428 Usernames never undergo SASLPrep.
1429
1430 By default, when building the C driver libicu is linked if available.
1431 This can be changed with the ENABLE_ICU cmake option. To specify an
1432 installation path of libicu, specify ICU_ROOT as a cmake option. See
1433 the FindICU documentation for more information.
1434
1435 Basic Authentication (SCRAM-SHA-1)
1436 The default authentication mechanism before MongoDB 4.0 is SCRAM-SHA-1
1437 (RFC 5802). Using this authentication mechanism means that the password
1438 is never actually sent over the wire when authenticating, but rather a
1439 computed proof that the client password is the same as the password the
1440 server knows.
1441
1442 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1&authSource=mydb");
1443
1444 NOTE:
1445 SCRAM-SHA-1 authenticates against the admin database by default. If
1446 the user is created in another database, then specifying the auth‐
1447 Source is required.
1448
1449 Legacy Authentication (MONGODB-CR)
1450 The MONGODB-CR authMechanism is deprecated and will no longer function
1451 in MongoDB 4.0. Instead, specify no authMechanism and the driver will
1452 use an authentication mechanism compatible with your server.
1453
1454 GSSAPI (Kerberos) Authentication
1455 NOTE:
1456 Kerberos support requires compiling the driver against cyrus-sasl on
1457 UNIX-like environments. On Windows, configure the driver to build
1458 against the Windows Native SSPI.
1459
1460 GSSAPI (Kerberos) authentication is available in the Enterprise Edition
1461 of MongoDB. To authenticate using GSSAPI, the MongoDB C driver must be
1462 installed with SASL support.
1463
1464 On UNIX-like environments, run the kinit command before using the fol‐
1465 lowing authentication methods:
1466
1467 $ kinit mongodbuser@EXAMPLE.COM
1468 mongodbuser@EXAMPLE.COM's Password:
1469 $ klistCredentials cache: FILE:/tmp/krb5cc_1000
1470 Principal: mongodbuser@EXAMPLE.COM
1471
1472 Issued Expires Principal
1473 Feb 9 13:48:51 2013 Feb 9 23:48:51 2013 krbtgt/EXAMPLE.COM@EXAMPLE.COM
1474
1475 Now authenticate using the MongoDB URI. GSSAPI authenticates against
1476 the $external virtual database, so a database does not need to be spec‐
1477 ified in the URI. Note that the Kerberos principal must be URL-encoded:
1478
1479 mongoc_client_t *client;
1480
1481 client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI");
1482
1483 NOTE:
1484 GSSAPI authenticates against the $external database, so specifying
1485 the authSource database is not required.
1486
1487 The driver supports these GSSAPI properties:
1488
1489 · CANONICALIZE_HOST_NAME: This might be required with Cyrus-SASL when
1490 the hosts report different hostnames than what is used in the Ker‐
1491 beros database. The default is "false".
1492
1493 · SERVICE_NAME: Use a different service name than the default, "mon‐
1494 godb".
1495
1496 Set properties in the URL:
1497
1498 mongoc_client_t *client;
1499
1500 client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&"
1501 "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true");
1502
1503 If you encounter errors such as Invalid net address, check if the
1504 application is behind a NAT (Network Address Translation) firewall. If
1505 so, create a ticket that uses forwardable and addressless Kerberos
1506 tickets. This can be done by passing -f -A to kinit.
1507
1508 $ kinit -f -A mongodbuser@EXAMPLE.COM
1509
1510 SASL Plain Authentication
1511 NOTE:
1512 The MongoDB C Driver must be compiled with SASL support in order to
1513 use SASL PLAIN authentication.
1514
1515 MongoDB Enterprise Edition supports the SASL PLAIN authentication mech‐
1516 anism, initially intended for delegating authentication to an LDAP
1517 server. Using the SASL PLAIN mechanism is very similar to the challenge
1518 response mechanism with usernames and passwords. This authentication
1519 mechanism uses the $external virtual database for LDAP support:
1520
1521 NOTE:
1522 SASL PLAIN is a clear-text authentication mechanism. It is strongly
1523 recommended to connect to MongoDB using TLS with certificate valida‐
1524 tion when using the PLAIN mechanism.
1525
1526 mongoc_client_t *client;
1527
1528 client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN");
1529
1530 PLAIN authenticates against the $external database, so specifying the
1531 authSource database is not required.
1532
1533 X.509 Certificate Authentication
1534 NOTE:
1535 The MongoDB C Driver must be compiled with TLS support for X.509
1536 authentication support. Once this is done, start a server with the
1537 following options:
1538
1539 $ mongod --tlsMode requireTLS --tlsCertificateKeyFile server.pem --tlsCAFile ca.pem
1540
1541 The MONGODB-X509 mechanism authenticates a username derived from the
1542 distinguished subject name of the X.509 certificate presented by the
1543 driver during TLS negotiation. This authentication method requires the
1544 use of TLS connections with certificate validation.
1545
1546 mongoc_client_t *client;
1547 mongoc_ssl_opt_t ssl_opts = { 0 };
1548
1549 ssl_opts.pem_file = "mycert.pem";
1550 ssl_opts.pem_pwd = "mycertpassword";
1551 ssl_opts.ca_file = "myca.pem";
1552 ssl_opts.ca_dir = "trust_dir";
1553 ssl_opts.weak_cert_validation = false;
1554
1555 client = mongoc_client_new ("mongodb://x509_derived_username@localhost/?authMechanism=MONGODB-X509");
1556 mongoc_client_set_ssl_opts (client, &ssl_opts);
1557
1558 MONGODB-X509 authenticates against the $external database, so specify‐
1559 ing the authSource database is not required. For more information on
1560 the x509_derived_username, see the MongoDB server x.509 tutorial.
1561
1562 NOTE:
1563 The MongoDB C Driver will attempt to determine the x509 derived
1564 username when none is provided, and as of MongoDB 3.4 providing the
1565 username is not required at all.
1566
1567 Authentication via AWS IAM
1568 The MONGODB-AWS mechanism authenticates to MongoDB servers with creden‐
1569 tials provided by AWS Identity and Access Management (IAM).
1570
1571 To authenticate, create a user with an associated Amazon Resource Name
1572 (ARN) on the $external database, and specify the MONGODB-AWS authMecha‐
1573 nism in the URI.
1574
1575 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost/?authMechanism=MONGODB-AWS");
1576
1577 Since MONGODB-AWS always authenticates against the $external database,
1578 so specifying the authSource database is not required.
1579
1580 Credentials include the access key id, secret access key, and optional
1581 session token. They may be obtained from the following ways.
1582
1583 AWS credentials via URI
1584 Credentials may be passed directly in the URI as username/password.
1585
1586 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://<access key id>:<secret access key>localhost/?authMechanism=MONGODB-AWS");
1587
1588 This may include a session token passed with authMechanismProperties.
1589
1590 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://<access key id>:<secret access key>localhost/?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:<token>");
1591
1592 AWS credentials via environment
1593 If credentials are not passed through the URI, libmongoc will check for
1594 the following environment variables.
1595
1596 · AWS_ACCESS_KEY_ID
1597
1598 · AWS_SECRET_ACCESS_KEY
1599
1600 · AWS_SESSION_TOKEN (optional)
1601
1602 AWS Credentials via ECS
1603 If credentials are not passed in the URI or with environment variables,
1604 libmongoc will check if the environment variable AWS_CONTAINER_CREDEN‐
1605 TIALS_RELATIVE_URI is set, and if so, attempt to retrieve temporary
1606 credentials from the ECS task metadata by querying a link local
1607 address.
1608
1609 AWS Credentials via EC2
1610 If credentials are not passed in the URI or with environment variables,
1611 and the environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is
1612 not set, libmongoc will attempt to retrieve temporary credentials from
1613 the EC2 machine metadata by querying link local addresses.
1614
1615 Basic Troubleshooting
1616 Troubleshooting Checklist
1617 The following is a short list of things to check when you have a prob‐
1618 lem.
1619
1620 · Did you call mongoc_init() in main()? If not, you will likely see a
1621 segfault.
1622
1623 · Have you leaked any clients or cursors as can be found with mon‐
1624 goc-stat <PID>?
1625
1626 · Have packets been delivered to the server? See egress bytes from mon‐
1627 goc-stat <PID>.
1628
1629 · Does valgrind show any leaks? Ensure you call mongoc_cleanup() at the
1630 end of your process to cleanup lingering allocations from the MongoDB
1631 C driver.
1632
1633 · If compiling your own copy of MongoDB C Driver, consider using the
1634 cmake option -DENABLE_TRACING=ON to enable function tracing and hex
1635 dumps of network packets to STDERR and STDOUT.
1636
1637 Performance Counters
1638 The MongoDB C driver comes with an optional unique feature to help
1639 developers and sysadmins troubleshoot problems in production. Perfor‐
1640 mance counters are available for each process using the driver. If
1641 available, the counters can be accessed outside of the application
1642 process via a shared memory segment. This means that you can graph
1643 statistics about your application process easily from tools like Munin
1644 or Nagios. Your author often uses watch --interval=0.5 -d mongoc-stat
1645 $PID to monitor an application.
1646
1647 Performance counters are only available on Linux platforms supporting
1648 shared memory segments. On supported platforms they are enabled by
1649 default. Applications can be built without the counters by specifying
1650 the cmake option -DENABLE_SHM_COUNTERS=OFF. Additionally, if perfor‐
1651 mance counters are already compiled, they can be disabled at runtime by
1652 specifying the environment variable MONGOC_DISABLE_SHM.
1653
1654 Performance counters keep track of the following:
1655
1656 · Active and Disposed Cursors
1657
1658 · Active and Disposed Clients, Client Pools, and Socket Streams.
1659
1660 · Number of operations sent and received, by type.
1661
1662 · Bytes transferred and received.
1663
1664 · Authentication successes and failures.
1665
1666 · Number of wire protocol errors.
1667
1668 To access counters for a given process, simply provide the process id
1669 to the mongoc-stat program installed with the MongoDB C Driver.
1670
1671 $ mongoc-stat 22203
1672 Operations : Egress Total : The number of sent operations. : 13247
1673 Operations : Ingress Total : The number of received operations. : 13246
1674 Operations : Egress Queries : The number of sent Query operations. : 13247
1675 Operations : Ingress Queries : The number of received Query operations. : 0
1676 Operations : Egress GetMore : The number of sent GetMore operations. : 0
1677 Operations : Ingress GetMore : The number of received GetMore operations. : 0
1678 Operations : Egress Insert : The number of sent Insert operations. : 0
1679 Operations : Ingress Insert : The number of received Insert operations. : 0
1680 Operations : Egress Delete : The number of sent Delete operations. : 0
1681 Operations : Ingress Delete : The number of received Delete operations. : 0
1682 Operations : Egress Update : The number of sent Update operations. : 0
1683 Operations : Ingress Update : The number of received Update operations. : 0
1684 Operations : Egress KillCursors : The number of sent KillCursors operations. : 0
1685 Operations : Ingress KillCursors : The number of received KillCursors operations. : 0
1686 Operations : Egress Msg : The number of sent Msg operations. : 0
1687 Operations : Ingress Msg : The number of received Msg operations. : 0
1688 Operations : Egress Reply : The number of sent Reply operations. : 0
1689 Operations : Ingress Reply : The number of received Reply operations. : 13246
1690 Cursors : Active : The number of active cursors. : 1
1691 Cursors : Disposed : The number of disposed cursors. : 13246
1692 Clients : Active : The number of active clients. : 1
1693 Clients : Disposed : The number of disposed clients. : 0
1694 Streams : Active : The number of active streams. : 1
1695 Streams : Disposed : The number of disposed streams. : 0
1696 Streams : Egress Bytes : The number of bytes sent. : 794931
1697 Streams : Ingress Bytes : The number of bytes received. : 589694
1698 Streams : N Socket Timeouts : The number of socket timeouts. : 0
1699 Client Pools : Active : The number of active client pools. : 1
1700 Client Pools : Disposed : The number of disposed client pools. : 0
1701 Protocol : Ingress Errors : The number of protocol errors on ingress. : 0
1702 Auth : Failures : The number of failed authentication requests. : 0
1703 Auth : Success : The number of successful authentication requests. : 0
1704
1705 Submitting a Bug Report
1706 Think you've found a bug? Want to see a new feature in the MongoDB C
1707 driver? Please open a case in our issue management tool, JIRA:
1708
1709 · Create an account and login.
1710
1711 · Navigate to the CDRIVER project.
1712
1713 · Click Create Issue - Please provide as much information as possible
1714 about the issue type and how to reproduce it.
1715
1716 Bug reports in JIRA for all driver projects (i.e. CDRIVER, CSHARP,
1717 JAVA) and the Core Server (i.e. SERVER) project are public.
1718
1719 Guides
1720 Configuring TLS
1721 Configuration with URI options
1722 Enable TLS by including tls=true the URI.
1723
1724 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/");
1725 mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
1726
1727 mongoc_client_t *client = mongoc_client_new_from_uri (uri);
1728
1729 The following URI options may be used to further configure TLS:
1730
1731 ┌────────────────────┬─────────────────────┬─────────────────────┐
1732 │Constant │ Key │ Description │
1733 ├────────────────────┼─────────────────────┼─────────────────────┤
1734 │MONGOC_URI_TLS │ tls │ {true|false}, indi‐ │
1735 │ │ │ cating if TLS must │
1736 │ │ │ be used. │
1737 ├────────────────────┼─────────────────────┼─────────────────────┤
1738 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ Path to PEM format‐ │
1739 │TIFICATEKEYFILE │ file │ ted Private Key, │
1740 │ │ │ with its Public │
1741 │ │ │ Certificate con‐ │
1742 │ │ │ catenated at the │
1743 │ │ │ end. │
1744 ├────────────────────┼─────────────────────┼─────────────────────┤
1745 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ The password, if │
1746 │TIFICATEKEYPASSWORD │ password │ any, to use to │
1747 │ │ │ unlock encrypted │
1748 │ │ │ Private Key. │
1749 ├────────────────────┼─────────────────────┼─────────────────────┤
1750 │MON‐ │ tlscafile │ One, or a bundle │
1751 │GOC_URI_TLSCAFILE │ │ of, Certificate │
1752 │ │ │ Authorities whom │
1753 │ │ │ should be consid‐ │
1754 │ │ │ ered to be trusted. │
1755 ├────────────────────┼─────────────────────┼─────────────────────┤
1756 │MONGOC_URI_TLSAL‐ │ tlsallowinvalidcer‐ │ Accept and ignore │
1757 │LOWINVALIDCERTIFI‐ │ tificates │ certificate verifi‐ │
1758 │CATES │ │ cation errors (e.g. │
1759 │ │ │ untrusted issuer, │
1760 │ │ │ expired, etc.) │
1761 └────────────────────┴─────────────────────┴─────────────────────┘
1762
1763
1764
1765
1766
1767
1768
1769 │MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │ Ignore hostname │
1770 │LOWINVALIDHOSTNAMES │ hostnames │ verification of the │
1771 │ │ │ certificate (e.g. │
1772 │ │ │ Man In The Middle, │
1773 │ │ │ using valid cer‐ │
1774 │ │ │ tificate, but │
1775 │ │ │ issued for another │
1776 │ │ │ hostname) │
1777 ├────────────────────┼─────────────────────┼─────────────────────┤
1778 │MONGOC_URI_TLSINSE‐ │ tlsinsecure │ {true|false}, indi‐ │
1779 │CURE │ │ cating if insecure │
1780 │ │ │ TLS options should │
1781 │ │ │ be used. Currently │
1782 │ │ │ this implies MON‐ │
1783 │ │ │ GOC_URI_TLSALLOWIN‐ │
1784 │ │ │ VALIDCERTIFICATES │
1785 │ │ │ and MON‐ │
1786 │ │ │ GOC_URI_TLSALLOWIN‐ │
1787 │ │ │ VALIDHOSTNAMES. │
1788 ├────────────────────┼─────────────────────┼─────────────────────┤
1789 │MONGOC_URI_TLSDIS‐ │ tlsdisablecertifi‐ │ {true|false}, indi‐ │
1790 │ABLECERTIFICATERE‐ │ caterevocationcheck │ cates if revocation │
1791 │VOCATIONCHECK │ │ checking (CRL / │
1792 │ │ │ OCSP) should be │
1793 │ │ │ disabled. │
1794 ├────────────────────┼─────────────────────┼─────────────────────┤
1795 │MONGOC_URI_TLSDIS‐ │ tlsdisableocspend‐ │ {true|false}, indi‐ │
1796 │ABLEOCSPEND‐ │ pointcheck │ cates if OCSP │
1797 │POINTCHECK │ │ responder endpoints │
1798 │ │ │ should not be │
1799 │ │ │ requested when an │
1800 │ │ │ OCSP response is │
1801 │ │ │ not stapled. │
1802 └────────────────────┴─────────────────────┴─────────────────────┘
1803
1804 Configuration with mongoc_ssl_opt_t
1805 Alternatively, the mongoc_ssl_opt_t struct may be used to configure TLS
1806 with mongoc_client_set_ssl_opts() or mongoc_client_pool_set_ssl_opts().
1807 Most of the configurable options can be set using the Connection String
1808 URI.
1809
1810 ┌───────────────────────┬──────────────────────────┐
1811 │mongoc_ssl_opt_t key │ URI key │
1812 ├───────────────────────┼──────────────────────────┤
1813 │pem_file │ tlsClientCertificateKey‐ │
1814 │ │ File │
1815 ├───────────────────────┼──────────────────────────┤
1816 │pem_pwd │ tlsClientCertificateKey‐ │
1817 │ │ Password │
1818 ├───────────────────────┼──────────────────────────┤
1819 │ca_file │ tlsCAFile │
1820 ├───────────────────────┼──────────────────────────┤
1821 │weak_cert_validation │ tlsAllowInvalidCertifi‐ │
1822 │ │ cates │
1823 ├───────────────────────┼──────────────────────────┤
1824 │allow_invalid_hostname │ tlsAllowInvalidHostnames │
1825 └───────────────────────┴──────────────────────────┘
1826
1827 The only exclusions are crl_file and ca_dir. Those may only be set with
1828 mongoc_ssl_opt_t.
1829
1830 Client Authentication
1831 When MongoDB is started with TLS enabled, it will by default require
1832 the client to provide a client certificate issued by a certificate
1833 authority specified by --tlsCAFile, or an authority trusted by the
1834 native certificate store in use on the server.
1835
1836 To provide the client certificate, set the tlsCertificateKeyFile in the
1837 URI to a PEM armored certificate file.
1838
1839 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/");
1840 mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
1841 mongoc_uri_set_option_as_utf8 (uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, "/path/to/client-certificate.pem");
1842
1843 mongoc_client_t *client = mongoc_client_new_from_uri (uri);
1844
1845 Server Certificate Verification
1846 The MongoDB C Driver will automatically verify the validity of the
1847 server certificate, such as issued by configured Certificate Authority,
1848 hostname validation, and expiration.
1849
1850 To overwrite this behavior, it is possible to disable hostname valida‐
1851 tion, OCSP endpoint revocation checking, revocation checking entirely,
1852 and allow invalid certificates.
1853
1854 This behavior is controlled using the tlsAllowInvalidHostnames, tlsDis‐
1855 ableOCSPEndpointCheck, tlsDisableCertificateRevocationCheck, and tlsAl‐
1856 lowInvalidCertificates options respectively. By default, all are set to
1857 false.
1858
1859 It is not recommended to change these defaults as it exposes the client
1860 to Man In The Middle attacks (when tlsAllowInvalidHostnames is set),
1861 invalid certificates (when tlsAllowInvalidCertificates is set), or
1862 potentially revoked certificates (when tlsDisableOCSPEndpointCheck or
1863 tlsDisableCertificateRevocationCheck are set).
1864
1865 Supported Libraries
1866 By default, libmongoc will attempt to find a supported TLS library and
1867 enable TLS support. This is controlled by the cmake flag ENABLE_SSL,
1868 which is set to AUTO by default. Valid values are:
1869
1870 · AUTO the default behavior. Link to the system's native TLS library,
1871 or attempt to find OpenSSL.
1872
1873 · DARWIN link to Secure Transport, the native TLS library on macOS.
1874
1875 · WINDOWS link to Secure Channel, the native TLS library on Windows.
1876
1877 · OPENSSL link to OpenSSL (libssl). An optional install path may be
1878 specified with OPENSSL_ROOT.
1879
1880 · LIBRESSL link to LibreSSL's libtls. (LibreSSL's compatible libssl may
1881 be linked to by setting OPENSSL).
1882
1883 · OFF disable TLS support.
1884
1885 OpenSSL
1886 The MongoDB C Driver uses OpenSSL, if available, on Linux and Unix
1887 platforms (besides macOS). Industry best practices and some regulations
1888 require the use of TLS 1.1 or newer, which requires at least OpenSSL
1889 1.0.1. Check your OpenSSL version like so:
1890
1891 $ openssl version
1892
1893 Ensure your system's OpenSSL is a recent version (at least 1.0.1), or
1894 install a recent version in a non-system path and build against it
1895 with:
1896
1897 cmake -DOPENSSL_ROOT_DIR=/absolute/path/to/openssl
1898
1899 When compiled against OpenSSL, the driver will attempt to load the sys‐
1900 tem default certificate store, as configured by the distribution. That
1901 can be overridden by setting the tlsCAFile URI option or with the
1902 fields ca_file and ca_dir in the mongoc_ssl_opt_t.
1903
1904 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is fully
1905 supported when using OpenSSL 1.0.1+ with the following notes:
1906
1907 · When a crl_file is set with mongoc_ssl_opt_t, and the crl_file
1908 revokes the server's certificate, the certificate is considered
1909 revoked (even if the certificate has a valid stapled OCSP response)
1910
1911 LibreSSL / libtls
1912 The MongoDB C Driver supports LibreSSL through the use of OpenSSL com‐
1913 patibility checks when configured to compile against openssl. It also
1914 supports the new libtls library when configured to build against
1915 libressl.
1916
1917 When compiled against the Windows native libraries, the crl_file option
1918 of a mongoc_ssl_opt_t is not supported, and will issue an error if
1919 used.
1920
1921 Setting tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevoca‐
1922 tionCheck has no effect.
1923
1924 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
1925 tially supported with the following notes:
1926
1927 · The Must-Staple extension (see RFC 7633) is ignored. Connection may
1928 continue if a Must-Staple certificate is presented with no stapled
1929 response (unless the client receives a revoked response from an OCSP
1930 responder).
1931
1932 · Connection will continue if a Must-Staple certificate is presented
1933 without a stapled response and the OCSP responder is down.
1934
1935 Native TLS Support on Windows (Secure Channel)
1936 The MongoDB C Driver supports the Windows native TLS library (Secure
1937 Channel, or SChannel), and its native crypto library (Cryptography API:
1938 Next Generation, or CNG).
1939
1940 When compiled against the Windows native libraries, the ca_dir option
1941 of a mongoc_ssl_opt_t is not supported, and will issue an error if
1942 used.
1943
1944 Encrypted PEM files (e.g., setting tlsCertificateKeyPassword) are also
1945 not supported, and will result in error when attempting to load them.
1946
1947 When tlsCAFile is set, the driver will only allow server certificates
1948 issued by the authority (or authorities) provided. When no tlsCAFile is
1949 set, the driver will look up the Certificate Authority using the System
1950 Local Machine Root certificate store to confirm the provided certifi‐
1951 cate.
1952
1953 When crl_file is set with mongoc_ssl_opt_t, the driver will import the
1954 revocation list to the System Local Machine Root certificate store.
1955
1956 Setting tlsDisableOCSPEndpointCheck has no effect.
1957
1958 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
1959 tially supported with the following notes:
1960
1961 · The Must-Staple extension (see RFC 7633) is ignored. Connection may
1962 continue if a Must-Staple certificate is presented with no stapled
1963 response (unless the client receives a revoked response from an OCSP
1964 responder).
1965
1966 · When a crl_file is set with mongoc_ssl_opt_t, and the crl_file
1967 revokes the server's certificate, the OCSP response takes precedence.
1968 E.g. if the server presents a certificate with a valid stapled OCSP
1969 response, the certificate is considered valid even if the crl_file
1970 marks it as revoked.
1971
1972 · Connection will continue if a Must-Staple certificate is presented
1973 without a stapled response and the OCSP responder is down.
1974
1975 Native TLS Support on macOS / Darwin (Secure Transport)
1976 The MongoDB C Driver supports the Darwin (OS X, macOS, iOS, etc.)
1977 native TLS library (Secure Transport), and its native crypto library
1978 (Common Crypto, or CC).
1979
1980 When compiled against Secure Transport, the ca_dir and crl_file options
1981 of a mongoc_ssl_opt_t are not supported. An error is issued if either
1982 are used.
1983
1984 When tlsCAFile is set, the driver will only allow server certificates
1985 issued by the authority (or authorities) provided. When no tlsCAFile is
1986 set, the driver will use the Certificate Authorities in the currently
1987 unlocked keychains.
1988
1989 Setting tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevoca‐
1990 tionCheck has no effect.
1991
1992 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
1993 tially supported with the following notes.
1994
1995 · The Must-Staple extension (see RFC 7633) is ignored. Connection may
1996 continue if a Must-Staple certificate is presented with no stapled
1997 response (unless the client receives a revoked response from an OCSP
1998 responder).
1999
2000 · Connection will continue if a Must-Staple certificate is presented
2001 without a stapled response and the OCSP responder is down.
2002
2003 Common Tasks
2004 Drivers for some other languages provide helper functions to perform
2005 certain common tasks. In the C Driver we must explicitly build commands
2006 to send to the server.
2007
2008 Setup
2009 First we'll write some code to insert sample data:
2010
2011 doc-common-insert.c
2012
2013 /* Don't try to compile this file on its own. It's meant to be #included
2014 by example code */
2015
2016 /* Insert some sample data */
2017 bool
2018 insert_data (mongoc_collection_t *collection)
2019 {
2020 mongoc_bulk_operation_t *bulk;
2021 enum N { ndocs = 4 };
2022 bson_t *docs[ndocs];
2023 bson_error_t error;
2024 int i = 0;
2025 bool ret;
2026
2027 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2028
2029 docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
2030 docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
2031 docs[2] = BCON_NEW (
2032 "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
2033 docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
2034
2035 for (i = 0; i < ndocs; i++) {
2036 mongoc_bulk_operation_insert (bulk, docs[i]);
2037 bson_destroy (docs[i]);
2038 docs[i] = NULL;
2039 }
2040
2041 ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
2042
2043 if (!ret) {
2044 fprintf (stderr, "Error inserting data: %s\n", error.message);
2045 }
2046
2047 mongoc_bulk_operation_destroy (bulk);
2048 return ret;
2049 }
2050
2051 /* A helper which we'll use a lot later on */
2052 void
2053 print_res (const bson_t *reply)
2054 {
2055 char *str;
2056 BSON_ASSERT (reply);
2057 str = bson_as_canonical_extended_json (reply, NULL);
2058 printf ("%s\n", str);
2059 bson_free (str);
2060 }
2061
2062
2063 explain Command
2064 This is how to use the explain command in MongoDB 3.2+:
2065
2066 explain.c
2067
2068 bool
2069 explain (mongoc_collection_t *collection)
2070 {
2071 bson_t *command;
2072 bson_t reply;
2073 bson_error_t error;
2074 bool res;
2075
2076 command = BCON_NEW ("explain",
2077 "{",
2078 "find",
2079 BCON_UTF8 (COLLECTION_NAME),
2080 "filter",
2081 "{",
2082 "x",
2083 BCON_INT32 (1),
2084 "}",
2085 "}");
2086 res = mongoc_collection_command_simple (
2087 collection, command, NULL, &reply, &error);
2088 if (!res) {
2089 fprintf (stderr, "Error with explain: %s\n", error.message);
2090 goto cleanup;
2091 }
2092
2093 /* Do something with the reply */
2094 print_res (&reply);
2095
2096 cleanup:
2097 bson_destroy (&reply);
2098 bson_destroy (command);
2099 return res;
2100 }
2101
2102
2103 Running the Examples
2104 common-operations.c
2105
2106 /*
2107 * Copyright 2016 MongoDB, Inc.
2108 *
2109 * Licensed under the Apache License, Version 2.0 (the "License");
2110 * you may not use this file except in compliance with the License.
2111 * You may obtain a copy of the License at
2112 *
2113 * http://www.apache.org/licenses/LICENSE-2.0
2114 *
2115 * Unless required by applicable law or agreed to in writing, software
2116 * distributed under the License is distributed on an "AS IS" BASIS,
2117 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2118 * See the License for the specific language governing permissions and
2119 * limitations under the License.
2120 */
2121
2122
2123 #include <mongoc/mongoc.h>
2124 #include <stdio.h>
2125
2126
2127 const char *COLLECTION_NAME = "things";
2128
2129 #include "../doc-common-insert.c"
2130 #include "explain.c"
2131
2132
2133 int
2134 main (int argc, char *argv[])
2135 {
2136 mongoc_database_t *database = NULL;
2137 mongoc_client_t *client = NULL;
2138 mongoc_collection_t *collection = NULL;
2139 mongoc_uri_t *uri = NULL;
2140 bson_error_t error;
2141 char *host_and_port;
2142 int res = 0;
2143
2144 if (argc < 2 || argc > 3) {
2145 fprintf (stderr,
2146 "usage: %s MONGOD-1-CONNECTION-STRING "
2147 "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
2148 argv[0]);
2149 fprintf (stderr,
2150 "MONGOD-1-CONNECTION-STRING can be "
2151 "of the following forms:\n");
2152 fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
2153 fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
2154 fprintf (stderr,
2155 "mongodb://user:pass@localhost:27017\t"
2156 "local machine on port 27017, and authenticate with username "
2157 "user and password pass\n");
2158 return EXIT_FAILURE;
2159 }
2160
2161 mongoc_init ();
2162
2163 if (strncmp (argv[1], "mongodb://", 10) == 0) {
2164 host_and_port = bson_strdup (argv[1]);
2165 } else {
2166 host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
2167 }
2168
2169 uri = mongoc_uri_new_with_error (host_and_port, &error);
2170 if (!uri) {
2171 fprintf (stderr,
2172 "failed to parse URI: %s\n"
2173 "error message: %s\n",
2174 host_and_port,
2175 error.message);
2176 res = EXIT_FAILURE;
2177 goto cleanup;
2178 }
2179
2180 client = mongoc_client_new_from_uri (uri);
2181 if (!client) {
2182 res = EXIT_FAILURE;
2183 goto cleanup;
2184 }
2185
2186 mongoc_client_set_error_api (client, 2);
2187 database = mongoc_client_get_database (client, "test");
2188 collection = mongoc_database_get_collection (database, COLLECTION_NAME);
2189
2190 printf ("Inserting data\n");
2191 if (!insert_data (collection)) {
2192 res = EXIT_FAILURE;
2193 goto cleanup;
2194 }
2195
2196 printf ("explain\n");
2197 if (!explain (collection)) {
2198 res = EXIT_FAILURE;
2199 goto cleanup;
2200 }
2201
2202 cleanup:
2203 if (collection) {
2204 mongoc_collection_destroy (collection);
2205 }
2206
2207 if (database) {
2208 mongoc_database_destroy (database);
2209 }
2210
2211 if (client) {
2212 mongoc_client_destroy (client);
2213 }
2214
2215 if (uri) {
2216 mongoc_uri_destroy (uri);
2217 }
2218
2219 bson_free (host_and_port);
2220 mongoc_cleanup ();
2221 return res;
2222 }
2223
2224
2225 First launch two separate instances of mongod (must be done from sepa‐
2226 rate shells):
2227
2228 $ mongod
2229
2230 $ mkdir /tmp/db2
2231 $ mongod --dbpath /tmp/db2 --port 27018 # second instance
2232
2233 Now compile and run the example program:
2234
2235 $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
2236 Inserting data
2237 explain
2238 {
2239 "executionStats" : {
2240 "allPlansExecution" : [],
2241 "executionStages" : {
2242 "advanced" : 19,
2243 "direction" : "forward" ,
2244 "docsExamined" : 76,
2245 "executionTimeMillisEstimate" : 0,
2246 "filter" : {
2247 "x" : {
2248 "$eq" : 1
2249 }
2250 },
2251 "invalidates" : 0,
2252 "isEOF" : 1,
2253 "nReturned" : 19,
2254 "needTime" : 58,
2255 "needYield" : 0,
2256 "restoreState" : 0,
2257 "saveState" : 0,
2258 "stage" : "COLLSCAN" ,
2259 "works" : 78
2260 },
2261 "executionSuccess" : true,
2262 "executionTimeMillis" : 0,
2263 "nReturned" : 19,
2264 "totalDocsExamined" : 76,
2265 "totalKeysExamined" : 0
2266 },
2267 "ok" : 1,
2268 "queryPlanner" : {
2269 "indexFilterSet" : false,
2270 "namespace" : "test.things",
2271 "parsedQuery" : {
2272 "x" : {
2273 "$eq" : 1
2274 }
2275 },
2276 "plannerVersion" : 1,
2277 "rejectedPlans" : [],
2278 "winningPlan" : {
2279 "direction" : "forward" ,
2280 "filter" : {
2281 "x" : {
2282 "$eq" : 1
2283 }
2284 },
2285 "stage" : "COLLSCAN"
2286 }
2287 },
2288 "serverInfo" : {
2289 "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
2290 "host" : "MacBook-Pro-57.local",
2291 "port" : 27017,
2292 "version" : "3.2.6"
2293 }
2294 }
2295
2296 Advanced Connections
2297 The following guide contains information specific to certain types of
2298 MongoDB configurations.
2299
2300 For an example of connecting to a simple standalone server, see the
2301 Tutorial. To establish a connection with authentication options
2302 enabled, see the Authentication page.
2303
2304 Connecting to a Replica Set
2305 Connecting to a replica set is much like connecting to a standalone
2306 MongoDB server. Simply specify the replica set name using the ?repli‐
2307 caSet=myreplset URI option.
2308
2309 #include <bson/bson.h>
2310 #include <mongoc/mongoc.h>
2311
2312 int
2313 main (int argc, char *argv[])
2314 {
2315 mongoc_client_t *client;
2316
2317 mongoc_init ();
2318
2319 /* Create our MongoDB Client */
2320 client = mongoc_client_new (
2321 "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");
2322
2323 /* Do some work */
2324 /* TODO */
2325
2326 /* Clean up */
2327 mongoc_client_destroy (client);
2328 mongoc_cleanup ();
2329
2330 return 0;
2331 }
2332
2333 TIP:
2334 Multiple hostnames can be specified in the MongoDB connection string
2335 URI, with a comma separating hosts in the seed list.
2336
2337 It is recommended to use a seed list of members of the replica set
2338 to allow the driver to connect to any node.
2339
2340 Connecting to a Sharded Cluster
2341 To connect to a sharded cluster, specify the mongos nodes the client
2342 should connect to. The C Driver will automatically detect that it has
2343 connected to a mongos sharding server.
2344
2345 If more than one hostname is specified, a seed list will be created to
2346 attempt failover between the mongos instances.
2347
2348 WARNING:
2349 Specifying the replicaSet parameter when connecting to a mongos
2350 sharding server is invalid.
2351
2352 #include <bson/bson.h>
2353 #include <mongoc/mongoc.h>
2354
2355 int
2356 main (int argc, char *argv[])
2357 {
2358 mongoc_client_t *client;
2359
2360 mongoc_init ();
2361
2362 /* Create our MongoDB Client */
2363 client = mongoc_client_new ("mongodb://myshard01:27017/");
2364
2365 /* Do something with client ... */
2366
2367 /* Free the client */
2368 mongoc_client_destroy (client);
2369
2370 mongoc_cleanup ();
2371
2372 return 0;
2373 }
2374
2375 Connecting to an IPv6 Address
2376 The MongoDB C Driver will automatically resolve IPv6 addresses from
2377 host names. However, to specify an IPv6 address directly, wrap the
2378 address in [].
2379
2380 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");
2381
2382 Connecting with IPv4 and IPv6
2383 If connecting to a hostname that has both IPv4 and IPv6 DNS records,
2384 the behavior follows RFC-6555. A connection to the IPv6 address is
2385 attempted first. If IPv6 fails, then a connection is attempted to the
2386 IPv4 address. If the connection attempt to IPv6 does not complete
2387 within 250ms, then IPv4 is tried in parallel. Whichever succeeds con‐
2388 nection first cancels the other. The successful DNS result is cached
2389 for 10 minutes.
2390
2391 As a consequence, attempts to connect to a mongod only listening on
2392 IPv4 may be delayed if there are both A (IPv4) and AAAA (IPv6) DNS
2393 records associated with the host.
2394
2395 To avoid a delay, configure hostnames to match the MongoDB configura‐
2396 tion. That is, only create an A record if the mongod is only listening
2397 on IPv4.
2398
2399 Connecting to a UNIX Domain Socket
2400 On UNIX-like systems, the C Driver can connect directly to a MongoDB
2401 server using a UNIX domain socket. Pass the URL-encoded path to the
2402 socket, which must be suffixed with .sock. For example, to connect to a
2403 domain socket at /tmp/mongodb-27017.sock:
2404
2405 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");
2406
2407 Include username and password like so:
2408
2409 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");
2410
2411 Connecting to a server over TLS
2412 These are instructions for configuring TLS/SSL connections.
2413
2414 To run a server locally (on port 27017, for example):
2415
2416 $ mongod --port 27017 --tlsMode requireTLS --tlsCertificateKeyFile server.pem --tlsCAFile ca.pem
2417
2418 Add /?tls=true to the end of a client URI.
2419
2420 mongoc_client_t *client = NULL;
2421 client = mongoc_client_new ("mongodb://localhost:27017/?tls=true");
2422
2423 MongoDB requires client certificates by default, unless the --tlsAllow‐
2424 ConnectionsWithoutCertificates is provided. The C Driver can be config‐
2425 ured to present a client certificate using the URI option tlsCertifi‐
2426 cateKeyFile, which may be referenced through the constant MON‐
2427 GOC_URI_TLSCERTIFICATEKEYFILE.
2428
2429 mongoc_client_t *client = NULL;
2430 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/?tls=true");
2431 mongoc_uri_set_option_as_utf8 (uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, "client.pem");
2432
2433 client = mongoc_client_new_from_uri (uri);
2434
2435 The client certificate provided by tlsCertificateKeyFile must be issued
2436 by one of the server trusted Certificate Authorities listed in
2437 --tlsCAFile, or issued by a CA in the native certificate store on the
2438 server when omitted.
2439
2440 See configuring_tls for more information on the various TLS related
2441 options.
2442
2443 Compressing data to and from MongoDB
2444 MongoDB 3.4 added Snappy compression support, zlib compression in 3.6,
2445 and zstd compression in 4.2. To enable compression support the client
2446 must be configured with which compressors to use:
2447
2448 mongoc_client_t *client = NULL;
2449 client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib,zstd");
2450
2451 The compressors option specifies the priority order of compressors the
2452 client wants to use. Messages are compressed if the client and server
2453 share any compressors in common.
2454
2455 Note that the compressor used by the server might not be the same com‐
2456 pressor as the client used. For example, if the client uses the con‐
2457 nection string compressors=zlib,snappy the client will use zlib com‐
2458 pression to send data (if possible), but the server might still reply
2459 using snappy, depending on how the server was configured.
2460
2461 The driver must be built with zlib and/or snappy and/or zstd support to
2462 enable compression support, any unknown (or not compiled in) compressor
2463 value will be ignored. Note: to build with zstd requires cmake 3.12 or
2464 higher.
2465
2466 Additional Connection Options
2467 The full list of connection options can be found in the mongoc_uri_t
2468 docs.
2469
2470 Certain socket/connection related options are not configurable:
2471
2472 ┌──────────────┬─────────────────────┬─────────────────────┐
2473 │Option │ Description │ Value │
2474 ├──────────────┼─────────────────────┼─────────────────────┤
2475 │SO_KEEPALIVE │ TCP Keep Alive │ Enabled │
2476 ├──────────────┼─────────────────────┼─────────────────────┤
2477 │TCP_KEEPIDLE │ How long a connec‐ │ 120 seconds │
2478 │ │ tion needs to │ │
2479 │ │ remain idle before │ │
2480 │ │ TCP starts sending │ │
2481 │ │ keepalive probes │ │
2482 ├──────────────┼─────────────────────┼─────────────────────┤
2483 │TCP_KEEPINTVL │ The time in seconds │ 10 seconds │
2484 │ │ between TCP probes │ │
2485 ├──────────────┼─────────────────────┼─────────────────────┤
2486 │TCP_KEEPCNT │ How many probes to │ 9 probes │
2487 │ │ send, without │ │
2488 │ │ acknowledgement, │ │
2489 │ │ before dropping the │ │
2490 │ │ connection │ │
2491 └──────────────┴─────────────────────┴─────────────────────┘
2492
2493
2494
2495
2496
2497
2498 │TCP_NODELAY │ Send packets as │ Enabled (no buffer‐ │
2499 │ │ soon as possible or │ ing) │
2500 │ │ buffer small pack‐ │ │
2501 │ │ ets (Nagle algo‐ │ │
2502 │ │ rithm) │ │
2503 └──────────────┴─────────────────────┴─────────────────────┘
2504
2505 Connection Pooling
2506 The MongoDB C driver has two connection modes: single-threaded and
2507 pooled. Single-threaded mode is optimized for embedding the driver
2508 within languages like PHP. Multi-threaded programs should use pooled
2509 mode: this mode minimizes the total connection count, and in pooled
2510 mode background threads monitor the MongoDB server topology, so the
2511 program need not block to scan it.
2512
2513 Single Mode
2514 In single mode, your program creates a mongoc_client_t directly:
2515
2516 mongoc_client_t *client = mongoc_client_new (
2517 "mongodb://hostA,hostB/?replicaSet=my_rs");
2518
2519 The client connects on demand when your program first uses it for a
2520 MongoDB operation. Using a non-blocking socket per server, it begins a
2521 check on each server concurrently, and uses the asynchronous poll or
2522 select function to receive events from the sockets, until all have
2523 responded or timed out. Put another way, in single-threaded mode the C
2524 Driver fans out to begin all checks concurrently, then fans in once all
2525 checks have completed or timed out. Once the scan completes, the client
2526 executes your program's operation and returns.
2527
2528 In single mode, the client re-scans the server topology roughly once
2529 per minute. If more than a minute has elapsed since the previous scan,
2530 the next operation on the client will block while the client completes
2531 its scan. This interval is configurable with heartbeatFrequencyMS in
2532 the connection string. (See mongoc_uri_t.)
2533
2534 A single client opens one connection per server in your topology: these
2535 connections are used both for scanning the topology and performing nor‐
2536 mal operations.
2537
2538 Pooled Mode
2539 To activate pooled mode, create a mongoc_client_pool_t:
2540
2541 mongoc_uri_t *uri = mongoc_uri_new (
2542 "mongodb://hostA,hostB/?replicaSet=my_rs");
2543
2544 mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
2545
2546 When your program first calls mongoc_client_pool_pop, the pool launches
2547 monitoring threads in the background. Monitoring threads independently
2548 connect to all servers in the connection string. As monitoring threads
2549 receive ismaster responses from the servers, they update the shared
2550 view of the server topology. Additional monitoring threads and connec‐
2551 tions are created as new servers are discovered. Monitoring threads are
2552 terminated when servers are removed from the shared view of the server
2553 topology.
2554
2555 Each thread that executes MongoDB operations must check out a client
2556 from the pool:
2557
2558 mongoc_client_t *client = mongoc_client_pool_pop (pool);
2559
2560 /* use the client for operations ... */
2561
2562 mongoc_client_pool_push (pool, client);
2563
2564 The mongoc_client_t object is not thread-safe, only the mon‐
2565 goc_client_pool_t is.
2566
2567 When the driver is in pooled mode, your program's operations are
2568 unblocked as soon as monitoring discovers a usable server. For example,
2569 if a thread in your program is waiting to execute an "insert" on the
2570 primary, it is unblocked as soon as the primary is discovered, rather
2571 than waiting for all secondaries to be checked as well.
2572
2573 The pool opens one connection per server for monitoring, and each
2574 client opens its own connection to each server it uses for application
2575 operations. Background monitoring threads re-scan servers independently
2576 roughly every 10 seconds. This interval is configurable with heartbeat‐
2577 FrequencyMS in the connection string. (See mongoc_uri_t.)
2578
2579 The connection string can also specify waitQueueTimeoutMS to limit the
2580 time that mongoc_client_pool_pop will wait for a client from the pool.
2581 (See mongoc_uri_t.) If waitQueueTimeoutMS is specified, then it is
2582 necessary to confirm that a client was actually returned:
2583
2584 mongoc_uri_t *uri = mongoc_uri_new (
2585 "mongodb://hostA,hostB/?replicaSet=my_rs&waitQueueTimeoutMS=1000");
2586
2587 mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
2588
2589 mongoc_client_t *client = mongoc_client_pool_pop (pool);
2590
2591 if (client) {
2592 /* use the client for operations ... */
2593
2594 mongoc_client_pool_push (pool, client);
2595 } else {
2596 /* take appropriate action for a timeout */
2597 }
2598
2599 See connection_pool_options to configure pool size and behavior, and
2600 see mongoc_client_pool_t for an extended example of a multi-threaded
2601 program that uses the driver in pooled mode.
2602
2603 Cursors
2604 Handling Cursor Failures
2605 Cursors exist on a MongoDB server. However, the mongoc_cursor_t struc‐
2606 ture gives the local process a handle to the cursor. It is possible for
2607 errors to occur on the server while iterating a cursor on the client.
2608 Even a network partition may occur. This means that applications should
2609 be robust in handling cursor failures.
2610
2611 While iterating cursors, you should check to see if an error has
2612 occurred. See the following example for how to robustly check for
2613 errors.
2614
2615 static void
2616 print_all_documents (mongoc_collection_t *collection)
2617 {
2618 mongoc_cursor_t *cursor;
2619 const bson_t *doc;
2620 bson_error_t error;
2621 bson_t query = BSON_INITIALIZER;
2622 char *str;
2623
2624 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
2625
2626 while (mongoc_cursor_next (cursor, &doc)) {
2627 str = bson_as_canonical_extended_json (doc, NULL);
2628 printf ("%s\n", str);
2629 bson_free (str);
2630 }
2631
2632 if (mongoc_cursor_error (cursor, &error)) {
2633 fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
2634 }
2635
2636 mongoc_cursor_destroy (cursor);
2637 }
2638
2639 Destroying Server-Side Cursors
2640 The MongoDB C driver will automatically destroy a server-side cursor
2641 when mongoc_cursor_destroy() is called. Failure to call this function
2642 when done with a cursor will leak memory client side as well as consume
2643 extra memory server side. If the cursor was configured to never time‐
2644 out, it will become a memory leak on the server.
2645
2646 Tailable Cursors
2647 Tailable cursors are cursors that remain open even after they've
2648 returned a final result. This way, if more documents are added to a
2649 collection (i.e., to the cursor's result set), then you can continue to
2650 call mongoc_cursor_next() to retrieve those additional results.
2651
2652 Here's a complete test case that demonstrates the use of tailable cur‐
2653 sors.
2654
2655 NOTE:
2656 Tailable cursors are for capped collections only.
2657
2658 An example to tail the oplog from a replica set.
2659
2660 mongoc-tail.c
2661
2662 #include <bson/bson.h>
2663 #include <mongoc/mongoc.h>
2664 #include <stdio.h>
2665 #include <stdlib.h>
2666
2667 #ifdef _WIN32
2668 #define sleep(_n) Sleep ((_n) *1000)
2669 #endif
2670
2671
2672 static void
2673 print_bson (const bson_t *b)
2674 {
2675 char *str;
2676
2677 str = bson_as_canonical_extended_json (b, NULL);
2678 fprintf (stdout, "%s\n", str);
2679 bson_free (str);
2680 }
2681
2682
2683 static mongoc_cursor_t *
2684 query_collection (mongoc_collection_t *collection, uint32_t last_time)
2685 {
2686 mongoc_cursor_t *cursor;
2687 bson_t query;
2688 bson_t gt;
2689 bson_t opts;
2690
2691 BSON_ASSERT (collection);
2692
2693 bson_init (&query);
2694 BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", >);
2695 BSON_APPEND_TIMESTAMP (>, "$gt", last_time, 0);
2696 bson_append_document_end (&query, >);
2697
2698 bson_init (&opts);
2699 BSON_APPEND_BOOL (&opts, "tailable", true);
2700 BSON_APPEND_BOOL (&opts, "awaitData", true);
2701
2702 cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
2703
2704 bson_destroy (&query);
2705 bson_destroy (&opts);
2706
2707 return cursor;
2708 }
2709
2710
2711 static void
2712 tail_collection (mongoc_collection_t *collection)
2713 {
2714 mongoc_cursor_t *cursor;
2715 uint32_t last_time;
2716 const bson_t *doc;
2717 bson_error_t error;
2718 bson_iter_t iter;
2719
2720 BSON_ASSERT (collection);
2721
2722 last_time = (uint32_t) time (NULL);
2723
2724 while (true) {
2725 cursor = query_collection (collection, last_time);
2726 while (!mongoc_cursor_error (cursor, &error) &&
2727 mongoc_cursor_more (cursor)) {
2728 if (mongoc_cursor_next (cursor, &doc)) {
2729 if (bson_iter_init_find (&iter, doc, "ts") &&
2730 BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
2731 bson_iter_timestamp (&iter, &last_time, NULL);
2732 }
2733 print_bson (doc);
2734 }
2735 }
2736 if (mongoc_cursor_error (cursor, &error)) {
2737 if (error.domain == MONGOC_ERROR_SERVER) {
2738 fprintf (stderr, "%s\n", error.message);
2739 exit (1);
2740 }
2741 }
2742
2743 mongoc_cursor_destroy (cursor);
2744 sleep (1);
2745 }
2746 }
2747
2748
2749 int
2750 main (int argc, char *argv[])
2751 {
2752 mongoc_collection_t *collection;
2753 mongoc_client_t *client;
2754 mongoc_uri_t *uri;
2755 bson_error_t error;
2756
2757 if (argc != 2) {
2758 fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
2759 return EXIT_FAILURE;
2760 }
2761
2762 mongoc_init ();
2763
2764 uri = mongoc_uri_new_with_error (argv[1], &error);
2765 if (!uri) {
2766 fprintf (stderr,
2767 "failed to parse URI: %s\n"
2768 "error message: %s\n",
2769 argv[1],
2770 error.message);
2771 return EXIT_FAILURE;
2772 }
2773
2774 client = mongoc_client_new_from_uri (uri);
2775 if (!client) {
2776 return EXIT_FAILURE;
2777 }
2778
2779 mongoc_client_set_error_api (client, 2);
2780
2781 collection = mongoc_client_get_collection (client, "local", "oplog.rs");
2782
2783 tail_collection (collection);
2784
2785 mongoc_collection_destroy (collection);
2786 mongoc_uri_destroy (uri);
2787 mongoc_client_destroy (client);
2788
2789 return EXIT_SUCCESS;
2790 }
2791
2792
2793 Let's compile and run this example against a replica set to see updates
2794 as they are made.
2795
2796 $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
2797 $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
2798 {
2799 "h" : -8458503739429355503,
2800 "ns" : "test.test",
2801 "o" : {
2802 "_id" : {
2803 "$oid" : "5372ab0a25164be923d10d50"
2804 }
2805 },
2806 "op" : "i",
2807 "ts" : {
2808 "$timestamp" : {
2809 "i" : 1,
2810 "t" : 1400023818
2811 }
2812 },
2813 "v" : 2
2814 }
2815
2816 The line of output is a sample from performing db.test.insert({}) from
2817 the mongo shell on the replica set.
2818
2819 See also mongoc_cursor_set_max_await_time_ms.
2820
2821 Bulk Write Operations
2822 This tutorial explains how to take advantage of MongoDB C driver bulk
2823 write operation features. Executing write operations in batches reduces
2824 the number of network round trips, increasing write throughput.
2825
2826 Bulk Insert
2827 First we need to fetch a bulk operation handle from the mongoc_collec‐
2828 tion_t.
2829
2830 mongoc_bulk_operation_t *bulk =
2831 mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2832
2833 We can now start inserting documents to the bulk operation. These will
2834 be buffered until we execute the operation.
2835
2836 The bulk operation will coalesce insertions as a single batch for each
2837 consecutive call to mongoc_bulk_operation_insert(). This creates a
2838 pipelined effect when possible.
2839
2840 To execute the bulk operation and receive the result we call mon‐
2841 goc_bulk_operation_execute().
2842
2843 bulk1.c
2844
2845 #include <assert.h>
2846 #include <mongoc/mongoc.h>
2847 #include <stdio.h>
2848
2849 static void
2850 bulk1 (mongoc_collection_t *collection)
2851 {
2852 mongoc_bulk_operation_t *bulk;
2853 bson_error_t error;
2854 bson_t *doc;
2855 bson_t reply;
2856 char *str;
2857 bool ret;
2858 int i;
2859
2860 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2861
2862 for (i = 0; i < 10000; i++) {
2863 doc = BCON_NEW ("i", BCON_INT32 (i));
2864 mongoc_bulk_operation_insert (bulk, doc);
2865 bson_destroy (doc);
2866 }
2867
2868 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2869
2870 str = bson_as_canonical_extended_json (&reply, NULL);
2871 printf ("%s\n", str);
2872 bson_free (str);
2873
2874 if (!ret) {
2875 fprintf (stderr, "Error: %s\n", error.message);
2876 }
2877
2878 bson_destroy (&reply);
2879 mongoc_bulk_operation_destroy (bulk);
2880 }
2881
2882 int
2883 main (int argc, char *argv[])
2884 {
2885 mongoc_client_t *client;
2886 mongoc_collection_t *collection;
2887 const char *uri_string = "mongodb://localhost/?appname=bulk1-example";
2888 mongoc_uri_t *uri;
2889 bson_error_t error;
2890
2891 mongoc_init ();
2892
2893 uri = mongoc_uri_new_with_error (uri_string, &error);
2894 if (!uri) {
2895 fprintf (stderr,
2896 "failed to parse URI: %s\n"
2897 "error message: %s\n",
2898 uri_string,
2899 error.message);
2900 return EXIT_FAILURE;
2901 }
2902
2903 client = mongoc_client_new_from_uri (uri);
2904 if (!client) {
2905 return EXIT_FAILURE;
2906 }
2907
2908 mongoc_client_set_error_api (client, 2);
2909 collection = mongoc_client_get_collection (client, "test", "test");
2910
2911 bulk1 (collection);
2912
2913 mongoc_uri_destroy (uri);
2914 mongoc_collection_destroy (collection);
2915 mongoc_client_destroy (client);
2916
2917 mongoc_cleanup ();
2918
2919 return EXIT_SUCCESS;
2920 }
2921
2922
2923 Example reply document:
2924
2925 {"nInserted" : 10000,
2926 "nMatched" : 0,
2927 "nModified" : 0,
2928 "nRemoved" : 0,
2929 "nUpserted" : 0,
2930 "writeErrors" : []
2931 "writeConcernErrors" : [] }
2932
2933 Mixed Bulk Write Operations
2934 MongoDB C driver also supports executing mixed bulk write operations. A
2935 batch of insert, update, and remove operations can be executed together
2936 using the bulk write operations API.
2937
2938 Ordered Bulk Write Operations
2939 Ordered bulk write operations are batched and sent to the server in the
2940 order provided for serial execution. The reply document describes the
2941 type and count of operations performed.
2942
2943 bulk2.c
2944
2945 #include <assert.h>
2946 #include <mongoc/mongoc.h>
2947 #include <stdio.h>
2948
2949 static void
2950 bulk2 (mongoc_collection_t *collection)
2951 {
2952 mongoc_bulk_operation_t *bulk;
2953 bson_error_t error;
2954 bson_t *query;
2955 bson_t *doc;
2956 bson_t *opts;
2957 bson_t reply;
2958 char *str;
2959 bool ret;
2960 int i;
2961
2962 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2963
2964 /* Remove everything */
2965 query = bson_new ();
2966 mongoc_bulk_operation_remove (bulk, query);
2967 bson_destroy (query);
2968
2969 /* Add a few documents */
2970 for (i = 1; i < 4; i++) {
2971 doc = BCON_NEW ("_id", BCON_INT32 (i));
2972 mongoc_bulk_operation_insert (bulk, doc);
2973 bson_destroy (doc);
2974 }
2975
2976 /* {_id: 1} => {$set: {foo: "bar"}} */
2977 query = BCON_NEW ("_id", BCON_INT32 (1));
2978 doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
2979 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
2980 bson_destroy (query);
2981 bson_destroy (doc);
2982
2983 /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
2984 opts = BCON_NEW ("upsert", BCON_BOOL (true));
2985 query = BCON_NEW ("_id", BCON_INT32 (4));
2986 doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
2987 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
2988 bson_destroy (query);
2989 bson_destroy (doc);
2990 bson_destroy (opts);
2991
2992 /* replace {j:1} with {j:2} */
2993 query = BCON_NEW ("j", BCON_INT32 (1));
2994 doc = BCON_NEW ("j", BCON_INT32 (2));
2995 mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
2996 bson_destroy (query);
2997 bson_destroy (doc);
2998
2999 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3000
3001 str = bson_as_canonical_extended_json (&reply, NULL);
3002 printf ("%s\n", str);
3003 bson_free (str);
3004
3005 if (!ret) {
3006 printf ("Error: %s\n", error.message);
3007 }
3008
3009 bson_destroy (&reply);
3010 mongoc_bulk_operation_destroy (bulk);
3011 }
3012
3013 int
3014 main (int argc, char *argv[])
3015 {
3016 mongoc_client_t *client;
3017 mongoc_collection_t *collection;
3018 const char *uri_string = "mongodb://localhost/?appname=bulk2-example";
3019 mongoc_uri_t *uri;
3020 bson_error_t error;
3021
3022 mongoc_init ();
3023
3024 uri = mongoc_uri_new_with_error (uri_string, &error);
3025 if (!uri) {
3026 fprintf (stderr,
3027 "failed to parse URI: %s\n"
3028 "error message: %s\n",
3029 uri_string,
3030 error.message);
3031 return EXIT_FAILURE;
3032 }
3033
3034 client = mongoc_client_new_from_uri (uri);
3035 if (!client) {
3036 return EXIT_FAILURE;
3037 }
3038
3039 mongoc_client_set_error_api (client, 2);
3040 collection = mongoc_client_get_collection (client, "test", "test");
3041
3042 bulk2 (collection);
3043
3044 mongoc_uri_destroy (uri);
3045 mongoc_collection_destroy (collection);
3046 mongoc_client_destroy (client);
3047
3048 mongoc_cleanup ();
3049
3050 return EXIT_SUCCESS;
3051 }
3052
3053
3054 Example reply document:
3055
3056 { "nInserted" : 3,
3057 "nMatched" : 2,
3058 "nModified" : 2,
3059 "nRemoved" : 10000,
3060 "nUpserted" : 1,
3061 "upserted" : [{"index" : 5, "_id" : 4}],
3062 "writeErrors" : []
3063 "writeConcernErrors" : [] }
3064
3065 The index field in the upserted array is the 0-based index of the
3066 upsert operation; in this example, the sixth operation of the overall
3067 bulk operation was an upsert, so its index is 5.
3068
3069 Unordered Bulk Write Operations
3070 Unordered bulk write operations are batched and sent to the server in
3071 arbitrary order where they may be executed in parallel. Any errors that
3072 occur are reported after all operations are attempted.
3073
3074 In the next example the first and third operations fail due to the
3075 unique constraint on _id. Since we are doing unordered execution the
3076 second and fourth operations succeed.
3077
3078 bulk3.c
3079
3080 #include <assert.h>
3081 #include <mongoc/mongoc.h>
3082 #include <stdio.h>
3083
3084 static void
3085 bulk3 (mongoc_collection_t *collection)
3086 {
3087 bson_t opts = BSON_INITIALIZER;
3088 mongoc_bulk_operation_t *bulk;
3089 bson_error_t error;
3090 bson_t *query;
3091 bson_t *doc;
3092 bson_t reply;
3093 char *str;
3094 bool ret;
3095
3096 /* false indicates unordered */
3097 BSON_APPEND_BOOL (&opts, "ordered", false);
3098 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3099 bson_destroy (&opts);
3100
3101 /* Add a document */
3102 doc = BCON_NEW ("_id", BCON_INT32 (1));
3103 mongoc_bulk_operation_insert (bulk, doc);
3104 bson_destroy (doc);
3105
3106 /* remove {_id: 2} */
3107 query = BCON_NEW ("_id", BCON_INT32 (2));
3108 mongoc_bulk_operation_remove_one (bulk, query);
3109 bson_destroy (query);
3110
3111 /* insert {_id: 3} */
3112 doc = BCON_NEW ("_id", BCON_INT32 (3));
3113 mongoc_bulk_operation_insert (bulk, doc);
3114 bson_destroy (doc);
3115
3116 /* replace {_id:4} {'i': 1} */
3117 query = BCON_NEW ("_id", BCON_INT32 (4));
3118 doc = BCON_NEW ("i", BCON_INT32 (1));
3119 mongoc_bulk_operation_replace_one (bulk, query, doc, false);
3120 bson_destroy (query);
3121 bson_destroy (doc);
3122
3123 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3124
3125 str = bson_as_canonical_extended_json (&reply, NULL);
3126 printf ("%s\n", str);
3127 bson_free (str);
3128
3129 if (!ret) {
3130 printf ("Error: %s\n", error.message);
3131 }
3132
3133 bson_destroy (&reply);
3134 mongoc_bulk_operation_destroy (bulk);
3135 bson_destroy (&opts);
3136 }
3137
3138 int
3139 main (int argc, char *argv[])
3140 {
3141 mongoc_client_t *client;
3142 mongoc_collection_t *collection;
3143 const char *uri_string = "mongodb://localhost/?appname=bulk3-example";
3144 mongoc_uri_t *uri;
3145 bson_error_t error;
3146
3147 mongoc_init ();
3148
3149 uri = mongoc_uri_new_with_error (uri_string, &error);
3150 if (!uri) {
3151 fprintf (stderr,
3152 "failed to parse URI: %s\n"
3153 "error message: %s\n",
3154 uri_string,
3155 error.message);
3156 return EXIT_FAILURE;
3157 }
3158
3159 client = mongoc_client_new_from_uri (uri);
3160 if (!client) {
3161 return EXIT_FAILURE;
3162 }
3163
3164 mongoc_client_set_error_api (client, 2);
3165 collection = mongoc_client_get_collection (client, "test", "test");
3166
3167 bulk3 (collection);
3168
3169 mongoc_uri_destroy (uri);
3170 mongoc_collection_destroy (collection);
3171 mongoc_client_destroy (client);
3172
3173 mongoc_cleanup ();
3174
3175 return EXIT_SUCCESS;
3176 }
3177
3178
3179 Example reply document:
3180
3181 { "nInserted" : 0,
3182 "nMatched" : 1,
3183 "nModified" : 1,
3184 "nRemoved" : 1,
3185 "nUpserted" : 0,
3186 "writeErrors" : [
3187 { "index" : 0,
3188 "code" : 11000,
3189 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
3190 { "index" : 2,
3191 "code" : 11000,
3192 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
3193 "writeConcernErrors" : [] }
3194
3195 Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }
3196
3197 The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.
3198
3199 Bulk Operation Bypassing Document Validation
3200 This feature is only available when using MongoDB 3.2 and later.
3201
3202 By default bulk operations are validated against the schema, if any is
3203 defined. In certain cases however it may be necessary to bypass the
3204 document validation.
3205
3206 bulk5.c
3207
3208 #include <assert.h>
3209 #include <mongoc/mongoc.h>
3210 #include <stdio.h>
3211
3212 static void
3213 bulk5_fail (mongoc_collection_t *collection)
3214 {
3215 mongoc_bulk_operation_t *bulk;
3216 bson_error_t error;
3217 bson_t *doc;
3218 bson_t reply;
3219 char *str;
3220 bool ret;
3221
3222 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3223
3224 /* Two inserts */
3225 doc = BCON_NEW ("_id", BCON_INT32 (31));
3226 mongoc_bulk_operation_insert (bulk, doc);
3227 bson_destroy (doc);
3228
3229 doc = BCON_NEW ("_id", BCON_INT32 (32));
3230 mongoc_bulk_operation_insert (bulk, doc);
3231 bson_destroy (doc);
3232
3233 /* The above documents do not comply to the schema validation rules
3234 * we created previously, so this will result in an error */
3235 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3236
3237 str = bson_as_canonical_extended_json (&reply, NULL);
3238 printf ("%s\n", str);
3239 bson_free (str);
3240
3241 if (!ret) {
3242 printf ("Error: %s\n", error.message);
3243 }
3244
3245 bson_destroy (&reply);
3246 mongoc_bulk_operation_destroy (bulk);
3247 }
3248
3249 static void
3250 bulk5_success (mongoc_collection_t *collection)
3251 {
3252 mongoc_bulk_operation_t *bulk;
3253 bson_error_t error;
3254 bson_t *doc;
3255 bson_t reply;
3256 char *str;
3257 bool ret;
3258
3259 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3260
3261 /* Allow this document to bypass document validation.
3262 * NOTE: When authentication is enabled, the authenticated user must have
3263 * either the "dbadmin" or "restore" roles to bypass document validation */
3264 mongoc_bulk_operation_set_bypass_document_validation (bulk, true);
3265
3266 /* Two inserts */
3267 doc = BCON_NEW ("_id", BCON_INT32 (31));
3268 mongoc_bulk_operation_insert (bulk, doc);
3269 bson_destroy (doc);
3270
3271 doc = BCON_NEW ("_id", BCON_INT32 (32));
3272 mongoc_bulk_operation_insert (bulk, doc);
3273 bson_destroy (doc);
3274
3275 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3276
3277 str = bson_as_canonical_extended_json (&reply, NULL);
3278 printf ("%s\n", str);
3279 bson_free (str);
3280
3281 if (!ret) {
3282 printf ("Error: %s\n", error.message);
3283 }
3284
3285 bson_destroy (&reply);
3286 mongoc_bulk_operation_destroy (bulk);
3287 }
3288
3289 int
3290 main (int argc, char *argv[])
3291 {
3292 bson_t *options;
3293 bson_error_t error;
3294 mongoc_client_t *client;
3295 mongoc_collection_t *collection;
3296 mongoc_database_t *database;
3297 const char *uri_string = "mongodb://localhost/?appname=bulk5-example";
3298 mongoc_uri_t *uri;
3299
3300 mongoc_init ();
3301
3302 uri = mongoc_uri_new_with_error (uri_string, &error);
3303 if (!uri) {
3304 fprintf (stderr,
3305 "failed to parse URI: %s\n"
3306 "error message: %s\n",
3307 uri_string,
3308 error.message);
3309 return EXIT_FAILURE;
3310 }
3311
3312 client = mongoc_client_new_from_uri (uri);
3313 if (!client) {
3314 return EXIT_FAILURE;
3315 }
3316
3317 mongoc_client_set_error_api (client, 2);
3318 database = mongoc_client_get_database (client, "testasdf");
3319
3320 /* Create schema validator */
3321 options = BCON_NEW (
3322 "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
3323 collection =
3324 mongoc_database_create_collection (database, "collname", options, &error);
3325
3326 if (collection) {
3327 bulk5_fail (collection);
3328 bulk5_success (collection);
3329 mongoc_collection_destroy (collection);
3330 } else {
3331 fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
3332 }
3333
3334 bson_free (options);
3335 mongoc_uri_destroy (uri);
3336 mongoc_database_destroy (database);
3337 mongoc_client_destroy (client);
3338
3339 mongoc_cleanup ();
3340
3341 return EXIT_SUCCESS;
3342 }
3343
3344
3345 Running the above example will result in:
3346
3347 { "nInserted" : 0,
3348 "nMatched" : 0,
3349 "nModified" : 0,
3350 "nRemoved" : 0,
3351 "nUpserted" : 0,
3352 "writeErrors" : [
3353 { "index" : 0,
3354 "code" : 121,
3355 "errmsg" : "Document failed validation" } ] }
3356
3357 Error: Document failed validation
3358
3359 { "nInserted" : 2,
3360 "nMatched" : 0,
3361 "nModified" : 0,
3362 "nRemoved" : 0,
3363 "nUpserted" : 0,
3364 "writeErrors" : [] }
3365
3366 The bson_error_t domain is MONGOC_ERROR_COMMAND.
3367
3368 Bulk Operation Write Concerns
3369 By default bulk operations are executed with the write_concern of the
3370 collection they are executed against. A custom write concern can be
3371 passed to the mongoc_collection_create_bulk_operation_with_opts()
3372 method. Write concern errors (e.g. wtimeout) will be reported after all
3373 operations are attempted, regardless of execution order.
3374
3375 bulk4.c
3376
3377 #include <assert.h>
3378 #include <mongoc/mongoc.h>
3379 #include <stdio.h>
3380
3381 static void
3382 bulk4 (mongoc_collection_t *collection)
3383 {
3384 bson_t opts = BSON_INITIALIZER;
3385 mongoc_write_concern_t *wc;
3386 mongoc_bulk_operation_t *bulk;
3387 bson_error_t error;
3388 bson_t *doc;
3389 bson_t reply;
3390 char *str;
3391 bool ret;
3392
3393 wc = mongoc_write_concern_new ();
3394 mongoc_write_concern_set_w (wc, 4);
3395 mongoc_write_concern_set_wtimeout_int64 (wc, 100); /* milliseconds */
3396 mongoc_write_concern_append (wc, &opts);
3397
3398 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3399
3400 /* Two inserts */
3401 doc = BCON_NEW ("_id", BCON_INT32 (10));
3402 mongoc_bulk_operation_insert (bulk, doc);
3403 bson_destroy (doc);
3404
3405 doc = BCON_NEW ("_id", BCON_INT32 (11));
3406 mongoc_bulk_operation_insert (bulk, doc);
3407 bson_destroy (doc);
3408
3409 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3410
3411 str = bson_as_canonical_extended_json (&reply, NULL);
3412 printf ("%s\n", str);
3413 bson_free (str);
3414
3415 if (!ret) {
3416 printf ("Error: %s\n", error.message);
3417 }
3418
3419 bson_destroy (&reply);
3420 mongoc_bulk_operation_destroy (bulk);
3421 mongoc_write_concern_destroy (wc);
3422 bson_destroy (&opts);
3423 }
3424
3425 int
3426 main (int argc, char *argv[])
3427 {
3428 mongoc_client_t *client;
3429 mongoc_collection_t *collection;
3430 const char *uri_string = "mongodb://localhost/?appname=bulk4-example";
3431 mongoc_uri_t *uri;
3432 bson_error_t error;
3433
3434 mongoc_init ();
3435
3436 uri = mongoc_uri_new_with_error (uri_string, &error);
3437 if (!uri) {
3438 fprintf (stderr,
3439 "failed to parse URI: %s\n"
3440 "error message: %s\n",
3441 uri_string,
3442 error.message);
3443 return EXIT_FAILURE;
3444 }
3445
3446 client = mongoc_client_new_from_uri (uri);
3447 if (!client) {
3448 return EXIT_FAILURE;
3449 }
3450
3451 mongoc_client_set_error_api (client, 2);
3452 collection = mongoc_client_get_collection (client, "test", "test");
3453
3454 bulk4 (collection);
3455
3456 mongoc_uri_destroy (uri);
3457 mongoc_collection_destroy (collection);
3458 mongoc_client_destroy (client);
3459
3460 mongoc_cleanup ();
3461
3462 return EXIT_SUCCESS;
3463 }
3464
3465
3466 Example reply document and error message:
3467
3468 { "nInserted" : 2,
3469 "nMatched" : 0,
3470 "nModified" : 0,
3471 "nRemoved" : 0,
3472 "nUpserted" : 0,
3473 "writeErrors" : [],
3474 "writeConcernErrors" : [
3475 { "code" : 64,
3476 "errmsg" : "waiting for replication timed out" }
3477 ] }
3478
3479 Error: waiting for replication timed out
3480
3481 The bson_error_t domain is MONGOC_ERROR_WRITE_CONCERN if there are
3482 write concern errors and no write errors. Write errors indicate failed
3483 operations, so they take precedence over write concern errors, which
3484 mean merely that the write concern is not satisfied yet.
3485
3486 Setting Collation Order
3487 This feature is only available when using MongoDB 3.4 and later.
3488
3489 bulk-collation.c
3490
3491 #include <mongoc/mongoc.h>
3492 #include <stdio.h>
3493
3494 static void
3495 bulk_collation (mongoc_collection_t *collection)
3496 {
3497 mongoc_bulk_operation_t *bulk;
3498 bson_t *opts;
3499 bson_t *doc;
3500 bson_t *selector;
3501 bson_t *update;
3502 bson_error_t error;
3503 bson_t reply;
3504 char *str;
3505 uint32_t ret;
3506
3507 /* insert {_id: "one"} and {_id: "One"} */
3508 bulk = mongoc_collection_create_bulk_operation_with_opts (
3509 collection, NULL);
3510 doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
3511 mongoc_bulk_operation_insert (bulk, doc);
3512 bson_destroy (doc);
3513
3514 doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
3515 mongoc_bulk_operation_insert (bulk, doc);
3516 bson_destroy (doc);
3517
3518 /* "One" normally sorts before "one"; make "one" come first */
3519 opts = BCON_NEW ("collation",
3520 "{",
3521 "locale",
3522 BCON_UTF8 ("en_US"),
3523 "caseFirst",
3524 BCON_UTF8 ("lower"),
3525 "}");
3526
3527 /* set x=1 on the document with _id "One", which now sorts after "one" */
3528 update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
3529 selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
3530 mongoc_bulk_operation_update_one_with_opts (
3531 bulk, selector, update, opts, &error);
3532
3533 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3534
3535 str = bson_as_canonical_extended_json (&reply, NULL);
3536 printf ("%s\n", str);
3537 bson_free (str);
3538
3539 if (!ret) {
3540 printf ("Error: %s\n", error.message);
3541 }
3542
3543 bson_destroy (&reply);
3544 bson_destroy (update);
3545 bson_destroy (selector);
3546 bson_destroy (opts);
3547 mongoc_bulk_operation_destroy (bulk);
3548 }
3549
3550 int
3551 main (int argc, char *argv[])
3552 {
3553 mongoc_client_t *client;
3554 mongoc_collection_t *collection;
3555 const char *uri_string = "mongodb://localhost/?appname=bulk-collation";
3556 mongoc_uri_t *uri;
3557 bson_error_t error;
3558
3559 mongoc_init ();
3560
3561 uri = mongoc_uri_new_with_error (uri_string, &error);
3562 if (!uri) {
3563 fprintf (stderr,
3564 "failed to parse URI: %s\n"
3565 "error message: %s\n",
3566 uri_string,
3567 error.message);
3568 return EXIT_FAILURE;
3569 }
3570
3571 client = mongoc_client_new_from_uri (uri);
3572 if (!client) {
3573 return EXIT_FAILURE;
3574 }
3575
3576 mongoc_client_set_error_api (client, 2);
3577 collection = mongoc_client_get_collection (client, "db", "collection");
3578 bulk_collation (collection);
3579
3580 mongoc_uri_destroy (uri);
3581 mongoc_collection_destroy (collection);
3582 mongoc_client_destroy (client);
3583
3584 mongoc_cleanup ();
3585
3586 return EXIT_SUCCESS;
3587 }
3588
3589
3590 Running the above example will result in:
3591
3592 { "nInserted" : 2,
3593 "nMatched" : 1,
3594 "nModified" : 1,
3595 "nRemoved" : 0,
3596 "nUpserted" : 0,
3597 "writeErrors" : [ ]
3598 }
3599
3600 Unacknowledged Bulk Writes
3601 Set "w" to zero for an unacknowledged write. The driver sends unac‐
3602 knowledged writes using the legacy opcodes OP_INSERT, OP_UPDATE, and
3603 OP_DELETE.
3604
3605 bulk6.c
3606
3607 #include <mongoc/mongoc.h>
3608 #include <stdio.h>
3609
3610 static void
3611 bulk6 (mongoc_collection_t *collection)
3612 {
3613 bson_t opts = BSON_INITIALIZER;
3614 mongoc_write_concern_t *wc;
3615 mongoc_bulk_operation_t *bulk;
3616 bson_error_t error;
3617 bson_t *doc;
3618 bson_t *selector;
3619 bson_t reply;
3620 char *str;
3621 bool ret;
3622
3623 wc = mongoc_write_concern_new ();
3624 mongoc_write_concern_set_w (wc, 0);
3625 mongoc_write_concern_append (wc, &opts);
3626
3627 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3628
3629 doc = BCON_NEW ("_id", BCON_INT32 (10));
3630 mongoc_bulk_operation_insert (bulk, doc);
3631 bson_destroy (doc);
3632
3633 selector = BCON_NEW ("_id", BCON_INT32 (11));
3634 mongoc_bulk_operation_remove_one (bulk, selector);
3635 bson_destroy (selector);
3636
3637 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3638
3639 str = bson_as_canonical_extended_json (&reply, NULL);
3640 printf ("%s\n", str);
3641 bson_free (str);
3642
3643 if (!ret) {
3644 printf ("Error: %s\n", error.message);
3645 }
3646
3647 bson_destroy (&reply);
3648 mongoc_bulk_operation_destroy (bulk);
3649 mongoc_write_concern_destroy (wc);
3650 bson_destroy (&opts);
3651 }
3652
3653 int
3654 main (int argc, char *argv[])
3655 {
3656 mongoc_client_t *client;
3657 mongoc_collection_t *collection;
3658 const char *uri_string = "mongodb://localhost/?appname=bulk6-example";
3659 mongoc_uri_t *uri;
3660 bson_error_t error;
3661
3662 mongoc_init ();
3663
3664 uri = mongoc_uri_new_with_error (uri_string, &error);
3665 if (!uri) {
3666 fprintf (stderr,
3667 "failed to parse URI: %s\n"
3668 "error message: %s\n",
3669 uri_string,
3670 error.message);
3671 return EXIT_FAILURE;
3672 }
3673
3674 client = mongoc_client_new_from_uri (uri);
3675 if (!client) {
3676 return EXIT_FAILURE;
3677 }
3678
3679 mongoc_client_set_error_api (client, 2);
3680 collection = mongoc_client_get_collection (client, "test", "test");
3681
3682 bulk6 (collection);
3683
3684 mongoc_uri_destroy (uri);
3685 mongoc_collection_destroy (collection);
3686 mongoc_client_destroy (client);
3687
3688 mongoc_cleanup ();
3689
3690 return EXIT_SUCCESS;
3691 }
3692
3693
3694 The reply document is empty:
3695
3696 { }
3697
3698 Further Reading
3699 See the Driver Bulk API Spec, which describes bulk write operations for
3700 all MongoDB drivers.
3701
3702 Aggregation Framework Examples
3703 This document provides a number of practical examples that display the
3704 capabilities of the aggregation framework.
3705
3706 The Aggregations using the Zip Codes Data Set examples uses a publicly
3707 available data set of all zipcodes and populations in the United
3708 States. These data are available at: zips.json.
3709
3710 Requirements
3711 Let's check if everything is installed.
3712
3713 Use the following command to load zips.json data set into mongod
3714 instance:
3715
3716 $ mongoimport --drop -d test -c zipcodes zips.json
3717
3718 Let's use the MongoDB shell to verify that everything was imported suc‐
3719 cessfully.
3720
3721 $ mongo test
3722 connecting to: test
3723 > db.zipcodes.count()
3724 29467
3725 > db.zipcodes.findOne()
3726 {
3727 "_id" : "35004",
3728 "city" : "ACMAR",
3729 "loc" : [
3730 -86.51557,
3731 33.584132
3732 ],
3733 "pop" : 6055,
3734 "state" : "AL"
3735 }
3736
3737 Aggregations using the Zip Codes Data Set
3738 Each document in this collection has the following form:
3739
3740 {
3741 "_id" : "35004",
3742 "city" : "Acmar",
3743 "state" : "AL",
3744 "pop" : 6055,
3745 "loc" : [-86.51557, 33.584132]
3746 }
3747
3748 In these documents:
3749
3750 · The _id field holds the zipcode as a string.
3751
3752 · The city field holds the city name.
3753
3754 · The state field holds the two letter state abbreviation.
3755
3756 · The pop field holds the population.
3757
3758 · The loc field holds the location as a [latitude, longitude] array.
3759
3760 States with Populations Over 10 Million
3761 To get all states with a population greater than 10 million, use the
3762 following aggregation pipeline:
3763
3764 aggregation1.c
3765
3766 #include <mongoc/mongoc.h>
3767 #include <stdio.h>
3768
3769 static void
3770 print_pipeline (mongoc_collection_t *collection)
3771 {
3772 mongoc_cursor_t *cursor;
3773 bson_error_t error;
3774 const bson_t *doc;
3775 bson_t *pipeline;
3776 char *str;
3777
3778 pipeline = BCON_NEW ("pipeline",
3779 "[",
3780 "{",
3781 "$group",
3782 "{",
3783 "_id",
3784 "$state",
3785 "total_pop",
3786 "{",
3787 "$sum",
3788 "$pop",
3789 "}",
3790 "}",
3791 "}",
3792 "{",
3793 "$match",
3794 "{",
3795 "total_pop",
3796 "{",
3797 "$gte",
3798 BCON_INT32 (10000000),
3799 "}",
3800 "}",
3801 "}",
3802 "]");
3803
3804 cursor = mongoc_collection_aggregate (
3805 collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
3806
3807 while (mongoc_cursor_next (cursor, &doc)) {
3808 str = bson_as_canonical_extended_json (doc, NULL);
3809 printf ("%s\n", str);
3810 bson_free (str);
3811 }
3812
3813 if (mongoc_cursor_error (cursor, &error)) {
3814 fprintf (stderr, "Cursor Failure: %s\n", error.message);
3815 }
3816
3817 mongoc_cursor_destroy (cursor);
3818 bson_destroy (pipeline);
3819 }
3820
3821 int
3822 main (int argc, char *argv[])
3823 {
3824 mongoc_client_t *client;
3825 mongoc_collection_t *collection;
3826 const char *uri_string =
3827 "mongodb://localhost:27017/?appname=aggregation-example";
3828 mongoc_uri_t *uri;
3829 bson_error_t error;
3830
3831 mongoc_init ();
3832
3833 uri = mongoc_uri_new_with_error (uri_string, &error);
3834 if (!uri) {
3835 fprintf (stderr,
3836 "failed to parse URI: %s\n"
3837 "error message: %s\n",
3838 uri_string,
3839 error.message);
3840 return EXIT_FAILURE;
3841 }
3842
3843 client = mongoc_client_new_from_uri (uri);
3844 if (!client) {
3845 return EXIT_FAILURE;
3846 }
3847
3848 mongoc_client_set_error_api (client, 2);
3849 collection = mongoc_client_get_collection (client, "test", "zipcodes");
3850
3851 print_pipeline (collection);
3852
3853 mongoc_uri_destroy (uri);
3854 mongoc_collection_destroy (collection);
3855 mongoc_client_destroy (client);
3856
3857 mongoc_cleanup ();
3858
3859 return EXIT_SUCCESS;
3860 }
3861
3862
3863 You should see a result like the following:
3864
3865 { "_id" : "PA", "total_pop" : 11881643 }
3866 { "_id" : "OH", "total_pop" : 10847115 }
3867 { "_id" : "NY", "total_pop" : 17990455 }
3868 { "_id" : "FL", "total_pop" : 12937284 }
3869 { "_id" : "TX", "total_pop" : 16986510 }
3870 { "_id" : "IL", "total_pop" : 11430472 }
3871 { "_id" : "CA", "total_pop" : 29760021 }
3872
3873 The above aggregation pipeline is build from two pipeline operators:
3874 $group and $match.
3875
3876 The $group pipeline operator requires _id field where we specify group‐
3877 ing; remaining fields specify how to generate composite value and must
3878 use one of the group aggregation functions: $addToSet, $first, $last,
3879 $max, $min, $avg, $push, $sum. The $match pipeline operator syntax is
3880 the same as the read operation query syntax.
3881
3882 The $group process reads all documents and for each state it creates a
3883 separate document, for example:
3884
3885 { "_id" : "WA", "total_pop" : 4866692 }
3886
3887 The total_pop field uses the $sum aggregation function to sum the val‐
3888 ues of all pop fields in the source documents.
3889
3890 Documents created by $group are piped to the $match pipeline operator.
3891 It returns the documents with the value of total_pop field greater than
3892 or equal to 10 million.
3893
3894 Average City Population by State
3895 To get the first three states with the greatest average population per
3896 city, use the following aggregation:
3897
3898 pipeline = BCON_NEW ("pipeline", "[",
3899 "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
3900 "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
3901 "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
3902 "{", "$limit", BCON_INT32 (3) "}",
3903 "]");
3904
3905 This aggregate pipeline produces:
3906
3907 { "_id" : "DC", "avg_city_pop" : 303450.0 }
3908 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3909 { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
3910
3911 The above aggregation pipeline is build from three pipeline operators:
3912 $group, $sort and $limit.
3913
3914 The first $group operator creates the following documents:
3915
3916 { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
3917
3918 Note, that the $group operator can't use nested documents except the
3919 _id field.
3920
3921 The second $group uses these documents to create the following docu‐
3922 ments:
3923
3924 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3925
3926 These documents are sorted by the avg_city_pop field in descending
3927 order. Finally, the $limit pipeline operator returns the first 3 docu‐
3928 ments from the sorted set.
3929
3930 distinct and mapReduce
3931 This document provides some practical, simple, examples to demonstrate
3932 the distinct and mapReduce commands.
3933
3934 Setup
3935 First we'll write some code to insert sample data:
3936
3937 doc-common-insert.c
3938
3939 /* Don't try to compile this file on its own. It's meant to be #included
3940 by example code */
3941
3942 /* Insert some sample data */
3943 bool
3944 insert_data (mongoc_collection_t *collection)
3945 {
3946 mongoc_bulk_operation_t *bulk;
3947 enum N { ndocs = 4 };
3948 bson_t *docs[ndocs];
3949 bson_error_t error;
3950 int i = 0;
3951 bool ret;
3952
3953 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3954
3955 docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
3956 docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
3957 docs[2] = BCON_NEW (
3958 "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
3959 docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
3960
3961 for (i = 0; i < ndocs; i++) {
3962 mongoc_bulk_operation_insert (bulk, docs[i]);
3963 bson_destroy (docs[i]);
3964 docs[i] = NULL;
3965 }
3966
3967 ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
3968
3969 if (!ret) {
3970 fprintf (stderr, "Error inserting data: %s\n", error.message);
3971 }
3972
3973 mongoc_bulk_operation_destroy (bulk);
3974 return ret;
3975 }
3976
3977 /* A helper which we'll use a lot later on */
3978 void
3979 print_res (const bson_t *reply)
3980 {
3981 char *str;
3982 BSON_ASSERT (reply);
3983 str = bson_as_canonical_extended_json (reply, NULL);
3984 printf ("%s\n", str);
3985 bson_free (str);
3986 }
3987
3988
3989 distinct command
3990 This is how to use the distinct command to get the distinct values of x
3991 which are greater than 1:
3992
3993 distinct.c
3994
3995 bool
3996 distinct (mongoc_database_t *database)
3997 {
3998 bson_t *command;
3999 bson_t reply;
4000 bson_error_t error;
4001 bool res;
4002 bson_iter_t iter;
4003 bson_iter_t array_iter;
4004 double val;
4005
4006 command = BCON_NEW ("distinct",
4007 BCON_UTF8 (COLLECTION_NAME),
4008 "key",
4009 BCON_UTF8 ("x"),
4010 "query",
4011 "{",
4012 "x",
4013 "{",
4014 "$gt",
4015 BCON_DOUBLE (1.0),
4016 "}",
4017 "}");
4018 res =
4019 mongoc_database_command_simple (database, command, NULL, &reply, &error);
4020 if (!res) {
4021 fprintf (stderr, "Error with distinct: %s\n", error.message);
4022 goto cleanup;
4023 }
4024
4025 /* Do something with reply (in this case iterate through the values) */
4026 if (!(bson_iter_init_find (&iter, &reply, "values") &&
4027 BSON_ITER_HOLDS_ARRAY (&iter) &&
4028 bson_iter_recurse (&iter, &array_iter))) {
4029 fprintf (stderr, "Couldn't extract \"values\" field from response\n");
4030 goto cleanup;
4031 }
4032
4033 while (bson_iter_next (&array_iter)) {
4034 if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
4035 val = bson_iter_double (&array_iter);
4036 printf ("Next double: %f\n", val);
4037 }
4038 }
4039
4040 cleanup:
4041 /* cleanup */
4042 bson_destroy (command);
4043 bson_destroy (&reply);
4044 return res;
4045 }
4046
4047
4048 mapReduce - basic example
4049 A simple example using the map reduce framework. It simply adds up the
4050 number of occurrences of each "tag".
4051
4052 First define the map and reduce functions:
4053
4054 constants.c
4055
4056 const char *const COLLECTION_NAME = "things";
4057
4058 /* Our map function just emits a single (key, 1) pair for each tag
4059 in the array: */
4060 const char *const MAPPER = "function () {"
4061 "this.tags.forEach(function(z) {"
4062 "emit(z, 1);"
4063 "});"
4064 "}";
4065
4066 /* The reduce function sums over all of the emitted values for a
4067 given key: */
4068 const char *const REDUCER = "function (key, values) {"
4069 "var total = 0;"
4070 "for (var i = 0; i < values.length; i++) {"
4071 "total += values[i];"
4072 "}"
4073 "return total;"
4074 "}";
4075 /* Note We can't just return values.length as the reduce function
4076 might be called iteratively on the results of other reduce
4077 steps. */
4078
4079
4080 Run the mapReduce command. Use the generic command helpers (e.g. mon‐
4081 goc_database_command_simple()). Do not the read command helpers (e.g.
4082 mongoc_database_read_command_with_opts()) because they are considered
4083 retryable read operations. If retryable reads are enabled, those opera‐
4084 tions will retry once on a retryable error, giving undesirable behavior
4085 for mapReduce.
4086
4087 map-reduce-basic.c
4088
4089 bool
4090 map_reduce_basic (mongoc_database_t *database)
4091 {
4092 bson_t reply;
4093 bson_t *command;
4094 bool res;
4095 bson_error_t error;
4096 mongoc_cursor_t *cursor;
4097 const bson_t *doc;
4098
4099 bool query_done = false;
4100
4101 const char *out_collection_name = "outCollection";
4102 mongoc_collection_t *out_collection;
4103
4104 /* Empty find query */
4105 bson_t find_query = BSON_INITIALIZER;
4106
4107 /* Construct the mapReduce command */
4108
4109 /* Other arguments can also be specified here, like "query" or
4110 "limit" and so on */
4111 command = BCON_NEW ("mapReduce",
4112 BCON_UTF8 (COLLECTION_NAME),
4113 "map",
4114 BCON_CODE (MAPPER),
4115 "reduce",
4116 BCON_CODE (REDUCER),
4117 "out",
4118 BCON_UTF8 (out_collection_name));
4119 res =
4120 mongoc_database_command_simple (database, command, NULL, &reply, &error);
4121
4122 if (!res) {
4123 fprintf (stderr, "MapReduce failed: %s\n", error.message);
4124 goto cleanup;
4125 }
4126
4127 /* Do something with the reply (it doesn't contain the mapReduce results) */
4128 print_res (&reply);
4129
4130 /* Now we'll query outCollection to see what the results are */
4131 out_collection =
4132 mongoc_database_get_collection (database, out_collection_name);
4133 cursor = mongoc_collection_find_with_opts (
4134 out_collection, &find_query, NULL, NULL);
4135 query_done = true;
4136
4137 /* Do something with the results */
4138 while (mongoc_cursor_next (cursor, &doc)) {
4139 print_res (doc);
4140 }
4141
4142 if (mongoc_cursor_error (cursor, &error)) {
4143 fprintf (stderr, "ERROR: %s\n", error.message);
4144 res = false;
4145 goto cleanup;
4146 }
4147
4148 cleanup:
4149 /* cleanup */
4150 if (query_done) {
4151 mongoc_cursor_destroy (cursor);
4152 mongoc_collection_destroy (out_collection);
4153 }
4154
4155 bson_destroy (&reply);
4156 bson_destroy (command);
4157
4158 return res;
4159 }
4160
4161
4162 mapReduce - more complicated example
4163 You must have replica set running for this.
4164
4165 In this example we contact a secondary in the replica set and do an
4166 "inline" map reduce, so the results are returned immediately:
4167
4168 map-reduce-advanced.c
4169
4170 bool
4171 map_reduce_advanced (mongoc_database_t *database)
4172 {
4173 bson_t *command;
4174 bson_error_t error;
4175 bool res = true;
4176 mongoc_cursor_t *cursor;
4177 mongoc_read_prefs_t *read_pref;
4178 const bson_t *doc;
4179
4180 /* Construct the mapReduce command */
4181 /* Other arguments can also be specified here, like "query" or "limit"
4182 and so on */
4183
4184 /* Read the results inline from a secondary replica */
4185 command = BCON_NEW ("mapReduce",
4186 BCON_UTF8 (COLLECTION_NAME),
4187 "map",
4188 BCON_CODE (MAPPER),
4189 "reduce",
4190 BCON_CODE (REDUCER),
4191 "out",
4192 "{",
4193 "inline",
4194 "1",
4195 "}");
4196
4197 read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
4198 cursor = mongoc_database_command (
4199 database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
4200
4201 /* Do something with the results */
4202 while (mongoc_cursor_next (cursor, &doc)) {
4203 print_res (doc);
4204 }
4205
4206 if (mongoc_cursor_error (cursor, &error)) {
4207 fprintf (stderr, "ERROR: %s\n", error.message);
4208 res = false;
4209 }
4210
4211 mongoc_cursor_destroy (cursor);
4212 mongoc_read_prefs_destroy (read_pref);
4213 bson_destroy (command);
4214
4215 return res;
4216 }
4217
4218
4219 Running the Examples
4220 Here's how to run the example code
4221
4222 basic-aggregation.c
4223
4224 /*
4225 * Copyright 2016 MongoDB, Inc.
4226 *
4227 * Licensed under the Apache License, Version 2.0 (the "License");
4228 * you may not use this file except in compliance with the License.
4229 * You may obtain a copy of the License at
4230 *
4231 * http://www.apache.org/licenses/LICENSE-2.0
4232 *
4233 * Unless required by applicable law or agreed to in writing, software
4234 * distributed under the License is distributed on an "AS IS" BASIS,
4235 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4236 * See the License for the specific language governing permissions and
4237 * limitations under the License.
4238 */
4239
4240
4241 #include <mongoc/mongoc.h>
4242 #include <stdio.h>
4243
4244
4245 #include "constants.c"
4246
4247 #include "../doc-common-insert.c"
4248 #include "distinct.c"
4249 #include "map-reduce-basic.c"
4250 #include "map-reduce-advanced.c"
4251
4252
4253 int
4254 main (int argc, char *argv[])
4255 {
4256 mongoc_database_t *database = NULL;
4257 mongoc_client_t *client = NULL;
4258 mongoc_collection_t *collection = NULL;
4259 mongoc_uri_t *uri = NULL;
4260 bson_error_t error;
4261 char *host_and_port = NULL;
4262 int exit_code = EXIT_FAILURE;
4263
4264 if (argc != 2) {
4265 fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
4266 fprintf (stderr,
4267 "the connection string can be of the following forms:\n");
4268 fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
4269 fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
4270 fprintf (stderr,
4271 "mongodb://user:pass@localhost:27017\t"
4272 "local machine on port 27017, and authenticate with username "
4273 "user and password pass\n");
4274 return exit_code;
4275 }
4276
4277 mongoc_init ();
4278
4279 if (strncmp (argv[1], "mongodb://", 10) == 0) {
4280 host_and_port = bson_strdup (argv[1]);
4281 } else {
4282 host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
4283 }
4284
4285 uri = mongoc_uri_new_with_error (host_and_port, &error);
4286 if (!uri) {
4287 fprintf (stderr,
4288 "failed to parse URI: %s\n"
4289 "error message: %s\n",
4290 host_and_port,
4291 error.message);
4292 goto cleanup;
4293 }
4294
4295 client = mongoc_client_new_from_uri (uri);
4296 if (!client) {
4297 goto cleanup;
4298 }
4299
4300 mongoc_client_set_error_api (client, 2);
4301 database = mongoc_client_get_database (client, "test");
4302 collection = mongoc_database_get_collection (database, COLLECTION_NAME);
4303
4304 printf ("Inserting data\n");
4305 if (!insert_data (collection)) {
4306 goto cleanup;
4307 }
4308
4309 printf ("distinct\n");
4310 if (!distinct (database)) {
4311 goto cleanup;
4312 }
4313
4314 printf ("map reduce\n");
4315 if (!map_reduce_basic (database)) {
4316 goto cleanup;
4317 }
4318
4319 printf ("more complicated map reduce\n");
4320 if (!map_reduce_advanced (database)) {
4321 goto cleanup;
4322 }
4323
4324 exit_code = EXIT_SUCCESS;
4325
4326 cleanup:
4327 if (collection) {
4328 mongoc_collection_destroy (collection);
4329 }
4330
4331 if (database) {
4332 mongoc_database_destroy (database);
4333 }
4334
4335 if (client) {
4336 mongoc_client_destroy (client);
4337 }
4338
4339 if (uri) {
4340 mongoc_uri_destroy (uri);
4341 }
4342
4343 if (host_and_port) {
4344 bson_free (host_and_port);
4345 }
4346
4347 mongoc_cleanup ();
4348 return exit_code;
4349 }
4350
4351
4352 If you want to try the advanced map reduce example with a secondary,
4353 start a replica set (instructions for how to do this can be found
4354 here).
4355
4356 Otherwise, just start an instance of MongoDB:
4357
4358 $ mongod
4359
4360 Now compile and run the example program:
4361
4362 $ cd examples/basic_aggregation/
4363 $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
4364 $ ./agg-example localhost
4365
4366 Inserting data
4367 distinct
4368 Next double: 2.000000
4369 Next double: 3.000000
4370 map reduce
4371 { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
4372 { "_id" : "cat", "value" : 63 }
4373 { "_id" : "dog", "value" : 42 }
4374 { "_id" : "mouse", "value" : 21 }
4375 more complicated map reduce
4376 { "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 }
4377
4378 Using libmongoc in a Microsoft Visual Studio project
4379 Download and install libmongoc on your system, then open Visual Studio,
4380 select "File→New→Project...", and create a new Win32 Console Applica‐
4381 tion. [image]
4382
4383 Remember to switch the platform from 32-bit to 64-bit: [image]
4384
4385 Right-click on your console application in the Solution Explorer and
4386 select "Properties". Choose to edit properties for "All Configura‐
4387 tions", expand the "C/C++" options and choose "General". Add to the
4388 "Additional Include Directories" these paths:
4389
4390 C:\mongo-c-driver\include\libbson-1.0
4391 C:\mongo-c-driver\include\libmongoc-1.0
4392 [image]
4393
4394 (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
4395 include paths will be different.)
4396
4397 Also in the Properties dialog, expand the "Linker" options and choose
4398 "Input", and add to the "Additional Dependencies" these libraries:
4399
4400 C:\mongo-c-driver\lib\bson-1.0.lib
4401 C:\mongo-c-driver\lib\mongoc-1.0.lib
4402 [image]
4403
4404 Adding these libraries as dependencies provides linker symbols to build
4405 your application, but to actually run it, libbson's and libmongoc's
4406 DLLs must be in your executable path. Select "Debugging" in the Proper‐
4407 ties dialog, and set the "Environment" option to:
4408
4409 PATH=c:/mongo-c-driver/bin
4410 [image]
4411
4412 Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
4413
4414 #include <mongoc/mongoc.h>
4415
4416 Static linking
4417 Following the instructions above, you have dynamically linked your
4418 application to the libbson and libmongoc DLLs. This is usually the
4419 right choice. If you want to link statically instead, update your
4420 "Additional Dependencies" list by removing bson-1.0.lib and mon‐
4421 goc-1.0.lib and replacing them with these libraries:
4422
4423 C:\mongo-c-driver\lib\bson-static-1.0.lib
4424 C:\mongo-c-driver\lib\mongoc-static-1.0.lib
4425 ws2_32.lib
4426 Secur32.lib
4427 Crypt32.lib
4428 BCrypt.lib
4429 [image]
4430
4431 (To explain the purpose of each library: bson-static-1.0.lib and mon‐
4432 goc-static-1.0.lib are static archives of the driver code. The socket
4433 library ws2_32 is required by libbson, which uses the socket routine
4434 gethostname to help guarantee ObjectId uniqueness. The BCrypt library
4435 is used by libmongoc for TLS connections to MongoDB, and Secur32 and
4436 Crypt32 are required for enterprise authentication methods like Ker‐
4437 beros.)
4438
4439 Finally, define two preprocessor symbols before including mongoc/mon‐
4440 goc.h in your stdafx.h:
4441
4442 #define BSON_STATIC
4443 #define MONGOC_STATIC
4444 #include <mongoc/mongoc.h>
4445
4446 Making these changes to your project is only required for static link‐
4447 ing; for most people, the dynamic-linking instructions above are pre‐
4448 ferred.
4449
4450 Next Steps
4451 Now you can build and debug applications in Visual Studio that use
4452 libbson and libmongoc. Proceed to making-a-connection in the tutorial
4453 to learn how connect to MongoDB and perform operations.
4454
4455 Creating Indexes
4456 To create indexes on a MongoDB collection, execute the createIndexes
4457 command with a command function like mongoc_database_write_com‐
4458 mand_with_opts or mongoc_collection_write_command_with_opts. See the
4459 MongoDB Manual entry for the createIndexes command for details.
4460
4461 Example
4462 example-create-indexes.c
4463
4464 /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
4465 * --libs libmongoc-1.0) */
4466
4467 /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */
4468
4469 #include <mongoc/mongoc.h>
4470 #include <stdio.h>
4471 #include <stdlib.h>
4472
4473 int
4474 main (int argc, char *argv[])
4475 {
4476 mongoc_client_t *client;
4477 const char *uri_string =
4478 "mongodb://127.0.0.1/?appname=create-indexes-example";
4479 mongoc_uri_t *uri;
4480 mongoc_database_t *db;
4481 const char *collection_name = "test";
4482 bson_t keys;
4483 char *index_name;
4484 bson_t *create_indexes;
4485 bson_t reply;
4486 char *reply_str;
4487 bson_error_t error;
4488 bool r;
4489
4490 mongoc_init ();
4491
4492 if (argc > 1) {
4493 uri_string = argv[1];
4494 }
4495
4496 if (argc > 2) {
4497 collection_name = argv[2];
4498 }
4499
4500 uri = mongoc_uri_new_with_error (uri_string, &error);
4501 if (!uri) {
4502 fprintf (stderr,
4503 "failed to parse URI: %s\n"
4504 "error message: %s\n",
4505 uri_string,
4506 error.message);
4507 return EXIT_FAILURE;
4508 }
4509
4510 client = mongoc_client_new_from_uri (uri);
4511 if (!client) {
4512 return EXIT_FAILURE;
4513 }
4514
4515 mongoc_client_set_error_api (client, 2);
4516 db = mongoc_client_get_database (client, "test");
4517
4518 /* ascending index on field "x" */
4519 bson_init (&keys);
4520 BSON_APPEND_INT32 (&keys, "x", 1);
4521 index_name = mongoc_collection_keys_to_index_string (&keys);
4522 create_indexes = BCON_NEW ("createIndexes",
4523 BCON_UTF8 (collection_name),
4524 "indexes",
4525 "[",
4526 "{",
4527 "key",
4528 BCON_DOCUMENT (&keys),
4529 "name",
4530 BCON_UTF8 (index_name),
4531 "}",
4532 "]");
4533
4534 r = mongoc_database_write_command_with_opts (
4535 db, create_indexes, NULL /* opts */, &reply, &error);
4536
4537 reply_str = bson_as_json (&reply, NULL);
4538 printf ("%s\n", reply_str);
4539
4540 if (!r) {
4541 fprintf (stderr, "Error in createIndexes: %s\n", error.message);
4542 }
4543
4544 bson_free (index_name);
4545 bson_free (reply_str);
4546 bson_destroy (&reply);
4547 bson_destroy (create_indexes);
4548 mongoc_database_destroy (db);
4549 mongoc_uri_destroy (uri);
4550 mongoc_client_destroy (client);
4551
4552 mongoc_cleanup ();
4553
4554 return r ? EXIT_SUCCESS : EXIT_FAILURE;
4555 }
4556
4557
4558 Aids for Debugging
4559 GDB
4560 This repository contains a .gdbinit file that contains helper functions
4561 to aid debugging of data structures. GDB will load this file
4562 automatically if you have added the directory which contains the
4563 .gdbinit file to GDB's auto-load safe-path, and you start GDB from the
4564 directory which holds the .gdbinit file.
4565
4566 You can see the safe-path with show auto-load safe-path on a GDB
4567 prompt. You can configure it by setting it in ~/.gdbinit with:
4568
4569 add-auto-load-safe-path /path/to/mongo-c-driver
4570
4571 If you haven't added the path to your auto-load safe-path, or start GDB
4572 in another directory, load the file with:
4573
4574 source path/to/mongo-c-driver/.gdbinit
4575
4576 The .gdbinit file defines the printbson function, which shows the con‐
4577 tents of a bson_t * variable. If you have a local bson_t, then you
4578 must prefix the variable with a &.
4579
4580 An example GDB session looks like:
4581
4582 (gdb) printbson bson
4583 ALLOC [0x555556cd7310 + 0] (len=475)
4584 {
4585 'bool' : true,
4586 'int32' : NumberInt("42"),
4587 'int64' : NumberLong("3000000042"),
4588 'string' : "Stŕìñg",
4589 'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
4590 'utcDateTime' : UTCDateTime(1511277299031),
4591 'arrayOfInts' : [
4592 '0' : NumberInt("1"),
4593 '1' : NumberInt("2")
4594 ],
4595 'embeddedDocument' : {
4596 'arrayOfStrings' : [
4597 '0' : "one",
4598 '1' : "two"
4599 ],
4600 'double' : 2.718280,
4601 'notherDoc' : {
4602 'true' : NumberInt("1"),
4603 'false' : false
4604 }
4605 },
4606 'binary' : Binary("02", "3031343532333637"),
4607 'regex' : Regex("@[a-z]+@", "im"),
4608 'null' : null,
4609 'js' : JavaScript("print foo"),
4610 'jsws' : JavaScript("print foo") with scope: {
4611 'f' : NumberInt("42"),
4612 'a' : [
4613 '0' : 3.141593,
4614 '1' : 2.718282
4615 ]
4616 },
4617 'timestamp' : Timestamp(4294967295, 4294967295),
4618 'double' : 3.141593
4619 }
4620
4621 LLDB
4622 This repository also includes a script that customizes LLDB's standard
4623 print command to print a bson_t or bson_t * as JSON:
4624
4625 (lldb) print b
4626 (bson_t) $0 = {"x": 1, "y": 2}
4627
4628 The custom bson command provides more options:
4629
4630 (lldb) bson --verbose b
4631 len=19
4632 flags=INLINE|STATIC
4633 {
4634 "x": 1,
4635 "y": 2
4636 }
4637 (lldb) bson --raw b
4638 '\x13\x00\x00\x00\x10x\x00\x01\x00\x00\x00\x10y\x00\x02\x00\x00\x00\x00'
4639
4640 Type help bson for a list of options.
4641
4642 The script requires a build of libbson with debug symbols, and an
4643 installation of PyMongo. Install PyMongo with:
4644
4645 python -m pip install pymongo
4646
4647 If you see "No module named pip" then you must install pip, then run
4648 the previous command again.
4649
4650 Create a file ~/.lldbinit containing:
4651
4652 command script import /path/to/mongo-c-driver/lldb_bson.py
4653
4654 If you see "bson command installed by lldb_bson" at the beginning of
4655 your LLDB session, you've installed the script correctly.
4656
4657 Using Client-Side Field Level Encryption
4658 New in MongoDB 4.2, Client-Side Field Level Encryption (also referred
4659 to as Client-Side Encryption) allows administrators and developers to
4660 encrypt specific data fields in addition to other MongoDB encryption
4661 features.
4662
4663 With Client-Side Encryption, developers can encrypt fields client side
4664 without any server-side configuration or directives. Client-Side
4665 Encryption supports workloads where applications must guarantee that
4666 unauthorized parties, including server administrators, cannot read the
4667 encrypted data.
4668
4669 Automatic encryption, where sensitive fields in commands are encrypted
4670 automatically, requires an Enterprise-only process to do query analy‐
4671 sis.
4672
4673 Installation
4674 libmongocrypt
4675 There is a separate library, libmongocrypt, that must be installed
4676 prior to configuring libmongoc to enable Client-Side Encryption.
4677
4678 libmongocrypt depends on libbson. To build libmongoc with Client-Side
4679 Encryption support you must:
4680
4681 1. Install libbson
4682
4683 2. Build and install libmongocrypt
4684
4685 3. Build libmongoc
4686
4687 To install libbson, follow the instructions to install with a package
4688 manager: Install libbson with a Package Manager or build from source
4689 with cmake (disable building libmongoc with -DENABLE_MONGOC=OFF):
4690
4691 $ cd mongo-c-driver
4692 $ mkdir cmake-build && cd cmake-build
4693 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=OFF ..
4694 $ cmake --build . --target install
4695
4696 To build and install libmongocrypt, clone the repository and configure
4697 as follows:
4698
4699 $ cd libmongocrypt
4700 $ mkdir cmake-build && cd cmake-build
4701 $ cmake -DENABLE_SHARED_BSON=ON ..
4702 $ cmake --build . --target install
4703
4704 Then, you should be able to build libmongoc with Client-Side Encryp‐
4705 tion.
4706
4707 $ cd mongo-c-driver
4708 $ mkdir cmake-build && cd cmake-build
4709 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=ON -DENABLE_CLIENT_SIDE_ENCRYPTION=ON ..
4710 $ cmake --build . --target install
4711
4712 mongocryptd
4713 The mongocryptd binary is required for automatic Client-Side Encryption
4714 and is included as a component in the MongoDB Enterprise Server pack‐
4715 age. For detailed installation instructions see the MongoDB documenta‐
4716 tion on mongocryptd.
4717
4718 mongocryptd performs the following:
4719
4720 · Parses the automatic encryption rules specified to the database con‐
4721 nection. If the JSON schema contains invalid automatic encryption
4722 syntax or any document validation syntax, mongocryptd returns an
4723 error.
4724
4725 · Uses the specified automatic encryption rules to mark fields in read
4726 and write operations for encryption.
4727
4728 · Rejects read/write operations that may return unexpected or incorrect
4729 results when applied to an encrypted field. For supported and unsup‐
4730 ported operations, see Read/Write Support with Automatic Field Level
4731 Encryption.
4732
4733 A mongoc_client_t configured with auto encryption will automatically
4734 spawn the mongocryptd process from the application's PATH. Applications
4735 can control the spawning behavior as part of the automatic encryption
4736 options. For example, to set a custom path to the mongocryptd process,
4737 set the mongocryptdSpawnPath with mongoc_auto_encryp‐
4738 tion_opts_set_extra().
4739
4740 bson_t *extra = BCON_NEW ("mongocryptdSpawnPath", "/path/to/mongocryptd");
4741 mongoc_auto_encryption_opts_set_extra (opts, extra);
4742
4743 To control the logging output of mongocryptd pass mongocryptdSpawnArgs
4744 to mongoc_auto_encryption_opts_set_extra():
4745
4746 bson_t *extra = BCON_NEW ("mongocryptdSpawnArgs",
4747 "[", "--logpath=/path/to/mongocryptd.log", "--logappend", "]");
4748 mongoc_auto_encryption_opts_set_extra (opts, extra);
4749
4750 If your application wishes to manage the mongocryptd process manually,
4751 it is possible to disable spawning mongocryptd:
4752
4753 bson_t *extra = BCON_NEW ("mongocryptdBypassSpawn",
4754 BCON_BOOL(true), "mongocryptdURI", "mongodb://localhost:27020");
4755 mongoc_auto_encryption_opts_set_extra (opts, extra);
4756
4757 mongocryptd is only responsible for supporting automatic Client-Side
4758 Encryption in the driver and does not itself perform any encryption or
4759 decryption.
4760
4761 Automatic Client-Side Field Level Encryption
4762 Automatic Client-Side Encryption is enabled by calling mon‐
4763 goc_client_enable_auto_encryption() on a mongoc_client_t. The following
4764 examples show how to set up automatic client-side field level encryp‐
4765 tion using mongoc_client_encryption_t to create a new encryption data
4766 key.
4767
4768 NOTE:
4769 Automatic client-side field level encryption requires MongoDB 4.2
4770 enterprise or a MongoDB 4.2 Atlas cluster. The community version of
4771 the server supports automatic decryption as well as Explicit Encryp‐
4772 tion.
4773
4774 Providing Local Automatic Encryption Rules
4775 The following example shows how to specify automatic encryption rules
4776 using a schema map set with mongoc_auto_encryp‐
4777 tion_opts_set_schema_map(). The automatic encryption rules are
4778 expressed using a strict subset of the JSON Schema syntax.
4779
4780 Supplying a schema map provides more security than relying on JSON
4781 Schemas obtained from the server. It protects against a malicious
4782 server advertising a false JSON Schema, which could trick the client
4783 into sending unencrypted data that should be encrypted.
4784
4785 JSON Schemas supplied in the schema map only apply to configuring auto‐
4786 matic client-side field level encryption. Other validation rules in the
4787 JSON schema will not be enforced by the driver and will result in an
4788 error:
4789
4790 client-side-encryption-schema-map.c
4791
4792 #include <mongoc/mongoc.h>
4793 #include <stdio.h>
4794 #include <stdlib.h>
4795
4796 #include "client-side-encryption-helpers.h"
4797
4798 /* Helper method to create a new data key in the key vault, a schema to use that
4799 * key, and writes the schema to a file for later use. */
4800 static bool
4801 create_schema_file (bson_t *kms_providers,
4802 const char *keyvault_db,
4803 const char *keyvault_coll,
4804 mongoc_client_t *keyvault_client,
4805 bson_error_t *error)
4806 {
4807 mongoc_client_encryption_t *client_encryption = NULL;
4808 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
4809 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
4810 bson_value_t datakey_id = {0};
4811 char *keyaltnames[] = {"mongoc_encryption_example_1"};
4812 bson_t *schema = NULL;
4813 char *schema_string = NULL;
4814 size_t schema_string_len;
4815 FILE *outfile = NULL;
4816 bool ret = false;
4817
4818 client_encryption_opts = mongoc_client_encryption_opts_new ();
4819 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
4820 kms_providers);
4821 mongoc_client_encryption_opts_set_keyvault_namespace (
4822 client_encryption_opts, keyvault_db, keyvault_coll);
4823 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
4824 keyvault_client);
4825
4826 client_encryption =
4827 mongoc_client_encryption_new (client_encryption_opts, error);
4828 if (!client_encryption) {
4829 goto fail;
4830 }
4831
4832 /* Create a new data key and json schema for the encryptedField.
4833 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
4834 */
4835 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
4836 mongoc_client_encryption_datakey_opts_set_keyaltnames (
4837 datakey_opts, keyaltnames, 1);
4838 if (!mongoc_client_encryption_create_datakey (
4839 client_encryption, "local", datakey_opts, &datakey_id, error)) {
4840 goto fail;
4841 }
4842
4843 /* Create a schema describing that "encryptedField" is a string encrypted
4844 * with the newly created data key using deterministic encryption. */
4845 schema = BCON_NEW ("properties",
4846 "{",
4847 "encryptedField",
4848 "{",
4849 "encrypt",
4850 "{",
4851 "keyId",
4852 "[",
4853 BCON_BIN (datakey_id.value.v_binary.subtype,
4854 datakey_id.value.v_binary.data,
4855 datakey_id.value.v_binary.data_len),
4856 "]",
4857 "bsonType",
4858 "string",
4859 "algorithm",
4860 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
4861 "}",
4862 "}",
4863 "}",
4864 "bsonType",
4865 "object");
4866
4867 /* Use canonical JSON so that other drivers and tools will be
4868 * able to parse the MongoDB extended JSON file. */
4869 schema_string = bson_as_canonical_extended_json (schema, &schema_string_len);
4870 outfile = fopen ("jsonSchema.json", "w");
4871 if (0 == fwrite (schema_string, sizeof (char), schema_string_len, outfile)) {
4872 fprintf (stderr, "failed to write to file\n");
4873 goto fail;
4874 }
4875
4876 ret = true;
4877 fail:
4878 mongoc_client_encryption_destroy (client_encryption);
4879 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
4880 mongoc_client_encryption_opts_destroy (client_encryption_opts);
4881 bson_free (schema_string);
4882 bson_destroy (schema);
4883 bson_value_destroy (&datakey_id);
4884 if (outfile) {
4885 fclose (outfile);
4886 }
4887 return true;
4888 }
4889
4890 /* This example demonstrates how to use automatic encryption with a client-side
4891 * schema map using the enterprise version of MongoDB */
4892 int
4893 main (int argc, char **argv)
4894 {
4895 /* The collection used to store the encryption data keys. */
4896 #define KEYVAULT_DB "encryption"
4897 #define KEYVAULT_COLL "__libmongocTestKeyVault"
4898 /* The collection used to store the encrypted documents in this example. */
4899 #define ENCRYPTED_DB "test"
4900 #define ENCRYPTED_COLL "coll"
4901
4902 int exit_status = EXIT_FAILURE;
4903 bool ret;
4904 uint8_t *local_masterkey = NULL;
4905 uint32_t local_masterkey_len;
4906 bson_t *kms_providers = NULL;
4907 bson_error_t error = {0};
4908 bson_t *index_keys = NULL;
4909 char *index_name = NULL;
4910 bson_t *create_index_cmd = NULL;
4911 bson_json_reader_t *reader = NULL;
4912 bson_t schema = BSON_INITIALIZER;
4913 bson_t *schema_map = NULL;
4914
4915 /* The MongoClient used to access the key vault (keyvault_namespace). */
4916 mongoc_client_t *keyvault_client = NULL;
4917 mongoc_collection_t *keyvault_coll = NULL;
4918 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
4919 mongoc_client_t *client = NULL;
4920 mongoc_collection_t *coll = NULL;
4921 bson_t *to_insert = NULL;
4922 mongoc_client_t *unencrypted_client = NULL;
4923 mongoc_collection_t *unencrypted_coll = NULL;
4924
4925 mongoc_init ();
4926
4927 /* Configure the master key. This must be the same master key that was used
4928 * to create the encryption key. */
4929 local_masterkey =
4930 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
4931 if (!local_masterkey || local_masterkey_len != 96) {
4932 fprintf (stderr,
4933 "Specify LOCAL_MASTERKEY environment variable as a "
4934 "secure random 96 byte hex value.\n");
4935 goto fail;
4936 }
4937
4938 kms_providers = BCON_NEW ("local",
4939 "{",
4940 "key",
4941 BCON_BIN (0, local_masterkey, local_masterkey_len),
4942 "}");
4943
4944 /* Set up the key vault for this example. */
4945 keyvault_client = mongoc_client_new (
4946 "mongodb://localhost/?appname=client-side-encryption-keyvault");
4947 keyvault_coll = mongoc_client_get_collection (
4948 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
4949 mongoc_collection_drop (keyvault_coll, NULL);
4950
4951 /* Create a unique index to ensure that two data keys cannot share the same
4952 * keyAltName. This is recommended practice for the key vault. */
4953 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
4954 index_name = mongoc_collection_keys_to_index_string (index_keys);
4955 create_index_cmd = BCON_NEW ("createIndexes",
4956 KEYVAULT_COLL,
4957 "indexes",
4958 "[",
4959 "{",
4960 "key",
4961 BCON_DOCUMENT (index_keys),
4962 "name",
4963 index_name,
4964 "unique",
4965 BCON_BOOL (true),
4966 "partialFilterExpression",
4967 "{",
4968 "keyAltNames",
4969 "{",
4970 "$exists",
4971 BCON_BOOL (true),
4972 "}",
4973 "}",
4974 "}",
4975 "]");
4976 ret = mongoc_client_command_simple (keyvault_client,
4977 KEYVAULT_DB,
4978 create_index_cmd,
4979 NULL /* read prefs */,
4980 NULL /* reply */,
4981 &error);
4982
4983 if (!ret) {
4984 goto fail;
4985 }
4986
4987 /* Create a new data key and a schema using it for encryption. Save the
4988 * schema to the file jsonSchema.json */
4989 ret = create_schema_file (
4990 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
4991
4992 if (!ret) {
4993 goto fail;
4994 }
4995
4996 /* Load the JSON Schema and construct the local schema_map option. */
4997 reader = bson_json_reader_new_from_file ("jsonSchema.json", &error);
4998 if (!reader) {
4999 goto fail;
5000 }
5001
5002 bson_json_reader_read (reader, &schema, &error);
5003
5004 /* Construct the schema map, mapping the namespace of the collection to the
5005 * schema describing encryption. */
5006 schema_map =
5007 BCON_NEW (ENCRYPTED_DB "." ENCRYPTED_COLL, BCON_DOCUMENT (&schema));
5008
5009 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5010 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
5011 keyvault_client);
5012 mongoc_auto_encryption_opts_set_keyvault_namespace (
5013 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5014 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5015 kms_providers);
5016 mongoc_auto_encryption_opts_set_schema_map (auto_encryption_opts,
5017 schema_map);
5018
5019 client =
5020 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5021
5022 /* Enable automatic encryption. It will determine that encryption is
5023 * necessary from the schema map instead of relying on the server to provide
5024 * a schema. */
5025 ret = mongoc_client_enable_auto_encryption (
5026 client, auto_encryption_opts, &error);
5027 if (!ret) {
5028 goto fail;
5029 }
5030
5031 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5032
5033 /* Clear old data */
5034 mongoc_collection_drop (coll, NULL);
5035
5036 to_insert = BCON_NEW ("encryptedField", "123456789");
5037 ret = mongoc_collection_insert_one (
5038 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5039 if (!ret) {
5040 goto fail;
5041 }
5042 printf ("decrypted document: ");
5043 if (!print_one_document (coll, &error)) {
5044 goto fail;
5045 }
5046 printf ("\n");
5047
5048 unencrypted_client = mongoc_client_new (
5049 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
5050 unencrypted_coll = mongoc_client_get_collection (
5051 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5052 printf ("encrypted document: ");
5053 if (!print_one_document (unencrypted_coll, &error)) {
5054 goto fail;
5055 }
5056 printf ("\n");
5057
5058 exit_status = EXIT_SUCCESS;
5059 fail:
5060 if (error.code) {
5061 fprintf (stderr, "error: %s\n", error.message);
5062 }
5063
5064 bson_free (local_masterkey);
5065 bson_destroy (kms_providers);
5066 mongoc_collection_destroy (keyvault_coll);
5067 bson_destroy (index_keys);
5068 bson_free (index_name);
5069 bson_destroy (create_index_cmd);
5070 bson_json_reader_destroy (reader);
5071 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5072 mongoc_collection_destroy (coll);
5073 mongoc_client_destroy (client);
5074 bson_destroy (to_insert);
5075 mongoc_collection_destroy (unencrypted_coll);
5076 mongoc_client_destroy (unencrypted_client);
5077 mongoc_client_destroy (keyvault_client);
5078 bson_destroy (&schema);
5079 bson_destroy (schema_map);
5080 mongoc_cleanup ();
5081 return exit_status;
5082 }
5083
5084 Server-Side Field Level Encryption Enforcement
5085 The MongoDB 4.2 server supports using schema validation to enforce
5086 encryption of specific fields in a collection. This schema validation
5087 will prevent an application from inserting unencrypted values for any
5088 fields marked with the "encrypt" JSON schema keyword.
5089
5090 The following example shows how to set up automatic client-side field
5091 level encryption using mongoc_client_encryption_t to create a new
5092 encryption data key and create a collection with the Automatic Encryp‐
5093 tion JSON Schema Syntax:
5094
5095 client-side-encryption-server-schema.c
5096
5097 #include <mongoc/mongoc.h>
5098 #include <stdio.h>
5099 #include <stdlib.h>
5100
5101 #include "client-side-encryption-helpers.h"
5102
5103 /* Helper method to create and return a JSON schema to use for encryption.
5104 The caller will use the returned schema for server-side encryption validation.
5105 */
5106 static bson_t *
5107 create_schema (bson_t *kms_providers,
5108 const char *keyvault_db,
5109 const char *keyvault_coll,
5110 mongoc_client_t *keyvault_client,
5111 bson_error_t *error)
5112 {
5113 mongoc_client_encryption_t *client_encryption = NULL;
5114 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5115 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5116 bson_value_t datakey_id = {0};
5117 char *keyaltnames[] = {"mongoc_encryption_example_2"};
5118 bson_t *schema = NULL;
5119
5120 client_encryption_opts = mongoc_client_encryption_opts_new ();
5121 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5122 kms_providers);
5123 mongoc_client_encryption_opts_set_keyvault_namespace (
5124 client_encryption_opts, keyvault_db, keyvault_coll);
5125 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5126 keyvault_client);
5127
5128 client_encryption =
5129 mongoc_client_encryption_new (client_encryption_opts, error);
5130 if (!client_encryption) {
5131 goto fail;
5132 }
5133
5134 /* Create a new data key and json schema for the encryptedField.
5135 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5136 */
5137 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5138 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5139 datakey_opts, keyaltnames, 1);
5140 if (!mongoc_client_encryption_create_datakey (
5141 client_encryption, "local", datakey_opts, &datakey_id, error)) {
5142 goto fail;
5143 }
5144
5145 /* Create a schema describing that "encryptedField" is a string encrypted
5146 * with the newly created data key using deterministic encryption. */
5147 schema = BCON_NEW ("properties",
5148 "{",
5149 "encryptedField",
5150 "{",
5151 "encrypt",
5152 "{",
5153 "keyId",
5154 "[",
5155 BCON_BIN (datakey_id.value.v_binary.subtype,
5156 datakey_id.value.v_binary.data,
5157 datakey_id.value.v_binary.data_len),
5158 "]",
5159 "bsonType",
5160 "string",
5161 "algorithm",
5162 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
5163 "}",
5164 "}",
5165 "}",
5166 "bsonType",
5167 "object");
5168
5169 fail:
5170 mongoc_client_encryption_destroy (client_encryption);
5171 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5172 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5173 bson_value_destroy (&datakey_id);
5174 return schema;
5175 }
5176
5177 /* This example demonstrates how to use automatic encryption with a server-side
5178 * schema using the enterprise version of MongoDB */
5179 int
5180 main (int argc, char **argv)
5181 {
5182 /* The collection used to store the encryption data keys. */
5183 #define KEYVAULT_DB "encryption"
5184 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5185 /* The collection used to store the encrypted documents in this example. */
5186 #define ENCRYPTED_DB "test"
5187 #define ENCRYPTED_COLL "coll"
5188
5189 int exit_status = EXIT_FAILURE;
5190 bool ret;
5191 uint8_t *local_masterkey = NULL;
5192 uint32_t local_masterkey_len;
5193 bson_t *kms_providers = NULL;
5194 bson_error_t error = {0};
5195 bson_t *index_keys = NULL;
5196 char *index_name = NULL;
5197 bson_t *create_index_cmd = NULL;
5198 bson_json_reader_t *reader = NULL;
5199 bson_t *schema = NULL;
5200
5201 /* The MongoClient used to access the key vault (keyvault_namespace). */
5202 mongoc_client_t *keyvault_client = NULL;
5203 mongoc_collection_t *keyvault_coll = NULL;
5204 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
5205 mongoc_client_t *client = NULL;
5206 mongoc_collection_t *coll = NULL;
5207 bson_t *to_insert = NULL;
5208 mongoc_client_t *unencrypted_client = NULL;
5209 mongoc_collection_t *unencrypted_coll = NULL;
5210 bson_t *create_cmd = NULL;
5211 bson_t *create_cmd_opts = NULL;
5212 mongoc_write_concern_t *wc = NULL;
5213
5214 mongoc_init ();
5215
5216 /* Configure the master key. This must be the same master key that was used
5217 * to create
5218 * the encryption key. */
5219 local_masterkey =
5220 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5221 if (!local_masterkey || local_masterkey_len != 96) {
5222 fprintf (stderr,
5223 "Specify LOCAL_MASTERKEY environment variable as a "
5224 "secure random 96 byte hex value.\n");
5225 goto fail;
5226 }
5227
5228 kms_providers = BCON_NEW ("local",
5229 "{",
5230 "key",
5231 BCON_BIN (0, local_masterkey, local_masterkey_len),
5232 "}");
5233
5234 /* Set up the key vault for this example. */
5235 keyvault_client = mongoc_client_new (
5236 "mongodb://localhost/?appname=client-side-encryption-keyvault");
5237 keyvault_coll = mongoc_client_get_collection (
5238 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
5239 mongoc_collection_drop (keyvault_coll, NULL);
5240
5241 /* Create a unique index to ensure that two data keys cannot share the same
5242 * keyAltName. This is recommended practice for the key vault. */
5243 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5244 index_name = mongoc_collection_keys_to_index_string (index_keys);
5245 create_index_cmd = BCON_NEW ("createIndexes",
5246 KEYVAULT_COLL,
5247 "indexes",
5248 "[",
5249 "{",
5250 "key",
5251 BCON_DOCUMENT (index_keys),
5252 "name",
5253 index_name,
5254 "unique",
5255 BCON_BOOL (true),
5256 "partialFilterExpression",
5257 "{",
5258 "keyAltNames",
5259 "{",
5260 "$exists",
5261 BCON_BOOL (true),
5262 "}",
5263 "}",
5264 "}",
5265 "]");
5266 ret = mongoc_client_command_simple (keyvault_client,
5267 KEYVAULT_DB,
5268 create_index_cmd,
5269 NULL /* read prefs */,
5270 NULL /* reply */,
5271 &error);
5272
5273 if (!ret) {
5274 goto fail;
5275 }
5276
5277 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5278 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
5279 keyvault_client);
5280 mongoc_auto_encryption_opts_set_keyvault_namespace (
5281 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5282 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5283 kms_providers);
5284 schema = create_schema (
5285 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
5286
5287 if (!schema) {
5288 goto fail;
5289 }
5290
5291 client =
5292 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5293 ret = mongoc_client_enable_auto_encryption (
5294 client, auto_encryption_opts, &error);
5295 if (!ret) {
5296 goto fail;
5297 }
5298
5299 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5300
5301 /* Clear old data */
5302 mongoc_collection_drop (coll, NULL);
5303
5304 /* Create the collection with the encryption JSON Schema. */
5305 create_cmd = BCON_NEW ("create",
5306 ENCRYPTED_COLL,
5307 "validator",
5308 "{",
5309 "$jsonSchema",
5310 BCON_DOCUMENT (schema),
5311 "}");
5312 wc = mongoc_write_concern_new ();
5313 mongoc_write_concern_set_wmajority (wc, 0);
5314 create_cmd_opts = bson_new ();
5315 mongoc_write_concern_append (wc, create_cmd_opts);
5316 ret = mongoc_client_command_with_opts (client,
5317 ENCRYPTED_DB,
5318 create_cmd,
5319 NULL /* read prefs */,
5320 create_cmd_opts,
5321 NULL /* reply */,
5322 &error);
5323 if (!ret) {
5324 goto fail;
5325 }
5326
5327 to_insert = BCON_NEW ("encryptedField", "123456789");
5328 ret = mongoc_collection_insert_one (
5329 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5330 if (!ret) {
5331 goto fail;
5332 }
5333 printf ("decrypted document: ");
5334 if (!print_one_document (coll, &error)) {
5335 goto fail;
5336 }
5337 printf ("\n");
5338
5339 unencrypted_client = mongoc_client_new (
5340 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
5341 unencrypted_coll = mongoc_client_get_collection (
5342 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5343 printf ("encrypted document: ");
5344 if (!print_one_document (unencrypted_coll, &error)) {
5345 goto fail;
5346 }
5347 printf ("\n");
5348
5349 /* Expect a server-side error if inserting with the unencrypted collection.
5350 */
5351 ret = mongoc_collection_insert_one (
5352 unencrypted_coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5353 if (!ret) {
5354 printf ("insert with unencrypted collection failed: %s\n", error.message);
5355 memset (&error, 0, sizeof (error));
5356 }
5357
5358 exit_status = EXIT_SUCCESS;
5359 fail:
5360 if (error.code) {
5361 fprintf (stderr, "error: %s\n", error.message);
5362 }
5363
5364 bson_free (local_masterkey);
5365 bson_destroy (kms_providers);
5366 mongoc_collection_destroy (keyvault_coll);
5367 bson_destroy (index_keys);
5368 bson_free (index_name);
5369 bson_destroy (create_index_cmd);
5370 bson_json_reader_destroy (reader);
5371 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5372 mongoc_collection_destroy (coll);
5373 mongoc_client_destroy (client);
5374 bson_destroy (to_insert);
5375 mongoc_collection_destroy (unencrypted_coll);
5376 mongoc_client_destroy (unencrypted_client);
5377 mongoc_client_destroy (keyvault_client);
5378 bson_destroy (schema);
5379 bson_destroy (create_cmd);
5380 bson_destroy (create_cmd_opts);
5381 mongoc_write_concern_destroy (wc);
5382
5383 mongoc_cleanup ();
5384 return exit_status;
5385 }
5386
5387 Explicit Encryption
5388 Explicit encryption is a MongoDB community feature and does not use the
5389 mongocryptd process. Explicit encryption is provided by the mon‐
5390 goc_client_encryption_t class, for example:
5391
5392 client-side-encryption-explicit.c
5393
5394 #include <mongoc/mongoc.h>
5395 #include <stdio.h>
5396 #include <stdlib.h>
5397
5398 #include "client-side-encryption-helpers.h"
5399
5400 /* This example demonstrates how to use explicit encryption and decryption using
5401 * the community version of MongoDB */
5402 int
5403 main (int argc, char **argv)
5404 {
5405 /* The collection used to store the encryption data keys. */
5406 #define KEYVAULT_DB "encryption"
5407 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5408 /* The collection used to store the encrypted documents in this example. */
5409 #define ENCRYPTED_DB "test"
5410 #define ENCRYPTED_COLL "coll"
5411
5412 int exit_status = EXIT_FAILURE;
5413 bool ret;
5414 uint8_t *local_masterkey = NULL;
5415 uint32_t local_masterkey_len;
5416 bson_t *kms_providers = NULL;
5417 bson_error_t error = {0};
5418 bson_t *index_keys = NULL;
5419 char *index_name = NULL;
5420 bson_t *create_index_cmd = NULL;
5421 bson_t *schema = NULL;
5422 mongoc_client_t *client = NULL;
5423 mongoc_collection_t *coll = NULL;
5424 mongoc_collection_t *keyvault_coll = NULL;
5425 bson_t *to_insert = NULL;
5426 bson_t *create_cmd = NULL;
5427 bson_t *create_cmd_opts = NULL;
5428 mongoc_write_concern_t *wc = NULL;
5429 mongoc_client_encryption_t *client_encryption = NULL;
5430 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5431 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5432 char *keyaltnames[] = {"mongoc_encryption_example_3"};
5433 bson_value_t datakey_id = {0};
5434 bson_value_t encrypted_field = {0};
5435 bson_value_t to_encrypt = {0};
5436 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
5437 bson_value_t decrypted = {0};
5438
5439 mongoc_init ();
5440
5441 /* Configure the master key. This must be the same master key that was used
5442 * to create the encryption key. */
5443 local_masterkey =
5444 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5445 if (!local_masterkey || local_masterkey_len != 96) {
5446 fprintf (stderr,
5447 "Specify LOCAL_MASTERKEY environment variable as a "
5448 "secure random 96 byte hex value.\n");
5449 goto fail;
5450 }
5451
5452 kms_providers = BCON_NEW ("local",
5453 "{",
5454 "key",
5455 BCON_BIN (0, local_masterkey, local_masterkey_len),
5456 "}");
5457
5458 /* The mongoc_client_t used to read/write application data. */
5459 client =
5460 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5461 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5462
5463 /* Clear old data */
5464 mongoc_collection_drop (coll, NULL);
5465
5466 /* Set up the key vault for this example. */
5467 keyvault_coll =
5468 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
5469 mongoc_collection_drop (keyvault_coll, NULL);
5470
5471 /* Create a unique index to ensure that two data keys cannot share the same
5472 * keyAltName. This is recommended practice for the key vault. */
5473 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5474 index_name = mongoc_collection_keys_to_index_string (index_keys);
5475 create_index_cmd = BCON_NEW ("createIndexes",
5476 KEYVAULT_COLL,
5477 "indexes",
5478 "[",
5479 "{",
5480 "key",
5481 BCON_DOCUMENT (index_keys),
5482 "name",
5483 index_name,
5484 "unique",
5485 BCON_BOOL (true),
5486 "partialFilterExpression",
5487 "{",
5488 "keyAltNames",
5489 "{",
5490 "$exists",
5491 BCON_BOOL (true),
5492 "}",
5493 "}",
5494 "}",
5495 "]");
5496 ret = mongoc_client_command_simple (client,
5497 KEYVAULT_DB,
5498 create_index_cmd,
5499 NULL /* read prefs */,
5500 NULL /* reply */,
5501 &error);
5502
5503 if (!ret) {
5504 goto fail;
5505 }
5506
5507 client_encryption_opts = mongoc_client_encryption_opts_new ();
5508 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5509 kms_providers);
5510 mongoc_client_encryption_opts_set_keyvault_namespace (
5511 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5512
5513 /* Set a mongoc_client_t to use for reading/writing to the key vault. This
5514 * can be the same mongoc_client_t used by the main application. */
5515 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5516 client);
5517 client_encryption =
5518 mongoc_client_encryption_new (client_encryption_opts, &error);
5519 if (!client_encryption) {
5520 goto fail;
5521 }
5522
5523 /* Create a new data key for the encryptedField.
5524 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5525 */
5526 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5527 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5528 datakey_opts, keyaltnames, 1);
5529 if (!mongoc_client_encryption_create_datakey (
5530 client_encryption, "local", datakey_opts, &datakey_id, &error)) {
5531 goto fail;
5532 }
5533
5534 /* Explicitly encrypt a field */
5535 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
5536 mongoc_client_encryption_encrypt_opts_set_algorithm (
5537 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
5538 mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts, &datakey_id);
5539 to_encrypt.value_type = BSON_TYPE_UTF8;
5540 to_encrypt.value.v_utf8.str = "123456789";
5541 to_encrypt.value.v_utf8.len = strlen (to_encrypt.value.v_utf8.str);
5542
5543 ret = mongoc_client_encryption_encrypt (
5544 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
5545 if (!ret) {
5546 goto fail;
5547 }
5548
5549 to_insert = bson_new ();
5550 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
5551 ret = mongoc_collection_insert_one (
5552 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5553 if (!ret) {
5554 goto fail;
5555 }
5556
5557 printf ("encrypted document: ");
5558 if (!print_one_document (coll, &error)) {
5559 goto fail;
5560 }
5561 printf ("\n");
5562
5563 /* Explicitly decrypt a field */
5564 ret = mongoc_client_encryption_decrypt (
5565 client_encryption, &encrypted_field, &decrypted, &error);
5566 if (!ret) {
5567 goto fail;
5568 }
5569 printf ("decrypted value: %s\n", decrypted.value.v_utf8.str);
5570
5571 exit_status = EXIT_SUCCESS;
5572 fail:
5573 if (error.code) {
5574 fprintf (stderr, "error: %s\n", error.message);
5575 }
5576
5577 bson_free (local_masterkey);
5578 bson_destroy (kms_providers);
5579 mongoc_collection_destroy (keyvault_coll);
5580 bson_destroy (index_keys);
5581 bson_free (index_name);
5582 bson_destroy (create_index_cmd);
5583 mongoc_collection_destroy (coll);
5584 mongoc_client_destroy (client);
5585 bson_destroy (to_insert);
5586 bson_destroy (schema);
5587 bson_destroy (create_cmd);
5588 bson_destroy (create_cmd_opts);
5589 mongoc_write_concern_destroy (wc);
5590 mongoc_client_encryption_destroy (client_encryption);
5591 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5592 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5593 bson_value_destroy (&encrypted_field);
5594 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
5595 bson_value_destroy (&decrypted);
5596 bson_value_destroy (&datakey_id);
5597
5598 mongoc_cleanup ();
5599 return exit_status;
5600 }
5601
5602 Explicit Encryption with Automatic Decryption
5603 Although automatic encryption requires MongoDB 4.2 enterprise or a Mon‐
5604 goDB 4.2 Atlas cluster, automatic decryption is supported for all
5605 users. To configure automatic decryption without automatic encryption
5606 set bypass_auto_encryption=True in mongoc_auto_encryption_opts_t:
5607
5608 client-side-encryption-auto-decryption.c
5609
5610 #include <mongoc/mongoc.h>
5611 #include <stdio.h>
5612 #include <stdlib.h>
5613
5614 #include "client-side-encryption-helpers.h"
5615
5616 /* This example demonstrates how to set up automatic decryption without
5617 * automatic encryption using the community version of MongoDB */
5618 int
5619 main (int argc, char **argv)
5620 {
5621 /* The collection used to store the encryption data keys. */
5622 #define KEYVAULT_DB "encryption"
5623 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5624 /* The collection used to store the encrypted documents in this example. */
5625 #define ENCRYPTED_DB "test"
5626 #define ENCRYPTED_COLL "coll"
5627
5628 int exit_status = EXIT_FAILURE;
5629 bool ret;
5630 uint8_t *local_masterkey = NULL;
5631 uint32_t local_masterkey_len;
5632 bson_t *kms_providers = NULL;
5633 bson_error_t error = {0};
5634 bson_t *index_keys = NULL;
5635 char *index_name = NULL;
5636 bson_t *create_index_cmd = NULL;
5637 bson_t *schema = NULL;
5638 mongoc_client_t *client = NULL;
5639 mongoc_collection_t *coll = NULL;
5640 mongoc_collection_t *keyvault_coll = NULL;
5641 bson_t *to_insert = NULL;
5642 bson_t *create_cmd = NULL;
5643 bson_t *create_cmd_opts = NULL;
5644 mongoc_write_concern_t *wc = NULL;
5645 mongoc_client_encryption_t *client_encryption = NULL;
5646 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5647 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5648 char *keyaltnames[] = {"mongoc_encryption_example_4"};
5649 bson_value_t datakey_id = {0};
5650 bson_value_t encrypted_field = {0};
5651 bson_value_t to_encrypt = {0};
5652 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
5653 bson_value_t decrypted = {0};
5654 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
5655 mongoc_client_t *unencrypted_client = NULL;
5656 mongoc_collection_t *unencrypted_coll = NULL;
5657
5658 mongoc_init ();
5659
5660 /* Configure the master key. This must be the same master key that was used
5661 * to create the encryption key. */
5662 local_masterkey =
5663 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5664 if (!local_masterkey || local_masterkey_len != 96) {
5665 fprintf (stderr,
5666 "Specify LOCAL_MASTERKEY environment variable as a "
5667 "secure random 96 byte hex value.\n");
5668 goto fail;
5669 }
5670
5671 kms_providers = BCON_NEW ("local",
5672 "{",
5673 "key",
5674 BCON_BIN (0, local_masterkey, local_masterkey_len),
5675 "}");
5676
5677 client =
5678 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5679 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5680 mongoc_auto_encryption_opts_set_keyvault_namespace (
5681 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5682 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5683 kms_providers);
5684
5685 /* Setting bypass_auto_encryption to true disables automatic encryption but
5686 * keeps the automatic decryption behavior. bypass_auto_encryption will also
5687 * disable spawning mongocryptd */
5688 mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts,
5689 true);
5690
5691 /* Once bypass_auto_encryption is set, community users can enable auto
5692 * encryption on the client. This will, in fact, only perform automatic
5693 * decryption. */
5694 ret = mongoc_client_enable_auto_encryption (
5695 client, auto_encryption_opts, &error);
5696 if (!ret) {
5697 goto fail;
5698 }
5699
5700 /* Now that automatic decryption is on, we can test it by inserting a
5701 * document with an explicitly encrypted value into the collection. When we
5702 * look up the document later, it should be automatically decrypted for us.
5703 */
5704 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5705
5706 /* Clear old data */
5707 mongoc_collection_drop (coll, NULL);
5708
5709 /* Set up the key vault for this example. */
5710 keyvault_coll =
5711 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
5712 mongoc_collection_drop (keyvault_coll, NULL);
5713
5714 /* Create a unique index to ensure that two data keys cannot share the same
5715 * keyAltName. This is recommended practice for the key vault. */
5716 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5717 index_name = mongoc_collection_keys_to_index_string (index_keys);
5718 create_index_cmd = BCON_NEW ("createIndexes",
5719 KEYVAULT_COLL,
5720 "indexes",
5721 "[",
5722 "{",
5723 "key",
5724 BCON_DOCUMENT (index_keys),
5725 "name",
5726 index_name,
5727 "unique",
5728 BCON_BOOL (true),
5729 "partialFilterExpression",
5730 "{",
5731 "keyAltNames",
5732 "{",
5733 "$exists",
5734 BCON_BOOL (true),
5735 "}",
5736 "}",
5737 "}",
5738 "]");
5739 ret = mongoc_client_command_simple (client,
5740 KEYVAULT_DB,
5741 create_index_cmd,
5742 NULL /* read prefs */,
5743 NULL /* reply */,
5744 &error);
5745
5746 if (!ret) {
5747 goto fail;
5748 }
5749
5750 client_encryption_opts = mongoc_client_encryption_opts_new ();
5751 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5752 kms_providers);
5753 mongoc_client_encryption_opts_set_keyvault_namespace (
5754 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5755
5756 /* The key vault client is used for reading to/from the key vault. This can
5757 * be the same mongoc_client_t used by the application. */
5758 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5759 client);
5760 client_encryption =
5761 mongoc_client_encryption_new (client_encryption_opts, &error);
5762 if (!client_encryption) {
5763 goto fail;
5764 }
5765
5766 /* Create a new data key for the encryptedField.
5767 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5768 */
5769 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5770 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5771 datakey_opts, keyaltnames, 1);
5772 ret = mongoc_client_encryption_create_datakey (
5773 client_encryption, "local", datakey_opts, &datakey_id, &error);
5774 if (!ret) {
5775 goto fail;
5776 }
5777
5778 /* Explicitly encrypt a field. */
5779 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
5780 mongoc_client_encryption_encrypt_opts_set_algorithm (
5781 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
5782 mongoc_client_encryption_encrypt_opts_set_keyaltname (
5783 encrypt_opts, "mongoc_encryption_example_4");
5784 to_encrypt.value_type = BSON_TYPE_UTF8;
5785 to_encrypt.value.v_utf8.str = "123456789";
5786 to_encrypt.value.v_utf8.len = strlen (to_encrypt.value.v_utf8.str);
5787
5788 ret = mongoc_client_encryption_encrypt (
5789 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
5790 if (!ret) {
5791 goto fail;
5792 }
5793
5794 to_insert = bson_new ();
5795 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
5796 ret = mongoc_collection_insert_one (
5797 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5798 if (!ret) {
5799 goto fail;
5800 }
5801
5802 /* When we retrieve the document, any encrypted fields will get automatically
5803 * decrypted by the driver. */
5804 printf ("decrypted document: ");
5805 if (!print_one_document (coll, &error)) {
5806 goto fail;
5807 }
5808 printf ("\n");
5809
5810 unencrypted_client =
5811 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5812 unencrypted_coll = mongoc_client_get_collection (
5813 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5814
5815 printf ("encrypted document: ");
5816 if (!print_one_document (unencrypted_coll, &error)) {
5817 goto fail;
5818 }
5819 printf ("\n");
5820
5821 exit_status = EXIT_SUCCESS;
5822 fail:
5823 if (error.code) {
5824 fprintf (stderr, "error: %s\n", error.message);
5825 }
5826
5827 bson_free (local_masterkey);
5828 bson_destroy (kms_providers);
5829 mongoc_collection_destroy (keyvault_coll);
5830 bson_destroy (index_keys);
5831 bson_free (index_name);
5832 bson_destroy (create_index_cmd);
5833 mongoc_collection_destroy (coll);
5834 mongoc_client_destroy (client);
5835 bson_destroy (to_insert);
5836 bson_destroy (schema);
5837 bson_destroy (create_cmd);
5838 bson_destroy (create_cmd_opts);
5839 mongoc_write_concern_destroy (wc);
5840 mongoc_client_encryption_destroy (client_encryption);
5841 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5842 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5843 bson_value_destroy (&encrypted_field);
5844 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
5845 bson_value_destroy (&decrypted);
5846 bson_value_destroy (&datakey_id);
5847 mongoc_collection_destroy (unencrypted_coll);
5848 mongoc_client_destroy (unencrypted_client);
5849 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5850
5851 mongoc_cleanup ();
5852 return exit_status;
5853 }
5854
5855 API Reference
5856 Initialization and cleanup
5857 Synopsis
5858 Initialize the MongoDB C Driver by calling mongoc_init exactly once at
5859 the beginning of your program. It is responsible for initializing
5860 global state such as process counters, SSL, and threading primitives.
5861
5862 Call mongoc_cleanup exactly once at the end of your program to release
5863 all memory and other resources allocated by the driver. You must not
5864 call any other MongoDB C Driver functions after mongoc_cleanup. Note
5865 that mongoc_init does not reinitialize the driver after mongoc_cleanup.
5866
5867 Deprecated feature: automatic initialization and cleanup
5868 On some platforms the driver can automatically call mongoc_init before
5869 main, and call mongoc_cleanup as the process exits. This is problematic
5870 in situations where related libraries also execute cleanup code on
5871 shutdown, and it creates inconsistent rules across platforms. Therefore
5872 the automatic initialization and cleanup feature is deprecated, and
5873 will be dropped in version 2.0. Meanwhile, for backward compatibility,
5874 the feature is enabled by default on platforms where it is available.
5875
5876 For portable, future-proof code, always call mongoc_init and mon‐
5877 goc_cleanup yourself, and configure the driver like:
5878
5879 cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO
5880
5881 Logging
5882 MongoDB C driver Logging Abstraction
5883
5884 Synopsis
5885 typedef enum {
5886 MONGOC_LOG_LEVEL_ERROR,
5887 MONGOC_LOG_LEVEL_CRITICAL,
5888 MONGOC_LOG_LEVEL_WARNING,
5889 MONGOC_LOG_LEVEL_MESSAGE,
5890 MONGOC_LOG_LEVEL_INFO,
5891 MONGOC_LOG_LEVEL_DEBUG,
5892 MONGOC_LOG_LEVEL_TRACE,
5893 } mongoc_log_level_t;
5894
5895 #define MONGOC_ERROR(...)
5896 #define MONGOC_CRITICAL(...)
5897 #define MONGOC_WARNING(...)
5898 #define MONGOC_MESSAGE(...)
5899 #define MONGOC_INFO(...)
5900 #define MONGOC_DEBUG(...)
5901
5902 typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
5903 const char *log_domain,
5904 const char *message,
5905 void *user_data);
5906
5907 void
5908 mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
5909 void
5910 mongoc_log (mongoc_log_level_t log_level,
5911 const char *log_domain,
5912 const char *format,
5913 ...) BSON_GNUC_PRINTF (3, 4);
5914 const char *
5915 mongoc_log_level_str (mongoc_log_level_t log_level);
5916 void
5917 mongoc_log_default_handler (mongoc_log_level_t log_level,
5918 const char *log_domain,
5919 const char *message,
5920 void *user_data);
5921 void
5922 mongoc_log_trace_enable (void);
5923 void
5924 mongoc_log_trace_disable (void);
5925
5926 The MongoDB C driver comes with an abstraction for logging that you can
5927 use in your application, or integrate with an existing logging system.
5928
5929 Macros
5930 To make logging a little less painful, various helper macros are pro‐
5931 vided. See the following example.
5932
5933 #undef MONGOC_LOG_DOMAIN
5934 #define MONGOC_LOG_DOMAIN "my-custom-domain"
5935
5936 MONGOC_WARNING ("An error occurred: %s", strerror (errno));
5937
5938 Custom Log Handlers
5939 The default log handler prints a timestamp and the log message to std‐
5940 out, or to stderr for warnings, critical messages, and errors.
5941 You can override the handler with mongoc_log_set_handler().
5942 Your handler function is called in a mutex for thread safety.
5943
5944 For example, you could register a custom handler to suppress messages
5945 at INFO level and below:
5946
5947 void
5948 my_logger (mongoc_log_level_t log_level,
5949 const char *log_domain,
5950 const char *message,
5951 void *user_data)
5952 {
5953 /* smaller values are more important */
5954 if (log_level < MONGOC_LOG_LEVEL_INFO) {
5955 mongoc_log_default_handler (log_level, log_domain, message, user_data);
5956 }
5957 }
5958
5959 int
5960 main (int argc, char *argv[])
5961 {
5962 mongoc_init ();
5963 mongoc_log_set_handler (my_logger, NULL);
5964
5965 /* ... your code ... */
5966
5967 mongoc_cleanup ();
5968 return 0;
5969 }
5970
5971 To restore the default handler:
5972
5973 mongoc_log_set_handler (mongoc_log_default_handler, NULL);
5974
5975 Disable logging
5976 To disable all logging, including warnings, critical messages and
5977 errors, provide an empty log handler:
5978
5979 mongoc_log_set_handler (NULL, NULL);
5980
5981 Tracing
5982 If compiling your own copy of the MongoDB C driver, consider configur‐
5983 ing with -DENABLE_TRACING=ON to enable function tracing and hex dumps
5984 of network packets to STDERR and STDOUT during development and debug‐
5985 ging.
5986
5987 This is especially useful when debugging what may be going on inter‐
5988 nally in the driver.
5989
5990 Trace messages can be enabled and disabled by calling mon‐
5991 goc_log_trace_enable() and mongoc_log_trace_disable()
5992
5993 NOTE:
5994 Compiling the driver with -DENABLE_TRACING=ON will affect its per‐
5995 formance. Disabling tracing with mongoc_log_trace_disable() signifi‐
5996 cantly reduces the overhead, but cannot remove it completely.
5997 « index
5998
5999 Error Reporting
6000 Description
6001 Many C Driver functions report errors by returning false or -1 and
6002 filling out a bson_error_t structure with an error domain, error code,
6003 and message. Use domain to determine which subsystem generated the
6004 error, and code for the specific error. message is a human-readable
6005 error description.
6006
6007 See also: Handling Errors in libbson.
6008
6009┌──────────────────────────────┬─────────────────────────────────────────┬───────────────────────────────────────┐
6010│Domain │ Code │ Description │
6011├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6012│MONGOC_ERROR_CLIENT │ MON‐ │ You tried to send a │
6013│ │ GOC_ERROR_CLIENT_TOO_BIG │ message larger than │
6014│ │ │ the server's max │
6015│ │ │ message size. │
6016├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6017│ │ MON‐ │ Wrong credentials, │
6018│ │ GOC_ERROR_CLIENT_AUTHEN‐ │ or failure sending │
6019│ │ TICATE │ or receiving │
6020│ │ │ authentication mes‐ │
6021│ │ │ sages. │
6022├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6023│ │ MON‐ │ You tried an TLS │
6024│ │ GOC_ERROR_CLIENT_NO_ACCEPT‐ │ connection but the │
6025│ │ ABLE_PEER │ driver was not │
6026│ │ │ built with TLS. │
6027├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6028│ │ MON‐ │ You began iterating │
6029│ │ GOC_ERROR_CLIENT_IN_EXHAUST │ an exhaust cursor, │
6030│ │ │ then tried to begin │
6031│ │ │ another operation │
6032│ │ │ with the same mon‐ │
6033│ │ │ goc_client_t. │
6034├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6035│ │ MONGOC_ERROR_CLIENT_SES‐ │ Failure related to │
6036│ │ SION_FAILURE │ creating or using a │
6037│ │ │ logical session. │
6038├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6039│ │ MON‐ │ Failure related to │
6040│ │ GOC_ERROR_CLIENT_INVALID_ENCRYP‐ │ arguments passed │
6041│ │ TION_ARG │ when initializing │
6042│ │ │ Client-Side Field │
6043│ │ │ Level Encryption. │
6044├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6045│ │ MON‐ │ Failure related to │
6046│ │ GOC_ERROR_CLIENT_INVALID_ENCRYP‐ │ Client-Side Field │
6047│ │ TION_STATE │ Level Encryption. │
6048├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6049│MONGOC_ERROR_STREAM │ MONGOC_ERROR_STREAM_NAME_RESOLU‐ │ DNS failure. │
6050│ │ TION │ │
6051└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
6052
6053
6054│ │ MONGOC_ERROR_STREAM_SOCKET │ Timeout communicat‐ │
6055│ │ │ ing with server, or │
6056│ │ │ connection closed. │
6057├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6058│ │ MONGOC_ERROR_STREAM_CONNECT │ Failed to connect │
6059│ │ │ to server. │
6060├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6061│MONGOC_ERROR_PROTO‐ │ MONGOC_ERROR_PROTO‐ │ Corrupt response │
6062│COL │ COL_INVALID_REPLY │ from server. │
6063├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6064│ │ MONGOC_ERROR_PROTO‐ │ The server version │
6065│ │ COL_BAD_WIRE_VERSION │ is too old or too │
6066│ │ │ new to communicate │
6067│ │ │ with the driver. │
6068├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6069│MONGOC_ERROR_CURSOR │ MONGOC_ERROR_CURSOR_INVALID_CUR‐ │ You passed bad │
6070│ │ SOR │ arguments to mon‐ │
6071│ │ │ goc_collec‐ │
6072│ │ │ tion_find_with_opts, │
6073│ │ │ or you called mon‐ │
6074│ │ │ goc_cursor_next on │
6075│ │ │ a completed or │
6076│ │ │ failed cursor, or │
6077│ │ │ the cursor timed │
6078│ │ │ out on the server. │
6079├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6080│ │ MON‐ │ A resume token was │
6081│ │ GOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN │ not returned in a │
6082│ │ │ document found with │
6083│ │ │ mon‐ │
6084│ │ │ goc_change_stream_next │
6085├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6086│MONGOC_ERROR_QUERY │ MONGOC_ERROR_QUERY_FAILURE │ Error API Version 1: │
6087│ │ │ Server error from com‐ │
6088│ │ │ mand or query. The │
6089│ │ │ server error message │
6090│ │ │ is in message. │
6091├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6092│MONGOC_ERROR_SERVER │ MONGOC_ERROR_QUERY_FAILURE │ Error API Version 2: │
6093│ │ │ Server error from com‐ │
6094│ │ │ mand or query. The │
6095│ │ │ server error message │
6096│ │ │ is in message. │
6097├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6098│MONGOC_ERROR_SASL │ A SASL error code. │ man sasl_errors for a │
6099│ │ │ list of codes. │
6100├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6101│MONGOC_ERROR_BSON │ MONGOC_ERROR_BSON_INVALID │ You passed an invalid │
6102│ │ │ or oversized BSON doc‐ │
6103│ │ │ ument as a parameter, │
6104│ │ │ or called mongoc_col‐ │
6105│ │ │ lection_create_index │
6106│ │ │ with invalid keys, or │
6107│ │ │ the server reply was │
6108│ │ │ corrupt. │
6109├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6110│MONGOC_ERROR_NAMES‐ │ MONGOC_ERROR_NAMESPACE_INVALID │ You tried to create a │
6111│PACE │ │ collection with an │
6112│ │ │ invalid name. │
6113├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6114│MONGOC_ERROR_COM‐ │ MONGOC_ERROR_COMMAND_INVALID_ARG │ Many functions set │
6115│MAND │ │ this error code when │
6116│ │ │ passed bad parameters. │
6117│ │ │ Print the error mes‐ │
6118│ │ │ sage for details. │
6119├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6120│ │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION │ You tried to use a │
6121│ │ │ command option the │
6122│ │ │ server does not sup‐ │
6123│ │ │ port. │
6124└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
6125
6126
6127
6128
6129
6130│ │ MONGOC_ERROR_DUPLICATE_KEY │ An insert or update │
6131│ │ │ failed because because │
6132│ │ │ of a duplicate _id or │
6133│ │ │ other unique-index │
6134│ │ │ violation. │
6135├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6136│ │ MONGOC_ERROR_MAX_TIME_MS_EXPIRED │ The operation failed │
6137│ │ │ because maxTimeMS │
6138│ │ │ expired. │
6139├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6140│ │ MONGOC_ERROR_SERVER_SELEC‐ │ The serverId option │
6141│ │ TION_INVALID_ID │ for an operation con‐ │
6142│ │ │ flicts with the pinned │
6143│ │ │ server for that opera‐ │
6144│ │ │ tion's client session │
6145│ │ │ (denoted by the ses‐ │
6146│ │ │ sionId option). │
6147├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6148│MONGOC_ERROR_COM‐ │ Error code from server. │ Error API Version 1: │
6149│MAND │ │ Server error from a │
6150│ │ │ command. The server │
6151│ │ │ error message is in │
6152│ │ │ message. │
6153├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6154│MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: │
6155│ │ │ Server error from a │
6156│ │ │ command. The server │
6157│ │ │ error message is in │
6158│ │ │ message. │
6159├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6160│MONGOC_ERROR_COL‐ │ MONGOC_ERROR_COLLECTION_INSERT_FAILED, │ Invalid or empty input │
6161│LECTION │ MONGOC_ERROR_COLLECTION_UPDATE_FAILED, │ to mongoc_collec‐ │
6162│ │ MONGOC_ERROR_COLLECTION_DELETE_FAILED. │ tion_insert_one, mon‐ │
6163│ │ │ goc_collec‐ │
6164│ │ │ tion_insert_bulk, mon‐ │
6165│ │ │ goc_collec‐ │
6166│ │ │ tion_update_one, mon‐ │
6167│ │ │ goc_collec‐ │
6168│ │ │ tion_update_many, mon‐ │
6169│ │ │ goc_collec‐ │
6170│ │ │ tion_replace_one, mon‐ │
6171│ │ │ goc_collec‐ │
6172│ │ │ tion_delete_one, or │
6173│ │ │ mongoc_collec‐ │
6174│ │ │ tion_delete_many. │
6175├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6176│MONGOC_ERROR_COL‐ │ Error code from server. │ Error API Version 1: │
6177│LECTION │ │ Server error from mon‐ │
6178│ │ │ goc_collec‐ │
6179│ │ │ tion_insert_one, mon‐ │
6180│ │ │ goc_collec‐ │
6181│ │ │ tion_insert_bulk, mon‐ │
6182│ │ │ goc_collec‐ │
6183│ │ │ tion_update_one, mon‐ │
6184│ │ │ goc_collec‐ │
6185│ │ │ tion_update_many, mon‐ │
6186│ │ │ goc_collec‐ │
6187│ │ │ tion_replace_one, │
6188├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6189│MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: │
6190│ │ │ Server error from mon‐ │
6191│ │ │ goc_collec‐ │
6192│ │ │ tion_insert_one, mon‐ │
6193│ │ │ goc_collec‐ │
6194│ │ │ tion_insert_bulk, mon‐ │
6195│ │ │ goc_collec‐ │
6196│ │ │ tion_update_one, mon‐ │
6197│ │ │ goc_collec‐ │
6198│ │ │ tion_update_many, mon‐ │
6199│ │ │ goc_collec‐ │
6200│ │ │ tion_replace_one, │
6201└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
6202
6203
6204
6205
6206│MONGOC_ERROR_GRIDFS │ MONGOC_ERROR_GRIDFS_CHUNK_MISSING │ The GridFS file is │
6207│ │ │ missing a document in │
6208│ │ │ its chunks collection. │
6209├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6210│ │ MONGOC_ERROR_GRIDFS_CORRUPT │ A data inconsistency │
6211│ │ │ was detected in │
6212│ │ │ GridFS. │
6213├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6214│ │ MONGOC_ERROR_GRIDFS_INVALID_FILENAME │ You passed a NULL │
6215│ │ │ filename to mon‐ │
6216│ │ │ goc_gridfs_remove_by_file‐ │
6217│ │ │ name. │
6218├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6219│ │ MONGOC_ERROR_GRIDFS_PROTOCOL_ERROR │ You called mon‐ │
6220│ │ │ goc_gridfs_file_set_id │
6221│ │ │ after mon‐ │
6222│ │ │ goc_gridfs_file_save, or │
6223│ │ │ tried to write on a closed │
6224│ │ │ GridFS stream. │
6225├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6226│ │ MON‐ │ A GridFS file is missing │
6227│ │ GOC_ERROR_GRIDFS_BUCKET_FILE_NOT_FOUND │ from files collection. │
6228├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6229│ │ MONGOC_ERROR_GRIDFS_BUCKET_STREAM │ An error occurred on a │
6230│ │ │ stream created from a │
6231│ │ │ GridFS operation like mon‐ │
6232│ │ │ goc_gridfs_bucket_upload_from_stream. │
6233├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6234│MONGOC_ERROR_SCRAM │ MONGOC_ERROR_SCRAM_PROTOCOL_ERROR │ Failure in SCRAM-SHA-1 authentica‐ │
6235│ │ │ tion. │
6236├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6237│MON‐ │ MONGOC_ERROR_SERVER_SELECTION_FAILURE │ No replica set member or mongos is │
6238│GOC_ERROR_SERVER_SELEC‐ │ │ available, or none matches your read │
6239│TION │ │ preference, or you supplied an │
6240│ │ │ invalid mongoc_read_prefs_t. │
6241├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6242│MONGOC_ERROR_WRITE_CON‐ │ Error code from server. │ There was a write concern error or │
6243│CERN │ │ timeout from the server. │
6244├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6245│MONGOC_ERROR_TRANSAC‐ │ MONGOC_ERROR_TRANSACTION_INVALID │ You attempted to start a transaction │
6246│TION │ │ when one is already in progress, or │
6247│ │ │ commit or abort when there is no │
6248│ │ │ transaction. │
6249├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
6250│MON‐ │ Error code produced by libmongocrypt. │ An error occurred in the library │
6251│GOC_ERROR_CLIENT_SIDE_ENCRYP‐ │ │ responsible for Client Side Encryp‐ │
6252│TION │ │ tion │
6253└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
6254
6255 Error Labels
6256 In some cases your application must make decisions based on what cate‐
6257 gory of error the driver has returned, but these categories do not cor‐
6258 respond perfectly to an error domain or code. In such cases, error
6259 labels provide a reliable way to determine how your application should
6260 respond to an error.
6261
6262 Any C Driver function that has a bson_t out-parameter named reply may
6263 include error labels to the reply, in the form of a BSON field named
6264 "errorLabels" containing an array of strings:
6265
6266 { "errorLabels": [ "TransientTransactionError" ] }
6267
6268 Use mongoc_error_has_label to test if a reply contains a specific
6269 label. See mongoc_client_session_start_transaction for example code
6270 that demonstrates the use of error labels in application logic.
6271
6272 The following error labels are currently defined. Future versions of
6273 MongoDB may introduce new labels.
6274
6275 TransientTransactionError
6276 Within a multi-document transaction, certain errors can leave the
6277 transaction in an unknown or aborted state. These include write con‐
6278 flicts, primary stepdowns, and network errors. In response, the appli‐
6279 cation should abort the transaction and try the same sequence of opera‐
6280 tions again in a new transaction.
6281
6282 UnknownTransactionCommitResult
6283 When mongoc_client_session_commit_transaction encounters a network
6284 error or certain server errors, it is not known whether the transaction
6285 was committed. Applications should attempt to commit the transaction
6286 again until: the commit succeeds, the commit fails with an error not
6287 labeled "UnknownTransactionCommitResult", or the application chooses to
6288 give up.
6289
6290 Setting the Error API Version
6291 The driver's error reporting began with a design flaw: when the error
6292 domain is MONGOC_ERROR_COLLECTION, MONGOC_ERROR_QUERY, or MON‐
6293 GOC_ERROR_COMMAND, the error code might originate from the server or
6294 the driver. An application cannot always know where an error origi‐
6295 nated, and therefore cannot tell what the code means.
6296
6297 For example, if mongoc_collection_update_one sets the error's domain to
6298 MONGOC_ERROR_COLLECTION and its code to 24, the application cannot know
6299 whether 24 is the generic driver error code MONGOC_ERROR_COLLEC‐
6300 TION_UPDATE_FAILED or the specific server error code "LockTimeout".
6301
6302 To fix this flaw while preserving backward compatibility, the C Driver
6303 1.4 introduces "Error API Versions". Version 1, the default Error API
6304 Version, maintains the flawed behavior. Version 2 adds a new error
6305 domain, MONGOC_ERROR_SERVER. In Version 2, error codes originating on
6306 the server always have error domain MONGOC_ERROR_SERVER or MON‐
6307 GOC_ERROR_WRITE_CONCERN. When the driver uses Version 2 the application
6308 can always determine the origin and meaning of error codes. New appli‐
6309 cations should use Version 2, and existing applications should be
6310 updated to use Version 2 as well.
6311
6312 ┌──────────────────────┬──────────────────────┬──────────────────────┐
6313 │Error Source │ API Version 1 │ API Version 2 │
6314 ├──────────────────────┼──────────────────────┼──────────────────────┤
6315 │mongoc_cursor_error │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6316 ├──────────────────────┼──────────────────────┼──────────────────────┤
6317 │mongoc_client_com‐ │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6318 │mand_with_opts, │ │ │
6319 │mongoc_data‐ │ │ │
6320 │base_com‐ │ │ │
6321 │mand_with_opts, and │ │ │
6322 │other command func‐ │ │ │
6323 │tions │ │ │
6324 ├──────────────────────┼──────────────────────┼──────────────────────┤
6325 │mongoc_collec‐ │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6326 │tion_count_with_opts │ │ │
6327 │mon‐ │ │ │
6328 │goc_client_get_data‐ │ │ │
6329 │base_names_with_opts, │ │ │
6330 │and other command │ │ │
6331 │helper functions │ │ │
6332 ├──────────────────────┼──────────────────────┼──────────────────────┤
6333 │mongoc_collec‐ │ MONGOC_ERROR_COM‐ │ MONGOC_ERROR_SERVER │
6334 │tion_insert_one mon‐ │ MAND │ │
6335 │goc_collec‐ │ │ │
6336 │tion_insert_bulk mon‐ │ │ │
6337 │goc_collec‐ │ │ │
6338 │tion_update_one mon‐ │ │ │
6339 │goc_collec‐ │ │ │
6340 │tion_update_many mon‐ │ │ │
6341 │goc_collec‐ │ │ │
6342 │tion_replace_one mon‐ │ │ │
6343 │goc_collec‐ │ │ │
6344 │tion_delete_one mon‐ │ │ │
6345 │goc_collec‐ │ │ │
6346 │tion_delete_many │ │ │
6347 ├──────────────────────┼──────────────────────┼──────────────────────┤
6348 │mongoc_bulk_opera‐ │ MONGOC_ERROR_COM‐ │ MONGOC_ERROR_SERVER │
6349 │tion_execute │ MAND │ │
6350 ├──────────────────────┼──────────────────────┼──────────────────────┤
6351 │Write-concern timeout │ MON‐ │ MON‐ │
6352 │ │ GOC_ERROR_WRITE_CON‐ │ GOC_ERROR_WRITE_CON‐ │
6353 │ │ CERN │ CERN │
6354 └──────────────────────┴──────────────────────┴──────────────────────┘
6355
6356 The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY
6357 and MONGOC_ERROR_API_VERSION_2. Set the version with mon‐
6358 goc_client_set_error_api or mongoc_client_pool_set_error_api.
6359
6360 See Also
6361 MongoDB Server Error Codes
6362
6363 Object Lifecycle
6364 This page documents the order of creation and destruction for libmon‐
6365 goc's main struct types.
6366
6367 Clients and pools
6368 Call mongoc_init() once, before calling any other libmongoc functions,
6369 and call mongoc_cleanup() once before your program exits.
6370
6371 A program that uses libmongoc from multiple threads should create a
6372 mongoc_client_pool_t with mongoc_client_pool_new(). Each thread
6373 acquires a mongoc_client_t from the pool with mongoc_client_pool_pop()
6374 and returns it with mongoc_client_pool_push() when the thread is fin‐
6375 ished using it. To destroy the pool, first return all clients, then
6376 call mongoc_client_pool_destroy().
6377
6378 If your program uses libmongoc from only one thread, create a mon‐
6379 goc_client_t directly with mongoc_client_new() or mon‐
6380 goc_client_new_from_uri(). Destroy it with mongoc_client_destroy().
6381
6382 Databases, collections, and related objects
6383 You can create a mongoc_database_t or mongoc_collection_t from a mon‐
6384 goc_client_t, and create a mongoc_cursor_t or mongoc_bulk_operation_t
6385 from a mongoc_collection_t.
6386
6387 Each of these objects must be destroyed before the client they were
6388 created from, but their lifetimes are otherwise independent.
6389
6390 GridFS objects
6391 You can create a mongoc_gridfs_t from a mongoc_client_t, create a mon‐
6392 goc_gridfs_file_t or mongoc_gridfs_file_list_t from a mongoc_gridfs_t,
6393 create a mongoc_gridfs_file_t from a mongoc_gridfs_file_list_t, and
6394 create a mongoc_stream_t from a mongoc_gridfs_file_t.
6395
6396 Each of these objects depends on the object it was created from. Always
6397 destroy GridFS objects in the reverse of the order they were created.
6398 The sole exception is that a mongoc_gridfs_file_t need not be destroyed
6399 before the mongoc_gridfs_file_list_t it was created from.
6400
6401 GridFS bucket objects
6402 Create mongoc_gridfs_bucket_t with a mongoc_database_t derived from a
6403 mongoc_client_t. The mongoc_database_t is independent from the mon‐
6404 goc_gridfs_bucket_t. But the mongoc_client_t must outlive the mon‐
6405 goc_gridfs_bucket_t.
6406
6407 A mongoc_stream_t may be created from the mongoc_gridfs_bucket_t. The
6408 mongoc_gridfs_bucket_t must outlive the mongoc_stream_t.
6409
6410 Sessions
6411 Start a session with mongoc_client_start_session, use the session for a
6412 sequence of operations and multi-document transactions, then free it
6413 with mongoc_client_session_destroy(). Any mongoc_cursor_t or mon‐
6414 goc_change_stream_t using a session must be destroyed before the ses‐
6415 sion, and a session must be destroyed before the mongoc_client_t it
6416 came from.
6417
6418 By default, sessions are causally consistent. To disable causal consis‐
6419 tency, before starting a session create a mongoc_session_opt_t with
6420 mongoc_session_opts_new() and call mongoc_session_opts_set_causal_con‐
6421 sistency(), then free the struct with mongoc_session_opts_destroy.
6422
6423 Unacknowledged writes are prohibited with sessions.
6424
6425 A mongoc_client_session_t must be used by only one thread at a time.
6426 Due to session pooling, mongoc_client_start_session may return a ses‐
6427 sion that has been idle for some time and is about to be closed after
6428 its idle timeout. Use the session within one minute of acquiring it to
6429 refresh the session and avoid a timeout.
6430
6431 Client Side Encryption
6432 When configuring a mongoc_client_t for automatic encryption via mon‐
6433 goc_client_enable_auto_encryption(), if a separate key vault client is
6434 set in the options (via mongoc_auto_encryption_opts_set_key‐
6435 vault_client()) the key vault client must outlive the encrypted client.
6436
6437 When configuring a mongoc_client_pool_t for automatic encryption via
6438 mongoc_client_pool_enable_auto_encryption(), if a separate key vault
6439 client pool is set in the options (via mongoc_auto_encryp‐
6440 tion_opts_set_keyvault_client_pool()) the key vault client pool must
6441 outlive the encrypted client pool.
6442
6443 When creating a mongoc_client_encryption_t, the configured key vault
6444 client (set via mongoc_client_encryption_opts_set_keyvault_client())
6445 must outlive the mongoc_client_encryption_t.
6446
6447 GridFS
6448 The C driver includes two APIs for GridFS.
6449
6450 The older API consists of mongoc_gridfs_t and its derivatives. It con‐
6451 tains deprecated API, does not support read preferences, and is not
6452 recommended in new applications. It does not conform to the MongoDB
6453 GridFS specification.
6454
6455 The newer API consists of mongoc_gridfs_bucket_t and allows upload‐
6456 ing/downloading through derived mongoc_stream_t objects. It conforms to
6457 the MongoDB GridFS specification.
6458
6459 There is not always a straightforward upgrade path from an application
6460 built with mongoc_gridfs_t to mongoc_gridfs_bucket_t (e.g. a mon‐
6461 goc_gridfs_file_t provides functions to seek but mongoc_stream_t does
6462 not). But users are encouraged to upgrade when possible.
6463
6464 mongoc_auto_encryption_opts_t
6465 Options for enabling automatic encryption and decryption for
6466 Client-Side Field Level Encryption.
6467
6468 Synopsis
6469 typedef struct _mongoc_auto_encryption_opts_t mongoc_auto_encryption_opts_t;
6470
6471 See Also
6472 · The guide for Using Client-Side Field Level Encryption
6473
6474 mongoc_bulk_operation_t
6475 Bulk Write Operations
6476
6477 Synopsis
6478 typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t;
6479
6480 The opaque type mongoc_bulk_operation_t provides an abstraction for
6481 submitting multiple write operations as a single batch.
6482
6483 After adding all of the write operations to the mongoc_bulk_opera‐
6484 tion_t, call mongoc_bulk_operation_execute() to execute the operation.
6485
6486 WARNING:
6487 It is only valid to call mongoc_bulk_operation_execute() once. The
6488 mongoc_bulk_operation_t must be destroyed afterwards.
6489
6490 See Also
6491 Bulk Write Operations
6492
6493 mongoc_change_stream_t
6494 Synopsis
6495 #include <mongoc/mongoc.h>
6496
6497 typedef struct _mongoc_change_stream_t mongoc_change_stream_t;
6498
6499 mongoc_change_stream_t is a handle to a change stream. A collection
6500 change stream can be obtained using mongoc_collection_watch.
6501
6502 It is recommended to use a mongoc_change_stream_t and its functions
6503 instead of a raw aggregation with a $changeStream stage. For more
6504 information see the MongoDB Manual Entry on Change Streams.
6505
6506 Example
6507 example-collection-watch.c
6508
6509 #include <mongoc/mongoc.h>
6510
6511 int
6512 main ()
6513 {
6514 bson_t empty = BSON_INITIALIZER;
6515 const bson_t *doc;
6516 bson_t *to_insert = BCON_NEW ("x", BCON_INT32 (1));
6517 const bson_t *err_doc;
6518 bson_error_t error;
6519 const char *uri_string;
6520 mongoc_uri_t *uri;
6521 mongoc_client_t *client;
6522 mongoc_collection_t *coll;
6523 mongoc_change_stream_t *stream;
6524 mongoc_write_concern_t *wc = mongoc_write_concern_new ();
6525 bson_t opts = BSON_INITIALIZER;
6526 bool r;
6527
6528 mongoc_init ();
6529
6530 uri_string = "mongodb://"
6531 "localhost:27017,localhost:27018,localhost:"
6532 "27019/db?replicaSet=rs0";
6533
6534 uri = mongoc_uri_new_with_error (uri_string, &error);
6535 if (!uri) {
6536 fprintf (stderr,
6537 "failed to parse URI: %s\n"
6538 "error message: %s\n",
6539 uri_string,
6540 error.message);
6541 return EXIT_FAILURE;
6542 }
6543
6544 client = mongoc_client_new_from_uri (uri);
6545 if (!client) {
6546 return EXIT_FAILURE;
6547 }
6548
6549 coll = mongoc_client_get_collection (client, "db", "coll");
6550 stream = mongoc_collection_watch (coll, &empty, NULL);
6551
6552 mongoc_write_concern_set_wmajority (wc, 10000);
6553 mongoc_write_concern_append (wc, &opts);
6554 r = mongoc_collection_insert_one (coll, to_insert, &opts, NULL, &error);
6555 if (!r) {
6556 fprintf (stderr, "Error: %s\n", error.message);
6557 return EXIT_FAILURE;
6558 }
6559
6560 while (mongoc_change_stream_next (stream, &doc)) {
6561 char *as_json = bson_as_relaxed_extended_json (doc, NULL);
6562 fprintf (stderr, "Got document: %s\n", as_json);
6563 bson_free (as_json);
6564 }
6565
6566 if (mongoc_change_stream_error_document (stream, &error, &err_doc)) {
6567 if (!bson_empty (err_doc)) {
6568 fprintf (stderr,
6569 "Server Error: %s\n",
6570 bson_as_relaxed_extended_json (err_doc, NULL));
6571 } else {
6572 fprintf (stderr, "Client Error: %s\n", error.message);
6573 }
6574 return EXIT_FAILURE;
6575 }
6576
6577 bson_destroy (to_insert);
6578 mongoc_write_concern_destroy (wc);
6579 bson_destroy (&opts);
6580 mongoc_change_stream_destroy (stream);
6581 mongoc_collection_destroy (coll);
6582 mongoc_uri_destroy (uri);
6583 mongoc_client_destroy (client);
6584 mongoc_cleanup ();
6585
6586 return EXIT_SUCCESS;
6587 }
6588
6589
6590 Starting and Resuming
6591 All watch functions accept several options to indicate where a change
6592 stream should start returning changes from: resumeAfter, startAfter,
6593 and startAtOperationTime.
6594
6595 All changes returned by mongoc_change_stream_next include a resume
6596 token in the _id field. MongoDB 4.2 also includes an additional resume
6597 token in each "aggregate" and "getMore" command response, which points
6598 to the end of that response's batch. The current token is automatically
6599 cached by libmongoc. In the event of an error, libmongoc attempts to
6600 recreate the change stream starting where it left off by passing the
6601 cached resume token. libmongoc only attempts to resume once, but client
6602 applications can access the cached resume token with mon‐
6603 goc_change_stream_get_resume_token and use it for their own resume
6604 logic by passing it as either the resumeAfter or startAfter option.
6605
6606 Additionally, change streams can start returning changes at an opera‐
6607 tion time by using the startAtOperationTime field. This can be the
6608 timestamp returned in the operationTime field of a command reply.
6609
6610 resumeAfter, startAfter, and startAtOperationTime are mutually exclu‐
6611 sive options. Setting more than one will result in a server error.
6612
6613 The following example implements custom resuming logic, persisting the
6614 resume token in a file.
6615
6616 example-resume.c
6617
6618 #include <mongoc/mongoc.h>
6619
6620 /* An example implementation of custom resume logic in a change stream.
6621 * example-resume starts a client-wide change stream and persists the resume
6622 * token in a file "resume-token.json". On restart, if "resume-token.json"
6623 * exists, the change stream starts watching after the persisted resume token.
6624 *
6625 * This behavior allows a user to exit example-resume, and restart it later
6626 * without missing any change events.
6627 */
6628 #include <unistd.h>
6629
6630 static const char *RESUME_TOKEN_PATH = "resume-token.json";
6631
6632 static bool
6633 _save_resume_token (const bson_t *doc)
6634 {
6635 FILE *file_stream;
6636 bson_iter_t iter;
6637 bson_t resume_token_doc;
6638 char *as_json = NULL;
6639 size_t as_json_len;
6640 ssize_t r, n_written;
6641 const bson_value_t *resume_token;
6642
6643 if (!bson_iter_init_find (&iter, doc, "_id")) {
6644 fprintf (stderr, "reply does not contain operationTime.");
6645 return false;
6646 }
6647 resume_token = bson_iter_value (&iter);
6648 /* store the resume token in a document, { resumeAfter: <resume token> }
6649 * which we can later append easily. */
6650 file_stream = fopen (RESUME_TOKEN_PATH, "w+");
6651 if (!file_stream) {
6652 fprintf (stderr, "failed to open %s for writing\n", RESUME_TOKEN_PATH);
6653 return false;
6654 }
6655 bson_init (&resume_token_doc);
6656 BSON_APPEND_VALUE (&resume_token_doc, "resumeAfter", resume_token);
6657 as_json = bson_as_canonical_extended_json (&resume_token_doc, &as_json_len);
6658 bson_destroy (&resume_token_doc);
6659 n_written = 0;
6660 while (n_written < as_json_len) {
6661 r = fwrite ((void *) (as_json + n_written),
6662 sizeof (char),
6663 as_json_len - n_written,
6664 file_stream);
6665 if (r == -1) {
6666 fprintf (stderr, "failed to write to %s\n", RESUME_TOKEN_PATH);
6667 bson_free (as_json);
6668 fclose (file_stream);
6669 return false;
6670 }
6671 n_written += r;
6672 }
6673
6674 bson_free (as_json);
6675 fclose (file_stream);
6676 return true;
6677 }
6678
6679 bool
6680 _load_resume_token (bson_t *opts)
6681 {
6682 bson_error_t error;
6683 bson_json_reader_t *reader;
6684 bson_t doc;
6685
6686 /* if the file does not exist, skip. */
6687 if (-1 == access (RESUME_TOKEN_PATH, R_OK)) {
6688 return true;
6689 }
6690 reader = bson_json_reader_new_from_file (RESUME_TOKEN_PATH, &error);
6691 if (!reader) {
6692 fprintf (stderr,
6693 "failed to open %s for reading: %s\n",
6694 RESUME_TOKEN_PATH,
6695 error.message);
6696 return false;
6697 }
6698
6699 bson_init (&doc);
6700 if (-1 == bson_json_reader_read (reader, &doc, &error)) {
6701 fprintf (stderr, "failed to read doc from %s\n", RESUME_TOKEN_PATH);
6702 bson_destroy (&doc);
6703 bson_json_reader_destroy (reader);
6704 return false;
6705 }
6706
6707 printf ("found cached resume token in %s, resuming change stream.\n",
6708 RESUME_TOKEN_PATH);
6709
6710 bson_concat (opts, &doc);
6711 bson_destroy (&doc);
6712 bson_json_reader_destroy (reader);
6713 return true;
6714 }
6715
6716 int
6717 main ()
6718 {
6719 int exit_code = EXIT_FAILURE;
6720 const char *uri_string;
6721 mongoc_uri_t *uri = NULL;
6722 bson_error_t error;
6723 mongoc_client_t *client = NULL;
6724 bson_t pipeline = BSON_INITIALIZER;
6725 bson_t opts = BSON_INITIALIZER;
6726 mongoc_change_stream_t *stream = NULL;
6727 const bson_t *doc;
6728
6729 const int max_time = 30; /* max amount of time, in seconds, that
6730 mongoc_change_stream_next can block. */
6731
6732 mongoc_init ();
6733 uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
6734 uri = mongoc_uri_new_with_error (uri_string, &error);
6735 if (!uri) {
6736 fprintf (stderr,
6737 "failed to parse URI: %s\n"
6738 "error message: %s\n",
6739 uri_string,
6740 error.message);
6741 goto cleanup;
6742 }
6743
6744 client = mongoc_client_new_from_uri (uri);
6745 if (!client) {
6746 goto cleanup;
6747 }
6748
6749 if (!_load_resume_token (&opts)) {
6750 goto cleanup;
6751 }
6752 BSON_APPEND_INT64 (&opts, "maxAwaitTimeMS", max_time * 1000);
6753
6754 printf ("listening for changes on the client (max %d seconds).\n", max_time);
6755 stream = mongoc_client_watch (client, &pipeline, &opts);
6756
6757 while (mongoc_change_stream_next (stream, &doc)) {
6758 char *as_json;
6759
6760 as_json = bson_as_canonical_extended_json (doc, NULL);
6761 printf ("change received: %s\n", as_json);
6762 bson_free (as_json);
6763 if (!_save_resume_token (doc)) {
6764 goto cleanup;
6765 }
6766 }
6767
6768 exit_code = EXIT_SUCCESS;
6769
6770 cleanup:
6771 mongoc_uri_destroy (uri);
6772 bson_destroy (&pipeline);
6773 bson_destroy (&opts);
6774 mongoc_change_stream_destroy (stream);
6775 mongoc_client_destroy (client);
6776 mongoc_cleanup ();
6777 return exit_code;
6778 }
6779
6780
6781 The following example shows using startAtOperationTime to synchronize a
6782 change stream with another operation.
6783
6784 example-start-at-optime.c
6785
6786 /* An example of starting a change stream with startAtOperationTime. */
6787 #include <mongoc/mongoc.h>
6788
6789 int
6790 main ()
6791 {
6792 int exit_code = EXIT_FAILURE;
6793 const char *uri_string;
6794 mongoc_uri_t *uri = NULL;
6795 bson_error_t error;
6796 mongoc_client_t *client = NULL;
6797 mongoc_collection_t *coll = NULL;
6798 bson_t pipeline = BSON_INITIALIZER;
6799 bson_t opts = BSON_INITIALIZER;
6800 mongoc_change_stream_t *stream = NULL;
6801 bson_iter_t iter;
6802 const bson_t *doc;
6803 bson_value_t cached_operation_time = {0};
6804 int i;
6805 bool r;
6806
6807 mongoc_init ();
6808 uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
6809 uri = mongoc_uri_new_with_error (uri_string, &error);
6810 if (!uri) {
6811 fprintf (stderr,
6812 "failed to parse URI: %s\n"
6813 "error message: %s\n",
6814 uri_string,
6815 error.message);
6816 goto cleanup;
6817 }
6818
6819 client = mongoc_client_new_from_uri (uri);
6820 if (!client) {
6821 goto cleanup;
6822 }
6823
6824 /* insert five documents. */
6825 coll = mongoc_client_get_collection (client, "db", "coll");
6826 for (i = 0; i < 5; i++) {
6827 bson_t reply;
6828 bson_t *insert_cmd = BCON_NEW ("insert",
6829 "coll",
6830 "documents",
6831 "[",
6832 "{",
6833 "x",
6834 BCON_INT64 (i),
6835 "}",
6836 "]");
6837
6838 r = mongoc_collection_write_command_with_opts (
6839 coll, insert_cmd, NULL, &reply, &error);
6840 bson_destroy (insert_cmd);
6841 if (!r) {
6842 bson_destroy (&reply);
6843 fprintf (stderr, "failed to insert: %s\n", error.message);
6844 goto cleanup;
6845 }
6846 if (i == 0) {
6847 /* cache the operation time in the first reply. */
6848 if (bson_iter_init_find (&iter, &reply, "operationTime")) {
6849 bson_value_copy (bson_iter_value (&iter), &cached_operation_time);
6850 } else {
6851 fprintf (stderr, "reply does not contain operationTime.");
6852 bson_destroy (&reply);
6853 goto cleanup;
6854 }
6855 }
6856 bson_destroy (&reply);
6857 }
6858
6859 /* start a change stream at the first returned operationTime. */
6860 BSON_APPEND_VALUE (&opts, "startAtOperationTime", &cached_operation_time);
6861 stream = mongoc_collection_watch (coll, &pipeline, &opts);
6862
6863 /* since the change stream started at the operation time of the first
6864 * insert, the five inserts are returned. */
6865 printf ("listening for changes on db.coll:\n");
6866 while (mongoc_change_stream_next (stream, &doc)) {
6867 char *as_json;
6868
6869 as_json = bson_as_canonical_extended_json (doc, NULL);
6870 printf ("change received: %s\n", as_json);
6871 bson_free (as_json);
6872 }
6873
6874 exit_code = EXIT_SUCCESS;
6875
6876 cleanup:
6877 mongoc_uri_destroy (uri);
6878 bson_destroy (&pipeline);
6879 bson_destroy (&opts);
6880 if (cached_operation_time.value_type) {
6881 bson_value_destroy (&cached_operation_time);
6882 }
6883 mongoc_change_stream_destroy (stream);
6884 mongoc_collection_destroy (coll);
6885 mongoc_client_destroy (client);
6886 mongoc_cleanup ();
6887 return exit_code;
6888 }
6889
6890
6891 mongoc_client_encryption_t
6892 Synopsis
6893 typedef struct _mongoc_client_encryption_t mongoc_client_encryption_t;
6894
6895 mongoc_client_encryption_t provides utility functions for Client-Side
6896 Field Level Encryption. See the guide for Using Client-Side Field Level
6897 Encryption.
6898
6899 Thread Safety
6900 mongoc_client_encryption_t is NOT thread-safe and should only be used
6901 in the same thread as the mongoc_client_t that is configured via mon‐
6902 goc_client_encryption_opts_set_keyvault_client().
6903
6904 Lifecycle
6905 The key vault client, configured via mongoc_client_encryp‐
6906 tion_opts_set_keyvault_client(), must outlive the mongoc_client_encryp‐
6907 tion_t.
6908
6909 See also
6910 · mongoc_client_enable_auto_encryption()
6911
6912 · mongoc_client_pool_enable_auto_encryption()
6913
6914 · The guide for Using Client-Side Field Level Encryption for libmongoc
6915
6916 · The MongoDB Manual for Client-Side Field Level Encryption
6917
6918 mongoc_client_encryption_datakey_opts_t
6919 Synopsis
6920 typedef struct _mongoc_client_encryption_datakey_opts_t mongoc_client_encryption_datakey_opts_t;
6921
6922 Used to set options for mongoc_client_encryption_create_datakey().
6923
6924 See also
6925 · mongoc_client_encryption_create_datakey()
6926
6927 mongoc_client_encryption_encrypt_opts_t
6928 Synopsis
6929 typedef struct _mongoc_client_encryption_encrypt_opts_t mongoc_client_encryption_encrypt_opts_t;
6930
6931 Used to set options for mongoc_client_encryption_encrypt().
6932
6933 See also
6934 · mongoc_client_encryption_encrypt()
6935
6936 mongoc_client_encryption_opts_t
6937 Synopsis
6938 typedef struct _mongoc_client_encryption_opts_t mongoc_client_encryption_opts_t;
6939
6940 Used to set options for mongoc_client_encryption_new().
6941
6942 See also
6943 · mongoc_client_encryption_new()
6944
6945 mongoc_client_pool_t
6946 A connection pool for multi-threaded programs. See connection-pooling.
6947
6948 Synopsis
6949 typedef struct _mongoc_client_pool_t mongoc_client_pool_t
6950
6951 mongoc_client_pool_t is the basis for multi-threading in the MongoDB C
6952 driver. Since mongoc_client_t structures are not thread-safe, this
6953 structure is used to retrieve a new mongoc_client_t for a given thread.
6954 This structure is thread-safe, except for its destructor method, mon‐
6955 goc_client_pool_destroy, which is not thread-safe and must only be
6956 called from one thread.
6957
6958 Example
6959 example-pool.c
6960
6961 /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
6962 * libmongoc-1.0) */
6963
6964 /* ./example-pool [CONNECTION_STRING] */
6965
6966 #include <mongoc/mongoc.h>
6967 #include <pthread.h>
6968 #include <stdio.h>
6969
6970 static pthread_mutex_t mutex;
6971 static bool in_shutdown = false;
6972
6973 static void *
6974 worker (void *data)
6975 {
6976 mongoc_client_pool_t *pool = data;
6977 mongoc_client_t *client;
6978 bson_t ping = BSON_INITIALIZER;
6979 bson_error_t error;
6980 bool r;
6981
6982 BSON_APPEND_INT32 (&ping, "ping", 1);
6983
6984 while (true) {
6985 client = mongoc_client_pool_pop (pool);
6986 /* Do something with client. If you are writing an HTTP server, you
6987 * probably only want to hold onto the client for the portion of the
6988 * request performing database queries.
6989 */
6990 r = mongoc_client_command_simple (
6991 client, "admin", &ping, NULL, NULL, &error);
6992
6993 if (!r) {
6994 fprintf (stderr, "%s\n", error.message);
6995 }
6996
6997 mongoc_client_pool_push (pool, client);
6998
6999 pthread_mutex_lock (&mutex);
7000 if (in_shutdown || !r) {
7001 pthread_mutex_unlock (&mutex);
7002 break;
7003 }
7004
7005 pthread_mutex_unlock (&mutex);
7006 }
7007
7008 bson_destroy (&ping);
7009 return NULL;
7010 }
7011
7012 int
7013 main (int argc, char *argv[])
7014 {
7015 const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
7016 mongoc_uri_t *uri;
7017 bson_error_t error;
7018 mongoc_client_pool_t *pool;
7019 pthread_t threads[10];
7020 unsigned i;
7021 void *ret;
7022
7023 pthread_mutex_init (&mutex, NULL);
7024 mongoc_init ();
7025
7026 if (argc > 1) {
7027 uri_string = argv[1];
7028 }
7029
7030 uri = mongoc_uri_new_with_error (uri_string, &error);
7031 if (!uri) {
7032 fprintf (stderr,
7033 "failed to parse URI: %s\n"
7034 "error message: %s\n",
7035 uri_string,
7036 error.message);
7037 return EXIT_FAILURE;
7038 }
7039
7040 pool = mongoc_client_pool_new (uri);
7041 mongoc_client_pool_set_error_api (pool, 2);
7042
7043 for (i = 0; i < 10; i++) {
7044 pthread_create (&threads[i], NULL, worker, pool);
7045 }
7046
7047 sleep (10);
7048 pthread_mutex_lock (&mutex);
7049 in_shutdown = true;
7050 pthread_mutex_unlock (&mutex);
7051
7052 for (i = 0; i < 10; i++) {
7053 pthread_join (threads[i], &ret);
7054 }
7055
7056 mongoc_client_pool_destroy (pool);
7057 mongoc_uri_destroy (uri);
7058
7059 mongoc_cleanup ();
7060
7061 return EXIT_SUCCESS;
7062 }
7063
7064
7065 mongoc_client_session_t
7066 Use a session for a sequence of operations, optionally with causal con‐
7067 sistency. See the MongoDB Manual Entry for Causal Consistency.
7068
7069 Synopsis
7070 Start a session with mongoc_client_start_session, use the session for a
7071 sequence of operations and multi-document transactions, then free it
7072 with mongoc_client_session_destroy(). Any mongoc_cursor_t or mon‐
7073 goc_change_stream_t using a session must be destroyed before the ses‐
7074 sion, and a session must be destroyed before the mongoc_client_t it
7075 came from.
7076
7077 By default, sessions are causally consistent. To disable causal consis‐
7078 tency, before starting a session create a mongoc_session_opt_t with
7079 mongoc_session_opts_new() and call mongoc_session_opts_set_causal_con‐
7080 sistency(), then free the struct with mongoc_session_opts_destroy.
7081
7082 Unacknowledged writes are prohibited with sessions.
7083
7084 A mongoc_client_session_t must be used by only one thread at a time.
7085 Due to session pooling, mongoc_client_start_session may return a ses‐
7086 sion that has been idle for some time and is about to be closed after
7087 its idle timeout. Use the session within one minute of acquiring it to
7088 refresh the session and avoid a timeout.
7089
7090 Example
7091 example-session.c
7092
7093 /* gcc example-session.c -o example-session \
7094 * $(pkg-config --cflags --libs libmongoc-1.0) */
7095
7096 /* ./example-session [CONNECTION_STRING] */
7097
7098 #include <stdio.h>
7099 #include <mongoc/mongoc.h>
7100
7101
7102 int
7103 main (int argc, char *argv[])
7104 {
7105 int exit_code = EXIT_FAILURE;
7106
7107 mongoc_client_t *client = NULL;
7108 const char *uri_string = "mongodb://127.0.0.1/?appname=session-example";
7109 mongoc_uri_t *uri = NULL;
7110 mongoc_client_session_t *client_session = NULL;
7111 mongoc_collection_t *collection = NULL;
7112 bson_error_t error;
7113 bson_t *selector = NULL;
7114 bson_t *update = NULL;
7115 bson_t *update_opts = NULL;
7116 bson_t *find_opts = NULL;
7117 mongoc_read_prefs_t *secondary = NULL;
7118 mongoc_cursor_t *cursor = NULL;
7119 const bson_t *doc;
7120 char *str;
7121 bool r;
7122
7123 mongoc_init ();
7124
7125 if (argc > 1) {
7126 uri_string = argv[1];
7127 }
7128
7129 uri = mongoc_uri_new_with_error (uri_string, &error);
7130 if (!uri) {
7131 fprintf (stderr,
7132 "failed to parse URI: %s\n"
7133 "error message: %s\n",
7134 uri_string,
7135 error.message);
7136 goto done;
7137 }
7138
7139 client = mongoc_client_new_from_uri (uri);
7140 if (!client) {
7141 goto done;
7142 }
7143
7144 mongoc_client_set_error_api (client, 2);
7145
7146 /* pass NULL for options - by default the session is causally consistent */
7147 client_session = mongoc_client_start_session (client, NULL, &error);
7148 if (!client_session) {
7149 fprintf (stderr, "Failed to start session: %s\n", error.message);
7150 goto done;
7151 }
7152
7153 collection = mongoc_client_get_collection (client, "test", "collection");
7154 selector = BCON_NEW ("_id", BCON_INT32 (1));
7155 update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}");
7156 update_opts = bson_new ();
7157 if (!mongoc_client_session_append (client_session, update_opts, &error)) {
7158 fprintf (stderr, "Could not add session to opts: %s\n", error.message);
7159 goto done;
7160 }
7161
7162 r = mongoc_collection_update_one (
7163 collection, selector, update, update_opts, NULL /* reply */, &error);
7164
7165 if (!r) {
7166 fprintf (stderr, "Update failed: %s\n", error.message);
7167 goto done;
7168 }
7169
7170 bson_destroy (selector);
7171 selector = BCON_NEW ("_id", BCON_INT32 (1));
7172 secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
7173
7174 find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000));
7175 if (!mongoc_client_session_append (client_session, find_opts, &error)) {
7176 fprintf (stderr, "Could not add session to opts: %s\n", error.message);
7177 goto done;
7178 };
7179
7180 /* read from secondary. since we're in a causally consistent session, the
7181 * data is guaranteed to reflect the update we did on the primary. the query
7182 * blocks waiting for the secondary to catch up, if necessary, or times out
7183 * and fails after 2000 ms.
7184 */
7185 cursor = mongoc_collection_find_with_opts (
7186 collection, selector, find_opts, secondary);
7187
7188 while (mongoc_cursor_next (cursor, &doc)) {
7189 str = bson_as_json (doc, NULL);
7190 fprintf (stdout, "%s\n", str);
7191 bson_free (str);
7192 }
7193
7194 if (mongoc_cursor_error (cursor, &error)) {
7195 fprintf (stderr, "Cursor Failure: %s\n", error.message);
7196 goto done;
7197 }
7198
7199 exit_code = EXIT_SUCCESS;
7200
7201 done:
7202 if (find_opts) {
7203 bson_destroy (find_opts);
7204 }
7205 if (update) {
7206 bson_destroy (update);
7207 }
7208 if (selector) {
7209 bson_destroy (selector);
7210 }
7211 if (update_opts) {
7212 bson_destroy (update_opts);
7213 }
7214 if (secondary) {
7215 mongoc_read_prefs_destroy (secondary);
7216 }
7217 /* destroy cursor, collection, session before the client they came from */
7218 if (cursor) {
7219 mongoc_cursor_destroy (cursor);
7220 }
7221 if (collection) {
7222 mongoc_collection_destroy (collection);
7223 }
7224 if (client_session) {
7225 mongoc_client_session_destroy (client_session);
7226 }
7227 if (uri) {
7228 mongoc_uri_destroy (uri);
7229 }
7230 if (client) {
7231 mongoc_client_destroy (client);
7232 }
7233
7234 mongoc_cleanup ();
7235
7236 return exit_code;
7237 }
7238
7239
7240 mongoc_client_session_with_transaction_cb_t
7241 Synopsis
7242 typedef bool (*mongoc_client_session_with_transaction_cb_t) (
7243 mongoc_client_session_t *session,
7244 void *ctx,
7245 bson_t **reply,
7246 bson_error_t *error);
7247
7248 Provide this callback to mongoc_client_session_with_transaction. The
7249 callback should run a sequence of operations meant to be contained
7250 within a transaction. The callback should not attempt to start or com‐
7251 mit transactions.
7252
7253 Parameters
7254 · session: A mongoc_client_session_t.
7255
7256 · ctx: A void* set to the the user-provided ctx passed to mon‐
7257 goc_client_session_with_transaction.
7258
7259 · reply: An optional location for a bson_t or NULL. The callback should
7260 set this if it runs any operations against the server and receives
7261 replies.
7262
7263 · error: A bson_error_t. The callback should set this if it receives
7264 any errors while running operations against the server.
7265
7266 Return
7267 Returns true for success and false on failure. If cb returns false then
7268 it should also set error.
7269
7270 See Also
7271 mongoc_client_session_with_transaction
7272
7273 mongoc_client_t
7274 A single-threaded MongoDB connection. See connection-pooling.
7275
7276 Synopsis
7277 typedef struct _mongoc_client_t mongoc_client_t;
7278
7279 typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
7280 const mongoc_uri_t *uri,
7281 const mongoc_host_list_t *host,
7282 void *user_data,
7283 bson_error_t *error);
7284
7285 mongoc_client_t is an opaque type that provides access to a MongoDB
7286 server, replica set, or sharded cluster. It maintains management of
7287 underlying sockets and routing to individual nodes based on mon‐
7288 goc_read_prefs_t or mongoc_write_concern_t.
7289
7290 Streams
7291 The underlying transport for a given client can be customized, wrapped
7292 or replaced by any implementation that fulfills mongoc_stream_t. A cus‐
7293 tom transport can be set with mongoc_client_set_stream_initiator().
7294
7295 Thread Safety
7296 mongoc_client_t is NOT thread-safe and should only be used from one
7297 thread at a time. When used in multi-threaded scenarios, it is recom‐
7298 mended that you use the thread-safe mongoc_client_pool_t to retrieve a
7299 mongoc_client_t for your thread.
7300
7301 Example
7302 example-client.c
7303
7304 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
7305 * libmongoc-1.0) */
7306
7307 /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
7308
7309 #include <mongoc/mongoc.h>
7310 #include <stdio.h>
7311 #include <stdlib.h>
7312
7313 int
7314 main (int argc, char *argv[])
7315 {
7316 mongoc_client_t *client;
7317 mongoc_collection_t *collection;
7318 mongoc_cursor_t *cursor;
7319 bson_error_t error;
7320 const bson_t *doc;
7321 const char *collection_name = "test";
7322 bson_t query;
7323 char *str;
7324 const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
7325 mongoc_uri_t *uri;
7326
7327 mongoc_init ();
7328 if (argc > 1) {
7329 uri_string = argv[1];
7330 }
7331
7332 if (argc > 2) {
7333 collection_name = argv[2];
7334 }
7335
7336 uri = mongoc_uri_new_with_error (uri_string, &error);
7337 if (!uri) {
7338 fprintf (stderr,
7339 "failed to parse URI: %s\n"
7340 "error message: %s\n",
7341 uri_string,
7342 error.message);
7343 return EXIT_FAILURE;
7344 }
7345
7346 client = mongoc_client_new_from_uri (uri);
7347 if (!client) {
7348 return EXIT_FAILURE;
7349 }
7350
7351 mongoc_client_set_error_api (client, 2);
7352
7353 bson_init (&query);
7354 collection = mongoc_client_get_collection (client, "test", collection_name);
7355 cursor = mongoc_collection_find_with_opts (
7356 collection,
7357 &query,
7358 NULL, /* additional options */
7359 NULL); /* read prefs, NULL for default */
7360
7361 while (mongoc_cursor_next (cursor, &doc)) {
7362 str = bson_as_canonical_extended_json (doc, NULL);
7363 fprintf (stdout, "%s\n", str);
7364 bson_free (str);
7365 }
7366
7367 if (mongoc_cursor_error (cursor, &error)) {
7368 fprintf (stderr, "Cursor Failure: %s\n", error.message);
7369 return EXIT_FAILURE;
7370 }
7371
7372 bson_destroy (&query);
7373 mongoc_cursor_destroy (cursor);
7374 mongoc_collection_destroy (collection);
7375 mongoc_uri_destroy (uri);
7376 mongoc_client_destroy (client);
7377 mongoc_cleanup ();
7378
7379 return EXIT_SUCCESS;
7380 }
7381
7382
7383 mongoc_collection_t
7384 Synopsis
7385 typedef struct _mongoc_collection_t mongoc_collection_t;
7386
7387 mongoc_collection_t provides access to a MongoDB collection. This han‐
7388 dle is useful for actions for most CRUD operations, I.e. insert,
7389 update, delete, find, etc.
7390
7391 Read Preferences and Write Concerns
7392 Read preferences and write concerns are inherited from the parent
7393 client. They can be overridden by set_* commands if so desired.
7394
7395 mongoc_cursor_t
7396 Client-side cursor abstraction
7397
7398 Synopsis
7399 typedef struct _mongoc_cursor_t mongoc_cursor_t;
7400
7401 mongoc_cursor_t provides access to a MongoDB query cursor. It wraps up
7402 the wire protocol negotiation required to initiate a query and retrieve
7403 an unknown number of documents.
7404
7405 Common cursor operations include:
7406
7407 · Determine which host we've connected to with mongoc_cur‐
7408 sor_get_host().
7409
7410 · Retrieve more records with repeated calls to mongoc_cursor_next().
7411
7412 · Clone a query to repeat execution at a later point with mongoc_cur‐
7413 sor_clone().
7414
7415 · Test for errors with mongoc_cursor_error().
7416
7417 Cursors are lazy, meaning that no connection is established and no net‐
7418 work traffic occurs until the first call to mongoc_cursor_next().
7419
7420 Thread Safety
7421 mongoc_cursor_t is NOT thread safe. It may only be used from within the
7422 thread in which it was created.
7423
7424 Example
7425 Query MongoDB and iterate results
7426
7427 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
7428 * libmongoc-1.0) */
7429
7430 /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
7431
7432 #include <mongoc/mongoc.h>
7433 #include <stdio.h>
7434 #include <stdlib.h>
7435
7436 int
7437 main (int argc, char *argv[])
7438 {
7439 mongoc_client_t *client;
7440 mongoc_collection_t *collection;
7441 mongoc_cursor_t *cursor;
7442 bson_error_t error;
7443 const bson_t *doc;
7444 const char *collection_name = "test";
7445 bson_t query;
7446 char *str;
7447 const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
7448 mongoc_uri_t *uri;
7449
7450 mongoc_init ();
7451 if (argc > 1) {
7452 uri_string = argv[1];
7453 }
7454
7455 if (argc > 2) {
7456 collection_name = argv[2];
7457 }
7458
7459 uri = mongoc_uri_new_with_error (uri_string, &error);
7460 if (!uri) {
7461 fprintf (stderr,
7462 "failed to parse URI: %s\n"
7463 "error message: %s\n",
7464 uri_string,
7465 error.message);
7466 return EXIT_FAILURE;
7467 }
7468
7469 client = mongoc_client_new_from_uri (uri);
7470 if (!client) {
7471 return EXIT_FAILURE;
7472 }
7473
7474 mongoc_client_set_error_api (client, 2);
7475
7476 bson_init (&query);
7477 collection = mongoc_client_get_collection (client, "test", collection_name);
7478 cursor = mongoc_collection_find_with_opts (
7479 collection,
7480 &query,
7481 NULL, /* additional options */
7482 NULL); /* read prefs, NULL for default */
7483
7484 while (mongoc_cursor_next (cursor, &doc)) {
7485 str = bson_as_canonical_extended_json (doc, NULL);
7486 fprintf (stdout, "%s\n", str);
7487 bson_free (str);
7488 }
7489
7490 if (mongoc_cursor_error (cursor, &error)) {
7491 fprintf (stderr, "Cursor Failure: %s\n", error.message);
7492 return EXIT_FAILURE;
7493 }
7494
7495 bson_destroy (&query);
7496 mongoc_cursor_destroy (cursor);
7497 mongoc_collection_destroy (collection);
7498 mongoc_uri_destroy (uri);
7499 mongoc_client_destroy (client);
7500 mongoc_cleanup ();
7501
7502 return EXIT_SUCCESS;
7503 }
7504
7505
7506 mongoc_database_t
7507 MongoDB Database Abstraction
7508
7509 Synopsis
7510 typedef struct _mongoc_database_t mongoc_database_t;
7511
7512 mongoc_database_t provides access to a MongoDB database. This handle is
7513 useful for actions a particular database object. It is not a container
7514 for mongoc_collection_t structures.
7515
7516 Read preferences and write concerns are inherited from the parent
7517 client. They can be overridden with mongoc_database_set_read_prefs()
7518 and mongoc_database_set_write_concern().
7519
7520 Examples
7521 #include <mongoc/mongoc.h>
7522
7523 int
7524 main (int argc, char *argv[])
7525 {
7526 mongoc_database_t *database;
7527 mongoc_client_t *client;
7528
7529 mongoc_init ();
7530
7531 client = mongoc_client_new ("mongodb://localhost/");
7532 database = mongoc_client_get_database (client, "test");
7533
7534 mongoc_database_destroy (database);
7535 mongoc_client_destroy (client);
7536
7537 mongoc_cleanup ();
7538
7539 return 0;
7540 }
7541
7542 mongoc_delete_flags_t
7543 Flags for deletion operations
7544
7545 Synopsis
7546 typedef enum {
7547 MONGOC_DELETE_NONE = 0,
7548 MONGOC_DELETE_SINGLE_REMOVE = 1 << 0,
7549 } mongoc_delete_flags_t;
7550
7551 Deprecated
7552 WARNING:
7553 These flags are deprecated and should not be used in new code.
7554
7555 Please use mongoc_collection_delete_one() or mongoc_collec‐
7556 tion_delete_many() instead.
7557
7558 mongoc_find_and_modify_opts_t
7559 find_and_modify abstraction
7560
7561 Synopsis
7562 mongoc_find_and_modify_opts_t is a builder interface to construct a
7563 find_and_modify command.
7564
7565 It was created to be able to accommodate new arguments to the MongoDB
7566 find_and_modify command.
7567
7568 As of MongoDB 3.2, the mongoc_write_concern_t specified on the mon‐
7569 goc_collection_t will be used, if any.
7570
7571 Example
7572 flags.c
7573
7574 void
7575 fam_flags (mongoc_collection_t *collection)
7576 {
7577 mongoc_find_and_modify_opts_t *opts;
7578 bson_t reply;
7579 bson_error_t error;
7580 bson_t query = BSON_INITIALIZER;
7581 bson_t *update;
7582 bool success;
7583
7584
7585 /* Find Zlatan Ibrahimovic, the striker */
7586 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7587 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7588 BSON_APPEND_UTF8 (&query, "profession", "Football player");
7589 BSON_APPEND_INT32 (&query, "age", 34);
7590 BSON_APPEND_INT32 (
7591 &query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62));
7592
7593 /* Add his football position */
7594 update = BCON_NEW ("$set", "{", "position", BCON_UTF8 ("striker"), "}");
7595
7596 opts = mongoc_find_and_modify_opts_new ();
7597
7598 mongoc_find_and_modify_opts_set_update (opts, update);
7599
7600 /* Create the document if it didn't exist, and return the updated document */
7601 mongoc_find_and_modify_opts_set_flags (
7602 opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7603
7604 success = mongoc_collection_find_and_modify_with_opts (
7605 collection, &query, opts, &reply, &error);
7606
7607 if (success) {
7608 char *str;
7609
7610 str = bson_as_canonical_extended_json (&reply, NULL);
7611 printf ("%s\n", str);
7612 bson_free (str);
7613 } else {
7614 fprintf (
7615 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7616 }
7617
7618 bson_destroy (&reply);
7619 bson_destroy (update);
7620 bson_destroy (&query);
7621 mongoc_find_and_modify_opts_destroy (opts);
7622 }
7623
7624
7625 bypass.c
7626
7627 void
7628 fam_bypass (mongoc_collection_t *collection)
7629 {
7630 mongoc_find_and_modify_opts_t *opts;
7631 bson_t reply;
7632 bson_t *update;
7633 bson_error_t error;
7634 bson_t query = BSON_INITIALIZER;
7635 bool success;
7636
7637
7638 /* Find Zlatan Ibrahimovic, the striker */
7639 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7640 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7641 BSON_APPEND_UTF8 (&query, "profession", "Football player");
7642
7643 /* Bump his age */
7644 update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
7645
7646 opts = mongoc_find_and_modify_opts_new ();
7647 mongoc_find_and_modify_opts_set_update (opts, update);
7648 /* He can still play, even though he is pretty old. */
7649 mongoc_find_and_modify_opts_set_bypass_document_validation (opts, true);
7650
7651 success = mongoc_collection_find_and_modify_with_opts (
7652 collection, &query, opts, &reply, &error);
7653
7654 if (success) {
7655 char *str;
7656
7657 str = bson_as_canonical_extended_json (&reply, NULL);
7658 printf ("%s\n", str);
7659 bson_free (str);
7660 } else {
7661 fprintf (
7662 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7663 }
7664
7665 bson_destroy (&reply);
7666 bson_destroy (update);
7667 bson_destroy (&query);
7668 mongoc_find_and_modify_opts_destroy (opts);
7669 }
7670
7671
7672 update.c
7673
7674 void
7675 fam_update (mongoc_collection_t *collection)
7676 {
7677 mongoc_find_and_modify_opts_t *opts;
7678 bson_t *update;
7679 bson_t reply;
7680 bson_error_t error;
7681 bson_t query = BSON_INITIALIZER;
7682 bool success;
7683
7684
7685 /* Find Zlatan Ibrahimovic */
7686 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7687 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7688
7689 /* Make him a book author */
7690 update = BCON_NEW ("$set", "{", "author", BCON_BOOL (true), "}");
7691
7692 opts = mongoc_find_and_modify_opts_new ();
7693 /* Note that the document returned is the _previous_ version of the document
7694 * To fetch the modified new version, use
7695 * mongoc_find_and_modify_opts_set_flags (opts,
7696 * MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7697 */
7698 mongoc_find_and_modify_opts_set_update (opts, update);
7699
7700 success = mongoc_collection_find_and_modify_with_opts (
7701 collection, &query, opts, &reply, &error);
7702
7703 if (success) {
7704 char *str;
7705
7706 str = bson_as_canonical_extended_json (&reply, NULL);
7707 printf ("%s\n", str);
7708 bson_free (str);
7709 } else {
7710 fprintf (
7711 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7712 }
7713
7714 bson_destroy (&reply);
7715 bson_destroy (update);
7716 bson_destroy (&query);
7717 mongoc_find_and_modify_opts_destroy (opts);
7718 }
7719
7720
7721 fields.c
7722
7723 void
7724 fam_fields (mongoc_collection_t *collection)
7725 {
7726 mongoc_find_and_modify_opts_t *opts;
7727 bson_t fields = BSON_INITIALIZER;
7728 bson_t *update;
7729 bson_t reply;
7730 bson_error_t error;
7731 bson_t query = BSON_INITIALIZER;
7732 bool success;
7733
7734
7735 /* Find Zlatan Ibrahimovic */
7736 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7737 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7738
7739 /* Return his goal tally */
7740 BSON_APPEND_INT32 (&fields, "goals", 1);
7741
7742 /* Bump his goal tally */
7743 update = BCON_NEW ("$inc", "{", "goals", BCON_INT32 (1), "}");
7744
7745 opts = mongoc_find_and_modify_opts_new ();
7746 mongoc_find_and_modify_opts_set_update (opts, update);
7747 mongoc_find_and_modify_opts_set_fields (opts, &fields);
7748 /* Return the new tally */
7749 mongoc_find_and_modify_opts_set_flags (opts,
7750 MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7751
7752 success = mongoc_collection_find_and_modify_with_opts (
7753 collection, &query, opts, &reply, &error);
7754
7755 if (success) {
7756 char *str;
7757
7758 str = bson_as_canonical_extended_json (&reply, NULL);
7759 printf ("%s\n", str);
7760 bson_free (str);
7761 } else {
7762 fprintf (
7763 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7764 }
7765
7766 bson_destroy (&reply);
7767 bson_destroy (update);
7768 bson_destroy (&fields);
7769 bson_destroy (&query);
7770 mongoc_find_and_modify_opts_destroy (opts);
7771 }
7772
7773
7774 sort.c
7775
7776 void
7777 fam_sort (mongoc_collection_t *collection)
7778 {
7779 mongoc_find_and_modify_opts_t *opts;
7780 bson_t *update;
7781 bson_t sort = BSON_INITIALIZER;
7782 bson_t reply;
7783 bson_error_t error;
7784 bson_t query = BSON_INITIALIZER;
7785 bool success;
7786
7787
7788 /* Find all users with the lastname Ibrahimovic */
7789 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7790
7791 /* Sort by age (descending) */
7792 BSON_APPEND_INT32 (&sort, "age", -1);
7793
7794 /* Bump his goal tally */
7795 update = BCON_NEW ("$set", "{", "oldest", BCON_BOOL (true), "}");
7796
7797 opts = mongoc_find_and_modify_opts_new ();
7798 mongoc_find_and_modify_opts_set_update (opts, update);
7799 mongoc_find_and_modify_opts_set_sort (opts, &sort);
7800
7801 success = mongoc_collection_find_and_modify_with_opts (
7802 collection, &query, opts, &reply, &error);
7803
7804 if (success) {
7805 char *str;
7806
7807 str = bson_as_canonical_extended_json (&reply, NULL);
7808 printf ("%s\n", str);
7809 bson_free (str);
7810 } else {
7811 fprintf (
7812 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7813 }
7814
7815 bson_destroy (&reply);
7816 bson_destroy (update);
7817 bson_destroy (&sort);
7818 bson_destroy (&query);
7819 mongoc_find_and_modify_opts_destroy (opts);
7820 }
7821
7822
7823 opts.c
7824
7825 void
7826 fam_opts (mongoc_collection_t *collection)
7827 {
7828 mongoc_find_and_modify_opts_t *opts;
7829 bson_t reply;
7830 bson_t *update;
7831 bson_error_t error;
7832 bson_t query = BSON_INITIALIZER;
7833 mongoc_write_concern_t *wc;
7834 bson_t extra = BSON_INITIALIZER;
7835 bool success;
7836
7837
7838 /* Find Zlatan Ibrahimovic, the striker */
7839 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7840 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7841 BSON_APPEND_UTF8 (&query, "profession", "Football player");
7842
7843 /* Bump his age */
7844 update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
7845
7846 opts = mongoc_find_and_modify_opts_new ();
7847 mongoc_find_and_modify_opts_set_update (opts, update);
7848
7849 /* Abort if the operation takes too long. */
7850 mongoc_find_and_modify_opts_set_max_time_ms (opts, 100);
7851
7852 /* Set write concern w: 2 */
7853 wc = mongoc_write_concern_new ();
7854 mongoc_write_concern_set_w (wc, 2);
7855 mongoc_write_concern_append (wc, &extra);
7856
7857 /* Some future findAndModify option the driver doesn't support conveniently
7858 */
7859 BSON_APPEND_INT32 (&extra, "futureOption", 42);
7860 mongoc_find_and_modify_opts_append (opts, &extra);
7861
7862 success = mongoc_collection_find_and_modify_with_opts (
7863 collection, &query, opts, &reply, &error);
7864
7865 if (success) {
7866 char *str;
7867
7868 str = bson_as_canonical_extended_json (&reply, NULL);
7869 printf ("%s\n", str);
7870 bson_free (str);
7871 } else {
7872 fprintf (
7873 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7874 }
7875
7876 bson_destroy (&reply);
7877 bson_destroy (&extra);
7878 bson_destroy (update);
7879 bson_destroy (&query);
7880 mongoc_write_concern_destroy (wc);
7881 mongoc_find_and_modify_opts_destroy (opts);
7882 }
7883
7884
7885 fam.c
7886
7887 int
7888 main (void)
7889 {
7890 mongoc_collection_t *collection;
7891 mongoc_database_t *database;
7892 mongoc_client_t *client;
7893 const char *uri_string =
7894 "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example";
7895 mongoc_uri_t *uri;
7896 bson_error_t error;
7897 bson_t *options;
7898
7899 mongoc_init ();
7900
7901 uri = mongoc_uri_new_with_error (uri_string, &error);
7902 if (!uri) {
7903 fprintf (stderr,
7904 "failed to parse URI: %s\n"
7905 "error message: %s\n",
7906 uri_string,
7907 error.message);
7908 return EXIT_FAILURE;
7909 }
7910
7911 client = mongoc_client_new_from_uri (uri);
7912 if (!client) {
7913 return EXIT_FAILURE;
7914 }
7915
7916 mongoc_client_set_error_api (client, 2);
7917 database = mongoc_client_get_database (client, "databaseName");
7918
7919 options = BCON_NEW ("validator",
7920 "{",
7921 "age",
7922 "{",
7923 "$lte",
7924 BCON_INT32 (34),
7925 "}",
7926 "}",
7927 "validationAction",
7928 BCON_UTF8 ("error"),
7929 "validationLevel",
7930 BCON_UTF8 ("moderate"));
7931
7932 collection = mongoc_database_create_collection (
7933 database, "collectionName", options, &error);
7934 if (!collection) {
7935 fprintf (
7936 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7937 return EXIT_FAILURE;
7938 }
7939
7940 fam_flags (collection);
7941 fam_bypass (collection);
7942 fam_update (collection);
7943 fam_fields (collection);
7944 fam_opts (collection);
7945 fam_sort (collection);
7946
7947 mongoc_collection_drop (collection, NULL);
7948 bson_destroy (options);
7949 mongoc_uri_destroy (uri);
7950 mongoc_database_destroy (database);
7951 mongoc_collection_destroy (collection);
7952 mongoc_client_destroy (client);
7953
7954 mongoc_cleanup ();
7955 return EXIT_SUCCESS;
7956 }
7957
7958
7959 Outputs:
7960
7961 {
7962 "lastErrorObject": {
7963 "updatedExisting": false,
7964 "n": 1,
7965 "upserted": {
7966 "$oid": "56562a99d13e6d86239c7b00"
7967 }
7968 },
7969 "value": {
7970 "_id": {
7971 "$oid": "56562a99d13e6d86239c7b00"
7972 },
7973 "age": 34,
7974 "firstname": "Zlatan",
7975 "goals": 342,
7976 "lastname": "Ibrahimovic",
7977 "profession": "Football player",
7978 "position": "striker"
7979 },
7980 "ok": 1
7981 }
7982 {
7983 "lastErrorObject": {
7984 "updatedExisting": true,
7985 "n": 1
7986 },
7987 "value": {
7988 "_id": {
7989 "$oid": "56562a99d13e6d86239c7b00"
7990 },
7991 "age": 34,
7992 "firstname": "Zlatan",
7993 "goals": 342,
7994 "lastname": "Ibrahimovic",
7995 "profession": "Football player",
7996 "position": "striker"
7997 },
7998 "ok": 1
7999 }
8000 {
8001 "lastErrorObject": {
8002 "updatedExisting": true,
8003 "n": 1
8004 },
8005 "value": {
8006 "_id": {
8007 "$oid": "56562a99d13e6d86239c7b00"
8008 },
8009 "age": 35,
8010 "firstname": "Zlatan",
8011 "goals": 342,
8012 "lastname": "Ibrahimovic",
8013 "profession": "Football player",
8014 "position": "striker"
8015 },
8016 "ok": 1
8017 }
8018 {
8019 "lastErrorObject": {
8020 "updatedExisting": true,
8021 "n": 1
8022 },
8023 "value": {
8024 "_id": {
8025 "$oid": "56562a99d13e6d86239c7b00"
8026 },
8027 "goals": 343
8028 },
8029 "ok": 1
8030 }
8031 {
8032 "lastErrorObject": {
8033 "updatedExisting": true,
8034 "n": 1
8035 },
8036 "value": {
8037 "_id": {
8038 "$oid": "56562a99d13e6d86239c7b00"
8039 },
8040 "age": 35,
8041 "firstname": "Zlatan",
8042 "goals": 343,
8043 "lastname": "Ibrahimovic",
8044 "profession": "Football player",
8045 "position": "striker",
8046 "author": true
8047 },
8048 "ok": 1
8049 }
8050
8051 mongoc_gridfs_file_list_t
8052 Synopsis
8053 #include <mongoc/mongoc.h>
8054
8055 typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t;
8056
8057 Description
8058 mongoc_gridfs_file_list_t provides a gridfs file list abstraction. It
8059 provides iteration and basic marshalling on top of a regular mon‐
8060 goc_collection_find_with_opts() style query. In interface, it's styled
8061 after mongoc_cursor_t.
8062
8063 Example
8064 mongoc_gridfs_file_list_t *list;
8065 mongoc_gridfs_file_t *file;
8066
8067 list = mongoc_gridfs_find (gridfs, query);
8068
8069 while ((file = mongoc_gridfs_file_list_next (list))) {
8070 do_something (file);
8071
8072 mongoc_gridfs_file_destroy (file);
8073 }
8074
8075 mongoc_gridfs_file_list_destroy (list);
8076
8077 mongoc_gridfs_file_opt_t
8078 Synopsis
8079 typedef struct {
8080 const char *md5;
8081 const char *filename;
8082 const char *content_type;
8083 const bson_t *aliases;
8084 const bson_t *metadata;
8085 uint32_t chunk_size;
8086 } mongoc_gridfs_file_opt_t;
8087
8088 Description
8089 This structure contains options that can be set on a mon‐
8090 goc_gridfs_file_t. It can be used by various functions when creating a
8091 new gridfs file.
8092
8093 mongoc_gridfs_file_t
8094 Synopsis
8095 typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t;
8096
8097 Description
8098 This structure provides a MongoDB GridFS file abstraction. It provides
8099 several APIs.
8100
8101 · readv, writev, seek, and tell.
8102
8103 · General file metadata such as filename and length.
8104
8105 · GridFS metadata such as md5, filename, content_type, aliases, meta‐
8106 data, chunk_size, and upload_date.
8107
8108 Thread Safety
8109 This structure is NOT thread-safe and should only be used from one
8110 thread at a time.
8111
8112 Related
8113 · mongoc_client_t
8114
8115 · mongoc_gridfs_t
8116
8117 · mongoc_gridfs_file_list_t
8118
8119 · mongoc_gridfs_file_opt_t
8120
8121 mongoc_gridfs_bucket_t
8122 Synopsis
8123 #include <mongoc/mongoc.h>
8124
8125 typedef struct _mongoc_gridfs_bucket_t mongoc_gridfs_bucket_t;
8126
8127 Description
8128 mongoc_gridfs_bucket_t provides a spec-compliant MongoDB GridFS imple‐
8129 mentation, superseding mongoc_gridfs_t. See the GridFS MongoDB documen‐
8130 tation.
8131
8132 Thread Safety
8133 mongoc_gridfs_bucket_t is NOT thread-safe and should only be used in
8134 the same thread as the owning mongoc_client_t.
8135
8136 Lifecycle
8137 It is an error to free a mongoc_gridfs_bucket_t before freeing all
8138 derived instances of mongoc_stream_t. The owning mongoc_client_t must
8139 outlive the mongoc_gridfs_bucket_t.
8140
8141 Example
8142 example-gridfs-bucket.c
8143
8144 #include <stdio.h>
8145 #include <stdlib.h>
8146
8147 #include <mongoc/mongoc.h>
8148
8149 int
8150 main (int argc, char *argv[])
8151 {
8152 const char *uri_string =
8153 "mongodb://localhost:27017/?appname=new-gridfs-example";
8154 mongoc_client_t *client;
8155 mongoc_database_t *db;
8156 mongoc_stream_t *file_stream;
8157 mongoc_gridfs_bucket_t *bucket;
8158 mongoc_cursor_t *cursor;
8159 bson_t filter;
8160 bool res;
8161 bson_value_t file_id;
8162 bson_error_t error;
8163 const bson_t *doc;
8164 char *str;
8165 mongoc_init ();
8166
8167 if (argc != 3) {
8168 fprintf (stderr, "usage: %s SOURCE_FILE_PATH FILE_COPY_PATH\n", argv[0]);
8169 return EXIT_FAILURE;
8170 }
8171
8172 /* 1. Make a bucket. */
8173 client = mongoc_client_new (uri_string);
8174 db = mongoc_client_get_database (client, "test");
8175 bucket = mongoc_gridfs_bucket_new (db, NULL, NULL, &error);
8176 if (!bucket) {
8177 printf ("Error creating gridfs bucket: %s\n", error.message);
8178 return EXIT_FAILURE;
8179 }
8180
8181 /* 2. Insert a file. */
8182 file_stream = mongoc_stream_file_new_for_path (argv[1], O_RDONLY, 0);
8183 res = mongoc_gridfs_bucket_upload_from_stream (
8184 bucket, "my-file", file_stream, NULL, &file_id, &error);
8185 if (!res) {
8186 printf ("Error uploading file: %s\n", error.message);
8187 return EXIT_FAILURE;
8188 }
8189
8190 mongoc_stream_close (file_stream);
8191 mongoc_stream_destroy (file_stream);
8192
8193 /* 3. Download the file in GridFS to a local file. */
8194 file_stream = mongoc_stream_file_new_for_path (argv[2], O_CREAT | O_RDWR, 0);
8195 if (!file_stream) {
8196 perror ("Error opening file stream");
8197 return EXIT_FAILURE;
8198 }
8199
8200 res = mongoc_gridfs_bucket_download_to_stream (
8201 bucket, &file_id, file_stream, &error);
8202 if (!res) {
8203 printf ("Error downloading file to stream: %s\n", error.message);
8204 return EXIT_FAILURE;
8205 }
8206 mongoc_stream_close (file_stream);
8207 mongoc_stream_destroy (file_stream);
8208
8209 /* 4. List what files are available in GridFS. */
8210 bson_init (&filter);
8211 cursor = mongoc_gridfs_bucket_find (bucket, &filter, NULL);
8212
8213 while (mongoc_cursor_next (cursor, &doc)) {
8214 str = bson_as_canonical_extended_json (doc, NULL);
8215 printf ("%s\n", str);
8216 bson_free (str);
8217 }
8218
8219 /* 5. Delete the file that we added. */
8220 res = mongoc_gridfs_bucket_delete_by_id (bucket, &file_id, &error);
8221 if (!res) {
8222 printf ("Error deleting the file: %s\n", error.message);
8223 return EXIT_FAILURE;
8224 }
8225
8226 /* 6. Cleanup. */
8227 mongoc_stream_close (file_stream);
8228 mongoc_stream_destroy (file_stream);
8229 mongoc_cursor_destroy (cursor);
8230 bson_destroy (&filter);
8231 mongoc_gridfs_bucket_destroy (bucket);
8232 mongoc_database_destroy (db);
8233 mongoc_client_destroy (client);
8234 mongoc_cleanup ();
8235
8236 return EXIT_SUCCESS;
8237 }
8238
8239
8240 See also
8241 · The MongoDB GridFS specification.
8242
8243 · The non spec-compliant mongoc_gridfs_t.
8244
8245 mongoc_gridfs_t
8246 WARNING:
8247 This GridFS implementation does not conform to the MongoDB GridFS
8248 specification. For a spec compliant implementation, use mon‐
8249 goc_gridfs_bucket_t.
8250
8251 Synopsis
8252 #include <mongoc/mongoc.h>
8253
8254 typedef struct _mongoc_gridfs_t mongoc_gridfs_t;
8255
8256 Description
8257 mongoc_gridfs_t provides a MongoDB gridfs implementation. The system as
8258 a whole is made up of gridfs objects, which contain gridfs_files and
8259 gridfs_file_lists. Essentially, a basic file system API.
8260
8261 There are extensive caveats about the kind of use cases gridfs is prac‐
8262 tical for. In particular, any writing after initial file creation is
8263 likely to both break any concurrent readers and be quite expensive.
8264 That said, this implementation does allow for arbitrary writes to
8265 existing gridfs object, just use them with caution.
8266
8267 mongoc_gridfs also integrates tightly with the mongoc_stream_t abstrac‐
8268 tion, which provides some convenient wrapping for file creation and
8269 reading/writing. It can be used without, but its worth looking to see
8270 if your problem can fit that model.
8271
8272 WARNING:
8273 mongoc_gridfs_t does not support read preferences. In a replica set,
8274 GridFS queries are always routed to the primary.
8275
8276 Thread Safety
8277 mongoc_gridfs_t is NOT thread-safe and should only be used in the same
8278 thread as the owning mongoc_client_t.
8279
8280 Lifecycle
8281 It is an error to free a mongoc_gridfs_t before freeing all related
8282 instances of mongoc_gridfs_file_t and mongoc_gridfs_file_list_t.
8283
8284 Example
8285 example-gridfs.c
8286
8287 #include <assert.h>
8288 #include <mongoc/mongoc.h>
8289 #include <stdio.h>
8290 #include <stdlib.h>
8291 #include <fcntl.h>
8292
8293 int
8294 main (int argc, char *argv[])
8295 {
8296 mongoc_gridfs_t *gridfs;
8297 mongoc_gridfs_file_t *file;
8298 mongoc_gridfs_file_list_t *list;
8299 mongoc_gridfs_file_opt_t opt = {0};
8300 mongoc_client_t *client;
8301 const char *uri_string = "mongodb://127.0.0.1:27017/?appname=gridfs-example";
8302 mongoc_uri_t *uri;
8303 mongoc_stream_t *stream;
8304 bson_t filter;
8305 bson_t opts;
8306 bson_t child;
8307 bson_error_t error;
8308 ssize_t r;
8309 char buf[4096];
8310 mongoc_iovec_t iov;
8311 const char *filename;
8312 const char *command;
8313 bson_value_t id;
8314
8315 if (argc < 2) {
8316 fprintf (stderr, "usage - %s command ...\n", argv[0]);
8317 return EXIT_FAILURE;
8318 }
8319
8320 mongoc_init ();
8321
8322 iov.iov_base = (void *) buf;
8323 iov.iov_len = sizeof buf;
8324
8325 /* connect to localhost client */
8326 uri = mongoc_uri_new_with_error (uri_string, &error);
8327 if (!uri) {
8328 fprintf (stderr,
8329 "failed to parse URI: %s\n"
8330 "error message: %s\n",
8331 uri_string,
8332 error.message);
8333 return EXIT_FAILURE;
8334 }
8335
8336 client = mongoc_client_new_from_uri (uri);
8337 assert (client);
8338 mongoc_client_set_error_api (client, 2);
8339
8340 /* grab a gridfs handle in test prefixed by fs */
8341 gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error);
8342 assert (gridfs);
8343
8344 command = argv[1];
8345 filename = argv[2];
8346
8347 if (strcmp (command, "read") == 0) {
8348 if (argc != 3) {
8349 fprintf (stderr, "usage - %s read filename\n", argv[0]);
8350 return EXIT_FAILURE;
8351 }
8352 file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error);
8353 assert (file);
8354
8355 stream = mongoc_stream_gridfs_new (file);
8356 assert (stream);
8357
8358 for (;;) {
8359 r = mongoc_stream_readv (stream, &iov, 1, -1, 0);
8360
8361 assert (r >= 0);
8362
8363 if (r == 0) {
8364 break;
8365 }
8366
8367 if (fwrite (iov.iov_base, 1, r, stdout) != r) {
8368 MONGOC_ERROR ("Failed to write to stdout. Exiting.\n");
8369 exit (1);
8370 }
8371 }
8372
8373 mongoc_stream_destroy (stream);
8374 mongoc_gridfs_file_destroy (file);
8375 } else if (strcmp (command, "list") == 0) {
8376 bson_init (&filter);
8377
8378 bson_init (&opts);
8379 bson_append_document_begin (&opts, "sort", -1, &child);
8380 BSON_APPEND_INT32 (&child, "filename", 1);
8381 bson_append_document_end (&opts, &child);
8382
8383 list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts);
8384
8385 bson_destroy (&filter);
8386 bson_destroy (&opts);
8387
8388 while ((file = mongoc_gridfs_file_list_next (list))) {
8389 const char *name = mongoc_gridfs_file_get_filename (file);
8390 printf ("%s\n", name ? name : "?");
8391
8392 mongoc_gridfs_file_destroy (file);
8393 }
8394
8395 mongoc_gridfs_file_list_destroy (list);
8396 } else if (strcmp (command, "write") == 0) {
8397 if (argc != 4) {
8398 fprintf (stderr, "usage - %s write filename input_file\n", argv[0]);
8399 return EXIT_FAILURE;
8400 }
8401
8402 stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0);
8403 assert (stream);
8404
8405 opt.filename = filename;
8406
8407 /* the driver generates a file_id for you */
8408 file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt);
8409 assert (file);
8410
8411 id.value_type = BSON_TYPE_INT32;
8412 id.value.v_int32 = 1;
8413
8414 /* optional: the following method specifies a file_id of any
8415 BSON type */
8416 if (!mongoc_gridfs_file_set_id (file, &id, &error)) {
8417 fprintf (stderr, "%s\n", error.message);
8418 return EXIT_FAILURE;
8419 }
8420
8421 if (!mongoc_gridfs_file_save (file)) {
8422 mongoc_gridfs_file_error (file, &error);
8423 fprintf (stderr, "Could not save: %s\n", error.message);
8424 return EXIT_FAILURE;
8425 }
8426
8427 mongoc_gridfs_file_destroy (file);
8428 } else {
8429 fprintf (stderr, "Unknown command");
8430 return EXIT_FAILURE;
8431 }
8432
8433 mongoc_gridfs_destroy (gridfs);
8434 mongoc_uri_destroy (uri);
8435 mongoc_client_destroy (client);
8436
8437 mongoc_cleanup ();
8438
8439 return EXIT_SUCCESS;
8440 }
8441
8442
8443 See also
8444 · The MongoDB GridFS specification.
8445
8446 · The spec-compliant mongoc_gridfs_bucket_t.
8447
8448 mongoc_host_list_t
8449 Synopsis
8450 typedef struct {
8451 mongoc_host_list_t *next;
8452 char host[BSON_HOST_NAME_MAX + 1];
8453 char host_and_port[BSON_HOST_NAME_MAX + 7];
8454 uint16_t port;
8455 int family;
8456 void *padding[4];
8457 } mongoc_host_list_t;
8458
8459 Description
8460 The host and port of a MongoDB server. Can be part of a linked list:
8461 for example the return value of mongoc_uri_get_hosts when multiple
8462 hosts are provided in the MongoDB URI.
8463
8464 See Also
8465 mongoc_uri_get_hosts and mongoc_cursor_get_host.
8466
8467 mongoc_index_opt_geo_t
8468 Synopsis
8469 #include <mongoc/mongoc.h>
8470
8471 typedef struct {
8472 uint8_t twod_sphere_version;
8473 uint8_t twod_bits_precision;
8474 double twod_location_min;
8475 double twod_location_max;
8476 double haystack_bucket_size;
8477 uint8_t *padding[32];
8478 } mongoc_index_opt_geo_t;
8479
8480 Description
8481 This structure contains the options that may be used for tuning a GEO
8482 index.
8483
8484 See Also
8485 mongoc_index_opt_t
8486
8487 mongoc_index_opt_wt_t
8488
8489 mongoc_index_opt_t
8490 Synopsis
8491 #include <mongoc/mongoc.h>
8492
8493 typedef struct {
8494 bool is_initialized;
8495 bool background;
8496 bool unique;
8497 const char *name;
8498 bool drop_dups;
8499 bool sparse;
8500 int32_t expire_after_seconds;
8501 int32_t v;
8502 const bson_t *weights;
8503 const char *default_language;
8504 const char *language_override;
8505 mongoc_index_opt_geo_t *geo_options;
8506 mongoc_index_opt_storage_t *storage_options;
8507 const bson_t *partial_filter_expression;
8508 const bson_t *collation;
8509 void *padding[4];
8510 } mongoc_index_opt_t;
8511
8512 Deprecated
8513 This structure is deprecated and should not be used in new code. See
8514 create-indexes.
8515
8516 Description
8517 This structure contains the options that may be used for tuning a spe‐
8518 cific index.
8519
8520 See the createIndexes documentations in the MongoDB manual for descrip‐
8521 tions of individual options.
8522
8523 NOTE:
8524 dropDups is deprecated as of MongoDB version 3.0.0. This option is
8525 silently ignored by the server and unique index builds using this
8526 option will fail if a duplicate value is detected.
8527
8528 Example
8529 {
8530 bson_t keys;
8531 bson_error_t error;
8532 mongoc_index_opt_t opt;
8533 mongoc_index_opt_geo_t geo_opt;
8534
8535 mongoc_index_opt_init (&opt);
8536 mongoc_index_opt_geo_init (&geo_opt);
8537
8538 bson_init (&keys);
8539 BSON_APPEND_UTF8 (&keys, "location", "2d");
8540
8541 geo_opt.twod_location_min = -123;
8542 geo_opt.twod_location_max = +123;
8543 geo_opt.twod_bits_precision = 30;
8544 opt.geo_options = &geo_opt;
8545
8546 collection = mongoc_client_get_collection (client, "test", "geo_test");
8547 if (mongoc_collection_create_index (collection, &keys, &opt, &error)) {
8548 /* Successfully created the geo index */
8549 }
8550 bson_destroy (&keys);
8551 mongoc_collection_destroy (&collection);
8552 }
8553
8554 See Also
8555 mongoc_index_opt_geo_t
8556
8557 mongoc_index_opt_wt_t
8558
8559 mongoc_index_opt_wt_t
8560 Synopsis
8561 #include <mongoc/mongoc.h>
8562
8563 typedef struct {
8564 mongoc_index_opt_storage_t base;
8565 const char *config_str;
8566 void *padding[8];
8567 } mongoc_index_opt_wt_t;
8568
8569 Description
8570 This structure contains the options that may be used for tuning a
8571 WiredTiger specific index.
8572
8573 See Also
8574 mongoc_index_opt_t
8575
8576 mongoc_index_opt_geo_t
8577
8578 mongoc_insert_flags_t
8579 Flags for insert operations
8580
8581 Synopsis
8582 typedef enum {
8583 MONGOC_INSERT_NONE = 0,
8584 MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0,
8585 } mongoc_insert_flags_t;
8586
8587 #define MONGOC_INSERT_NO_VALIDATE (1U << 31)
8588
8589 Description
8590 These flags correspond to the MongoDB wire protocol. They may be bit‐
8591 wise or'd together. They may modify how an insert happens on the Mon‐
8592 goDB server.
8593
8594 Flag Values
8595 ┌──────────────────────────┬────────────────────────────┐
8596 │MONGOC_INSERT_NONE │ Specify no insert flags. │
8597 ├──────────────────────────┼────────────────────────────┤
8598 │MONGOC_INSERT_CON‐ │ Continue inserting docu‐ │
8599 │TINUE_ON_ERROR │ ments from the insertion │
8600 │ │ set even if one insert │
8601 │ │ fails. │
8602 ├──────────────────────────┼────────────────────────────┤
8603 │MONGOC_INSERT_NO_VALIDATE │ Do not validate insertion │
8604 │ │ documents before perform‐ │
8605 │ │ ing an insert. Validation │
8606 │ │ can be expensive, so this │
8607 │ │ can save some time if you │
8608 │ │ know your documents are │
8609 │ │ already valid. │
8610 └──────────────────────────┴────────────────────────────┘
8611
8612 mongoc_iovec_t
8613 Synopsis
8614 Synopsis
8615 #include <mongoc/mongoc.h>
8616
8617 #ifdef _WIN32
8618 typedef struct {
8619 u_long iov_len;
8620 char *iov_base;
8621 } mongoc_iovec_t;
8622 #else
8623 typedef struct iovec mongoc_iovec_t;
8624 #endif
8625
8626 The mongoc_iovec_t structure is a portability abstraction for consumers
8627 of the mongoc_stream_t interfaces. It allows for scatter/gather I/O
8628 through the socket subsystem.
8629
8630 WARNING:
8631 When writing portable code, beware of the ordering of iov_len and
8632 iov_base as they are different on various platforms. Therefore, you
8633 should not use C initializers for initialization.
8634
8635 mongoc_matcher_t
8636 Client-side document matching abstraction
8637
8638 Synopsis
8639 typedef struct _mongoc_matcher_t mongoc_matcher_t;
8640
8641 mongoc_matcher_t provides a reduced-interface for client-side matching
8642 of BSON documents.
8643
8644 It can perform the basics such as $in, $nin, $eq, $neq, $gt, $gte, $lt,
8645 and $lte.
8646
8647 WARNING:
8648 mongoc_matcher_t does not currently support the full spectrum of
8649 query operations that the MongoDB server supports.
8650
8651 Deprecated
8652 WARNING:
8653 mongoc_matcher_t is deprecated and will be removed in version 2.0.
8654
8655 Example
8656 Filter a sequence of BSON documents from STDIN based on a query
8657
8658 #include <bson/bson.h>
8659 #include <mongoc/mongoc.h>
8660 #include <stdio.h>
8661
8662 int
8663 main (int argc, char *argv[])
8664 {
8665 mongoc_matcher_t *matcher;
8666 bson_reader_t *reader;
8667 const bson_t *bson;
8668 bson_t *spec;
8669 char *str;
8670 int fd;
8671
8672 mongoc_init ();
8673
8674 #ifdef _WIN32
8675 fd = fileno (stdin);
8676 #else
8677 fd = STDIN_FILENO;
8678 #endif
8679
8680 reader = bson_reader_new_from_fd (fd, false);
8681
8682 spec = BCON_NEW ("hello", "world");
8683 matcher = mongoc_matcher_new (spec, NULL);
8684
8685 while ((bson = bson_reader_read (reader, NULL))) {
8686 if (mongoc_matcher_match (matcher, bson)) {
8687 str = bson_as_canonical_extended_json (bson, NULL);
8688 printf ("%s\n", str);
8689 bson_free (str);
8690 }
8691 }
8692
8693 bson_reader_destroy (reader);
8694 bson_destroy (spec);
8695
8696 mongoc_cleanup ();
8697
8698 return 0;
8699 }
8700
8701 mongoc_query_flags_t
8702 Flags for query operations
8703
8704 Synopsis
8705 typedef enum {
8706 MONGOC_QUERY_NONE = 0,
8707 MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1,
8708 MONGOC_QUERY_SLAVE_OK = 1 << 2,
8709 MONGOC_QUERY_OPLOG_REPLAY = 1 << 3,
8710 MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
8711 MONGOC_QUERY_AWAIT_DATA = 1 << 5,
8712 MONGOC_QUERY_EXHAUST = 1 << 6,
8713 MONGOC_QUERY_PARTIAL = 1 << 7,
8714 } mongoc_query_flags_t;
8715
8716 Description
8717 These flags correspond to the MongoDB wire protocol. They may be bit‐
8718 wise or'd together. They may modify how a query is performed in the
8719 MongoDB server.
8720
8721 Flag Values
8722 ┌───────────────────────────┬────────────────────────────┐
8723 │MONGOC_QUERY_NONE │ Specify no query flags. │
8724 ├───────────────────────────┼────────────────────────────┤
8725 │MONGOC_QUERY_TAILABLE_CUR‐ │ Cursor will not be closed │
8726 │SOR │ when the last data is │
8727 │ │ retrieved. You can resume │
8728 │ │ this cursor later. │
8729 ├───────────────────────────┼────────────────────────────┤
8730 │MONGOC_QUERY_SLAVE_OK │ Allow query of replica set │
8731 │ │ secondaries. │
8732 ├───────────────────────────┼────────────────────────────┤
8733 │MONGOC_QUERY_OPLOG_REPLAY │ Used internally by Mon‐ │
8734 │ │ goDB. │
8735 └───────────────────────────┴────────────────────────────┘
8736
8737
8738
8739
8740
8741 │MONGOC_QUERY_NO_CUR‐ │ The server normally times │
8742 │SOR_TIMEOUT │ out an idle cursor after │
8743 │ │ an inactivity period (10 │
8744 │ │ minutes). This prevents │
8745 │ │ that. │
8746 ├───────────────────────────┼────────────────────────────┤
8747 │MONGOC_QUERY_AWAIT_DATA │ Use with MON‐ │
8748 │ │ GOC_QUERY_TAILABLE_CURSOR. │
8749 │ │ Block rather than return‐ │
8750 │ │ ing no data. After a │
8751 │ │ period, time out. │
8752 ├───────────────────────────┼────────────────────────────┤
8753 │MONGOC_QUERY_EXHAUST │ Stream the data down full │
8754 │ │ blast in multiple "reply" │
8755 │ │ packets. Faster when you │
8756 │ │ are pulling down a lot of │
8757 │ │ data and you know you want │
8758 │ │ to retrieve it all. Only │
8759 │ │ applies to cursors created │
8760 │ │ from a find operation │
8761 │ │ (i.e. mongoc_collec‐ │
8762 │ │ tion_find()). │
8763 ├───────────────────────────┼────────────────────────────┤
8764 │MONGOC_QUERY_PARTIAL │ Get partial results from │
8765 │ │ mongos if some shards are │
8766 │ │ down (instead of throwing │
8767 │ │ an error). │
8768 └───────────────────────────┴────────────────────────────┘
8769
8770 mongoc_rand
8771 MongoDB Random Number Generator
8772
8773 Synopsis
8774 void
8775 mongoc_rand_add (const void *buf, int num, double entropy);
8776
8777 void
8778 mongoc_rand_seed (const void *buf, int num);
8779
8780 int
8781 mongoc_rand_status (void);
8782
8783 Description
8784 The mongoc_rand family of functions provide access to the low level
8785 randomness primitives used by the MongoDB C Driver. In particular,
8786 they control the creation of cryptographically strong pseudo-random
8787 bytes required by some security mechanisms.
8788
8789 While we can usually pull enough entropy from the environment, you may
8790 be required to seed the PRNG manually depending on your OS, hardware
8791 and other entropy consumers running on the same system.
8792
8793 Entropy
8794 mongoc_rand_add and mongoc_rand_seed allow the user to directly provide
8795 entropy. They differ insofar as mongoc_rand_seed requires that each
8796 bit provided is fully random. mongoc_rand_add allows the user to spec‐
8797 ify the degree of randomness in the provided bytes as well.
8798
8799 Status
8800 The mongoc_rand_status function allows the user to check the status of
8801 the mongoc PRNG. This can be used to guarantee sufficient entropy at
8802 program startup, rather than waiting for runtime errors to occur.
8803
8804 mongoc_read_concern_t
8805 Read Concern abstraction
8806
8807 Synopsis
8808 New in MongoDB 3.2.
8809
8810 The mongoc_read_concern_t allows clients to choose a level of isolation
8811 for their reads. The default, MONGOC_READ_CONCERN_LEVEL_LOCAL, is right
8812 for the great majority of applications.
8813
8814 You can specify a read concern on connection objects, database objects,
8815 or collection objects.
8816
8817 See readConcern on the MongoDB website for more information.
8818
8819 Read Concern is only sent to MongoDB when it has explicitly been set by
8820 mongoc_read_concern_set_level to anything other than NULL.
8821
8822 Read Concern Levels
8823 ┌────────────────────┬─────────────────────┬─────────────────────┐
8824 │Macro │ Description │ First MongoDB ver‐ │
8825 │ │ │ sion │
8826 ├────────────────────┼─────────────────────┼─────────────────────┤
8827 │MONGOC_READ_CON‐ │ Level "local", the │ 3.2 │
8828 │CERN_LEVEL_LOCAL │ default. │ │
8829 ├────────────────────┼─────────────────────┼─────────────────────┤
8830 │MONGOC_READ_CON‐ │ Level "majority". │ 3.2 │
8831 │CERN_LEVEL_MAJORITY │ │ │
8832 ├────────────────────┼─────────────────────┼─────────────────────┤
8833 │MONGOC_READ_CON‐ │ Level "lineariz‐ │ 3.4 │
8834 │CERN_LEVEL_LIN‐ │ able". │ │
8835 │EARIZABLE │ │ │
8836 ├────────────────────┼─────────────────────┼─────────────────────┤
8837 │MONGOC_READ_CON‐ │ Level "available". │ 3.6 │
8838 │CERN_LEVEL_AVAIL‐ │ │ │
8839 │ABLE │ │ │
8840 ├────────────────────┼─────────────────────┼─────────────────────┤
8841 │MONGOC_READ_CON‐ │ Level "snapshot". │ 4.0 │
8842 │CERN_LEVEL_SNAPSHOT │ │ │
8843 └────────────────────┴─────────────────────┴─────────────────────┘
8844
8845 For the sake of compatibility with future versions of MongoDB, mon‐
8846 goc_read_concern_set_level allows any string, not just this list of
8847 known read concern levels.
8848
8849 See Read Concern Levels in the MongoDB manual for more information
8850 about the individual read concern levels.
8851
8852 mongoc_read_mode_t
8853 Read Preference Modes
8854
8855 Synopsis
8856 typedef enum {
8857 MONGOC_READ_PRIMARY = (1 << 0),
8858 MONGOC_READ_SECONDARY = (1 << 1),
8859 MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
8860 MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
8861 MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
8862 } mongoc_read_mode_t;
8863
8864 Description
8865 This enum describes how reads should be dispatched. The default is MON‐
8866 GOC_READ_PRIMARY.
8867
8868 Please see the MongoDB website for a description of Read Preferences.
8869
8870 mongoc_read_prefs_t
8871 A read preference abstraction
8872
8873 Synopsis
8874 mongoc_read_prefs_t provides an abstraction on top of the MongoDB con‐
8875 nection read preferences. It allows for hinting to the driver which
8876 nodes in a replica set should be accessed first and how.
8877
8878 You can specify a read preference mode on connection objects, database
8879 objects, collection objects, or per-operation. Generally, it makes the
8880 most sense to stick with the global default mode, MONGOC_READ_PRIMARY.
8881 All of the other modes come with caveats that won't be covered in great
8882 detail here.
8883
8884 Read Modes
8885 ┌───────────────────────────┬────────────────────────────┐
8886 │MONGOC_READ_PRIMARY │ Default mode. All opera‐ │
8887 │ │ tions read from the cur‐ │
8888 │ │ rent replica set primary. │
8889 ├───────────────────────────┼────────────────────────────┤
8890 │MONGOC_READ_SECONDARY │ All operations read from │
8891 │ │ among the nearest sec‐ │
8892 │ │ ondary members of the │
8893 │ │ replica set. │
8894 └───────────────────────────┴────────────────────────────┘
8895
8896
8897 │MONGOC_READ_PRIMARY_PRE‐ │ In most situations, opera‐ │
8898 │FERRED │ tions read from the pri‐ │
8899 │ │ mary but if it is unavail‐ │
8900 │ │ able, operations read from │
8901 │ │ secondary members. │
8902 ├───────────────────────────┼────────────────────────────┤
8903 │MONGOC_READ_SECONDARY_PRE‐ │ In most situations, opera‐ │
8904 │FERRED │ tions read from among the │
8905 │ │ nearest secondary members, │
8906 │ │ but if no secondaries are │
8907 │ │ available, operations read │
8908 │ │ from the primary. │
8909 ├───────────────────────────┼────────────────────────────┤
8910 │MONGOC_READ_NEAREST │ Operations read from among │
8911 │ │ the nearest members of the │
8912 │ │ replica set, irrespective │
8913 │ │ of the member's type. │
8914 └───────────────────────────┴────────────────────────────┘
8915
8916 Tag Sets
8917 Tag sets allow you to specify custom read preferences and write con‐
8918 cerns so that your application can target operations to specific mem‐
8919 bers.
8920
8921 Custom read preferences and write concerns evaluate tags sets in dif‐
8922 ferent ways: read preferences consider the value of a tag when select‐
8923 ing a member to read from, while write concerns ignore the value of a
8924 tag when selecting a member, except to consider whether or not the
8925 value is unique.
8926
8927 You can specify tag sets with the following read preference modes:
8928
8929 · primaryPreferred
8930
8931 · secondary
8932
8933 · secondaryPreferred
8934
8935 · nearest
8936
8937 Tags are not compatible with MONGOC_READ_PRIMARY and, in general, only
8938 apply when selecting a secondary member of a set for a read operation.
8939 However, the nearest read mode, when combined with a tag set, will
8940 select the nearest member that matches the specified tag set, which may
8941 be a primary or secondary.
8942
8943 Tag sets are represented as a comma-separated list of colon-separated
8944 key-value pairs when provided as a connection string, e.g.
8945 dc:ny,rack:1.
8946
8947 To specify a list of tag sets, using multiple readPreferenceTags, e.g.
8948
8949 readPreferenceTags=dc:ny,rack:1;readPreferenceTags=dc:ny;readPreferenceTags=
8950
8951 Note the empty value for the last one, which means "match any secondary
8952 as a last resort".
8953
8954 Order matters when using multiple readPreferenceTags.
8955
8956 Tag Sets can also be configured using mongoc_read_prefs_set_tags.
8957
8958 All interfaces use the same member selection logic to choose the member
8959 to which to direct read operations, basing the choice on read prefer‐
8960 ence mode and tag sets.
8961
8962 Max Staleness
8963 When connected to replica set running MongoDB 3.4 or later, the driver
8964 estimates the staleness of each secondary based on lastWriteDate values
8965 provided in server isMaster responses.
8966
8967 Max Staleness is the maximum replication lag in seconds (wall clock
8968 time) that a secondary can suffer and still be eligible for reads. The
8969 default is MONGOC_NO_MAX_STALENESS, which disables staleness checks.
8970 Otherwise, it must be a positive integer at least MONGOC_SMALL‐
8971 EST_MAX_STALENESS_SECONDS (90 seconds).
8972
8973 Max Staleness is also supported by sharded clusters of replica sets if
8974 all servers run MongoDB 3.4 or later.
8975
8976 Hedged Reads
8977 When connecting to a sharded cluster running MongoDB 4.4 or later,
8978 reads can be sent in parallel to the two "best" hosts. Once one result
8979 returns, any other outstanding operations that were part of the hedged
8980 read are cancelled.
8981
8982 When the read preference mode is MONGOC_READ_NEAREST and the sharded
8983 cluster is running MongoDB 4.4 or later, hedged reads are enabled by
8984 default. Additionally, hedged reads may be explicitly enabled or dis‐
8985 abled by calling mongoc_read_prefs_set_hedge with a BSON document, e.g.
8986
8987 {
8988 enabled: true
8989 }
8990
8991 Appropriate values for the enabled key are true or false.
8992
8993 mongoc_remove_flags_t
8994 Flags for deletion operations
8995
8996 Synopsis
8997 typedef enum {
8998 MONGOC_REMOVE_NONE = 0,
8999 MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0,
9000 } mongoc_remove_flags_t;
9001
9002 Description
9003 These flags correspond to the MongoDB wire protocol. They may be bit‐
9004 wise or'd together. They may change the number of documents that are
9005 removed during a remove command.
9006
9007 Flag Values
9008 ┌───────────────────┬────────────────────────────┐
9009 │MONGOC_REMOVE_NONE │ Specify no removal flags. │
9010 │ │ All matching documents │
9011 │ │ will be removed. │
9012 ├───────────────────┼────────────────────────────┤
9013 │MONGOC_REMOVE_SIN‐ │ Only remove the first │
9014 │GLE_REMOVE │ matching document from the │
9015 │ │ selector. │
9016 └───────────────────┴────────────────────────────┘
9017
9018 mongoc_reply_flags_t
9019 Flags from server replies
9020
9021 Synopsis
9022 typedef enum {
9023 MONGOC_REPLY_NONE = 0,
9024 MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0,
9025 MONGOC_REPLY_QUERY_FAILURE = 1 << 1,
9026 MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2,
9027 MONGOC_REPLY_AWAIT_CAPABLE = 1 << 3,
9028 } mongoc_reply_flags_t;
9029
9030 Description
9031 These flags correspond to the wire protocol. They may be bitwise or'd
9032 together.
9033
9034 Flag Values
9035 ┌───────────────────────────┬────────────────────────────┐
9036 │MONGOC_REPLY_NONE │ No flags set. │
9037 ├───────────────────────────┼────────────────────────────┤
9038 │MONGOC_REPLY_CUR‐ │ No matching cursor was │
9039 │SOR_NOT_FOUND │ found on the server. │
9040 ├───────────────────────────┼────────────────────────────┤
9041 │MONGOC_REPLY_QUERY_FAILURE │ The query failed or was │
9042 │ │ invalid. Error document │
9043 │ │ has been provided. │
9044 ├───────────────────────────┼────────────────────────────┤
9045 │MONGOC_REPLY_SHARD_CON‐ │ Shard config is stale. │
9046 │FIG_STALE │ │
9047 ├───────────────────────────┼────────────────────────────┤
9048 │MONGOC_REPLY_AWAIT_CAPABLE │ If the returned cursor is │
9049 │ │ capable of MON‐ │
9050 │ │ GOC_QUERY_AWAIT_DATA. │
9051 └───────────────────────────┴────────────────────────────┘
9052
9053 mongoc_server_description_t
9054 Server description
9055
9056 Synopsis
9057 #include <mongoc/mongoc.h>
9058 typedef struct _mongoc_server_description_t mongoc_server_description_t
9059
9060 mongoc_server_description_t holds information about a mongod or mongos
9061 the driver is connected to.
9062
9063 See also mongoc_client_get_server_descriptions().
9064
9065 Lifecycle
9066 Clean up with mongoc_server_description_destroy().
9067
9068 mongoc_session_opt_t
9069 #include <mongoc/mongoc.h>
9070
9071 typedef struct _mongoc_session_opt_t mongoc_session_opt_t;
9072
9073 Synopsis
9074 Start a session with mongoc_client_start_session, use the session for a
9075 sequence of operations and multi-document transactions, then free it
9076 with mongoc_client_session_destroy(). Any mongoc_cursor_t or mon‐
9077 goc_change_stream_t using a session must be destroyed before the ses‐
9078 sion, and a session must be destroyed before the mongoc_client_t it
9079 came from.
9080
9081 By default, sessions are causally consistent. To disable causal consis‐
9082 tency, before starting a session create a mongoc_session_opt_t with
9083 mongoc_session_opts_new() and call mongoc_session_opts_set_causal_con‐
9084 sistency(), then free the struct with mongoc_session_opts_destroy.
9085
9086 Unacknowledged writes are prohibited with sessions.
9087
9088 A mongoc_client_session_t must be used by only one thread at a time.
9089 Due to session pooling, mongoc_client_start_session may return a ses‐
9090 sion that has been idle for some time and is about to be closed after
9091 its idle timeout. Use the session within one minute of acquiring it to
9092 refresh the session and avoid a timeout.
9093
9094 See the example code for mongoc_session_opts_set_causal_consistency.
9095
9096 mongoc_socket_t
9097 Portable socket abstraction
9098
9099 Synopsis
9100 #include <mongoc/mongoc.h>
9101
9102 typedef struct _mongoc_socket_t mongoc_socket_t
9103
9104 Synopsis
9105 This structure provides a socket abstraction that is friendlier for
9106 portability than BSD sockets directly. Inconsistencies between Linux,
9107 various BSDs, Solaris, and Windows are handled here.
9108
9109 mongoc_ssl_opt_t
9110 Synopsis
9111 typedef struct {
9112 const char *pem_file;
9113 const char *pem_pwd;
9114 const char *ca_file;
9115 const char *ca_dir;
9116 const char *crl_file;
9117 bool weak_cert_validation;
9118 bool allow_invalid_hostname;
9119 void *internal;
9120 void *padding[6];
9121 } mongoc_ssl_opt_t;
9122
9123 Description
9124 This structure is used to set the TLS options for a mongoc_client_t or
9125 mongoc_client_pool_t.
9126
9127 Beginning in version 1.2.0, once a pool or client has any TLS options
9128 set, all connections use TLS, even if ssl=true is omitted from the Mon‐
9129 goDB URI. Before, TLS options were ignored unless tls=true was included
9130 in the URI.
9131
9132 As of 1.4.0, the mongoc_client_pool_set_ssl_opts and mon‐
9133 goc_client_set_ssl_opts will not only shallow copy the struct, but will
9134 also copy the const char*. It is therefore no longer needed to make
9135 sure the values remain valid after setting them.
9136
9137 See Also
9138 · configuring_tls
9139
9140 · mongoc_client_set_ssl_opts
9141
9142 · mongoc_client_pool_set_ssl_opts
9143
9144 mongoc_stream_buffered_t
9145 Synopsis
9146 typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t;
9147
9148 Description
9149 mongoc_stream_buffered_t should be considered a subclass of mon‐
9150 goc_stream_t. It performs buffering on an underlying stream.
9151
9152 See Also
9153 mongoc_stream_buffered_new()
9154
9155 mongoc_stream_destroy()
9156
9157 mongoc_stream_file_t
9158 Synopsis
9159 typedef struct _mongoc_stream_file_t mongoc_stream_file_t
9160
9161 mongoc_stream_file_t is a mongoc_stream_t subclass for working with
9162 standard UNIX style file-descriptors.
9163
9164 mongoc_stream_socket_t
9165 Synopsis
9166 typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t
9167
9168 mongoc_stream_socket_t should be considered a subclass of mon‐
9169 goc_stream_t that works upon socket streams.
9170
9171 mongoc_stream_t
9172 Synopsis
9173 typedef struct _mongoc_stream_t mongoc_stream_t
9174
9175 mongoc_stream_t provides a generic streaming IO abstraction based on a
9176 struct of pointers interface. The idea is to allow wrappers, perhaps
9177 other language drivers, to easily shim their IO system on top of mon‐
9178 goc_stream_t.
9179
9180 The API for the stream abstraction is currently private and non-exten‐
9181 sible.
9182
9183 Stream Types
9184 There are a number of built in stream types that come with mongoc. The
9185 default configuration is a buffered unix stream. If TLS is in use, that
9186 in turn is wrapped in a tls stream.
9187
9188 See Also
9189 mongoc_stream_buffered_t
9190
9191 mongoc_stream_file_t
9192
9193 mongoc_stream_socket_t
9194
9195 mongoc_stream_tls_t
9196
9197 mongoc_stream_tls_t
9198 Synopsis
9199 typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t
9200
9201 mongoc_stream_tls_t is a mongoc_stream_t subclass for working with TLS
9202 streams.
9203
9204 mongoc_topology_description_t
9205 Status of MongoDB Servers
9206
9207 Synopsis
9208 typedef struct _mongoc_topology_description_t mongoc_topology_description_t;
9209
9210 mongoc_topology_description_t is an opaque type representing the
9211 driver's knowledge of the MongoDB server or servers it is connected to.
9212 Its API conforms to the SDAM Monitoring Specification.
9213
9214 Applications receive a temporary reference to a mongoc_topol‐
9215 ogy_description_t as a parameter to an SDAM Monitoring callback. See
9216 Introduction to Application Performance Monitoring.
9217
9218 mongoc_transaction_opt_t
9219 #include <mongoc/mongoc.h>
9220
9221 typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;
9222
9223 Synopsis
9224 Options for starting a multi-document transaction.
9225
9226 When a session is first created with mongoc_client_start_session, it
9227 inherits from the client the read concern, write concern, and read
9228 preference with which to start transactions. Each of these fields can
9229 be overridden independently. Create a mongoc_transaction_opt_t with
9230 mongoc_transaction_opts_new, and pass a non-NULL option to any of the
9231 mongoc_transaction_opt_t setter functions:
9232
9233 · mongoc_transaction_opts_set_read_concern
9234
9235 · mongoc_transaction_opts_set_write_concern
9236
9237 · mongoc_transaction_opts_set_read_prefs
9238
9239 Pass the resulting transaction options to mongoc_client_ses‐
9240 sion_start_transaction. Each field set in the transaction options over‐
9241 rides the inherited client configuration.
9242
9243 Example
9244 example-transaction.c
9245
9246 /* gcc example-transaction.c -o example-transaction \
9247 * $(pkg-config --cflags --libs libmongoc-1.0) */
9248
9249 /* ./example-transaction [CONNECTION_STRING] */
9250
9251 #include <stdio.h>
9252 #include <mongoc/mongoc.h>
9253
9254
9255 int
9256 main (int argc, char *argv[])
9257 {
9258 int exit_code = EXIT_FAILURE;
9259
9260 mongoc_client_t *client = NULL;
9261 mongoc_database_t *database = NULL;
9262 mongoc_collection_t *collection = NULL;
9263 mongoc_client_session_t *session = NULL;
9264 mongoc_session_opt_t *session_opts = NULL;
9265 mongoc_transaction_opt_t *default_txn_opts = NULL;
9266 mongoc_transaction_opt_t *txn_opts = NULL;
9267 mongoc_read_concern_t *read_concern = NULL;
9268 mongoc_write_concern_t *write_concern = NULL;
9269 const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
9270 mongoc_uri_t *uri;
9271 bson_error_t error;
9272 bson_t *doc = NULL;
9273 bson_t *insert_opts = NULL;
9274 int32_t i;
9275 int64_t start;
9276 bson_t reply = BSON_INITIALIZER;
9277 char *reply_json;
9278 bool r;
9279
9280 mongoc_init ();
9281
9282 if (argc > 1) {
9283 uri_string = argv[1];
9284 }
9285
9286 uri = mongoc_uri_new_with_error (uri_string, &error);
9287 if (!uri) {
9288 MONGOC_ERROR ("failed to parse URI: %s\n"
9289 "error message: %s\n",
9290 uri_string,
9291 error.message);
9292 goto done;
9293 }
9294
9295 client = mongoc_client_new_from_uri (uri);
9296 if (!client) {
9297 goto done;
9298 }
9299
9300 mongoc_client_set_error_api (client, 2);
9301 database = mongoc_client_get_database (client, "example-transaction");
9302
9303 /* inserting into a nonexistent collection normally creates it, but a
9304 * collection can't be created in a transaction; create it now */
9305 collection =
9306 mongoc_database_create_collection (database, "collection", NULL, &error);
9307
9308 if (!collection) {
9309 /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
9310 if (error.code == 48) {
9311 collection = mongoc_database_get_collection (database, "collection");
9312 } else {
9313 MONGOC_ERROR ("Failed to create collection: %s", error.message);
9314 goto done;
9315 }
9316 }
9317
9318 /* a transaction's read preferences, read concern, and write concern can be
9319 * set on the client, on the default transaction options, or when starting
9320 * the transaction. for the sake of this example, set read concern on the
9321 * default transaction options. */
9322 default_txn_opts = mongoc_transaction_opts_new ();
9323 read_concern = mongoc_read_concern_new ();
9324 mongoc_read_concern_set_level (read_concern, "snapshot");
9325 mongoc_transaction_opts_set_read_concern (default_txn_opts, read_concern);
9326 session_opts = mongoc_session_opts_new ();
9327 mongoc_session_opts_set_default_transaction_opts (session_opts,
9328 default_txn_opts);
9329
9330 session = mongoc_client_start_session (client, session_opts, &error);
9331 if (!session) {
9332 MONGOC_ERROR ("Failed to start session: %s", error.message);
9333 goto done;
9334 }
9335
9336 /* in this example, set write concern when starting the transaction */
9337 txn_opts = mongoc_transaction_opts_new ();
9338 write_concern = mongoc_write_concern_new ();
9339 mongoc_write_concern_set_wmajority (write_concern, 1000 /* wtimeout */);
9340 mongoc_transaction_opts_set_write_concern (txn_opts, write_concern);
9341
9342 insert_opts = bson_new ();
9343 if (!mongoc_client_session_append (session, insert_opts, &error)) {
9344 MONGOC_ERROR ("Could not add session to opts: %s", error.message);
9345 goto done;
9346 }
9347
9348 retry_transaction:
9349 r = mongoc_client_session_start_transaction (session, txn_opts, &error);
9350 if (!r) {
9351 MONGOC_ERROR ("Failed to start transaction: %s", error.message);
9352 goto done;
9353 }
9354
9355 /* insert two documents - on error, retry the whole transaction */
9356 for (i = 0; i < 2; i++) {
9357 doc = BCON_NEW ("_id", BCON_INT32 (i));
9358 bson_destroy (&reply);
9359 r = mongoc_collection_insert_one (
9360 collection, doc, insert_opts, &reply, &error);
9361
9362 bson_destroy (doc);
9363
9364 if (!r) {
9365 MONGOC_ERROR ("Insert failed: %s", error.message);
9366 mongoc_client_session_abort_transaction (session, NULL);
9367
9368 /* a network error, primary failover, or other temporary error in a
9369 * transaction includes {"errorLabels": ["TransientTransactionError"]},
9370 * meaning that trying the entire transaction again may succeed
9371 */
9372 if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
9373 goto retry_transaction;
9374 }
9375
9376 goto done;
9377 }
9378
9379 reply_json = bson_as_json (&reply, NULL);
9380 printf ("%s\n", reply_json);
9381 bson_free (reply_json);
9382 }
9383
9384 /* in case of transient errors, retry for 5 seconds to commit transaction */
9385 start = bson_get_monotonic_time ();
9386 while (bson_get_monotonic_time () - start < 5 * 1000 * 1000) {
9387 bson_destroy (&reply);
9388 r = mongoc_client_session_commit_transaction (session, &reply, &error);
9389 if (r) {
9390 /* success */
9391 break;
9392 } else {
9393 MONGOC_ERROR ("Warning: commit failed: %s", error.message);
9394 if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
9395 goto retry_transaction;
9396 } else if (mongoc_error_has_label (&reply,
9397 "UnknownTransactionCommitResult")) {
9398 /* try again to commit */
9399 continue;
9400 }
9401
9402 /* unrecoverable error trying to commit */
9403 break;
9404 }
9405 }
9406
9407 exit_code = EXIT_SUCCESS;
9408
9409 done:
9410 bson_destroy (&reply);
9411 bson_destroy (insert_opts);
9412 mongoc_write_concern_destroy (write_concern);
9413 mongoc_read_concern_destroy (read_concern);
9414 mongoc_transaction_opts_destroy (txn_opts);
9415 mongoc_transaction_opts_destroy (default_txn_opts);
9416 mongoc_client_session_destroy (session);
9417 mongoc_collection_destroy (collection);
9418 mongoc_database_destroy (database);
9419 mongoc_uri_destroy (uri);
9420 mongoc_client_destroy (client);
9421
9422 mongoc_cleanup ();
9423
9424 return exit_code;
9425 }
9426
9427
9428 mongoc_transaction_state_t
9429 Constants for transaction states
9430
9431 Synopsis
9432 typedef enum {
9433 MONGOC_TRANSACTION_NONE = 0,
9434 MONGOC_TRANSACTION_STARTING = 1,
9435 MONGOC_TRANSACTION_IN_PROGRESS = 2,
9436 MONGOC_TRANSACTION_COMMITTED = 3,
9437 MONGOC_TRANSACTION_ABORTED = 4,
9438 } mongoc_transaction_state_t;
9439
9440 Description
9441 These constants describe the current transaction state of a session.
9442
9443 Flag Values
9444 ──────────────────────────────────────────────────────────
9445 MONGOC_TRANSACTION_NONE There is no transaction in
9446 progress.
9447 ──────────────────────────────────────────────────────────
9448 MONGOC_TRANSACTION_START‐ A transaction has been
9449 ING started, but no operation
9450 has been sent to the
9451 server.
9452 ──────────────────────────────────────────────────────────
9453 MONGOC_TRANSAC‐ A transaction is in
9454 TION_IN_PROGRESS progress.
9455 ──────────────────────────────────────────────────────────
9456 MONGOC_TRANSACTION_COMMIT‐ The transaction was com‐
9457 TED mitted.
9458 ──────────────────────────────────────────────────────────
9459 MONGOC_TRANSACTION_ABORTED The transaction was
9460 aborted.
9461 ┌───────────────────────────┬────────────────────────────┐
9462 │ │ │
9463 mongoc_upda│te_flags_t │ │
9464 Flags f│or update operations │ │
9465 │ │ │
9466 Synopsis │ │ │
9467 type│def enum { │ │
9468 M│ONGOC_UPDATE_NONE = 0, │ │
9469 M│ONGOC_UPDATE_UPSERT = 1 << 0│, │
9470 M│ONGOC_UPDATE_MULTI_UPDATE = │1 << 1, │
9471 } mo│ngoc_update_flags_t; │ │
9472 │ │ │
9473 #def│ine MONGOC_UPDATE_NO_VALIDAT│E (1U << 31) │
9474 │ │ │
9475 Description│ │ │
9476 These f│lags correspond to the Mongo│DB wire protocol. They may b│e bit‐
9477 wise o│r'd together. The allow for│modifying the way an update │is per‐
9478 formed │in the MongoDB server. │ │
9479 │ │ │
9480 Flag Values│ │ │
9481 ├───────────────────────────┼────────────────────────────┤
9482 │MONGOC_UPDATE_NONE │ No update flags set. │
9483 ├───────────────────────────┼────────────────────────────┤
9484 │MONGOC_UPDATE_UPSERT │ If an upsert should be │
9485 │ │ performed. │
9486 ├───────────────────────────┼────────────────────────────┤
9487 │MONGOC_UPDATE_MULTI_UPDATE │ If more than a single │
9488 │ │ matching document should │
9489 │ │ be updated. By default │
9490 │ │ only the first document is │
9491 │ │ updated. │
9492 ├───────────────────────────┼────────────────────────────┤
9493 │MONGOC_UPDATE_NO_VALIDATE │ Do not perform client side │
9494 │ │ BSON validations when per‐ │
9495 │ │ forming an update. This is │
9496 │ │ useful if you already know │
9497 │ │ your BSON documents are │
9498 │ │ valid. │
9499 ├───────────────────────────┼────────────────────────────┤
9500 │ │ │
9501 mongoc_uri_│t │ │
9502 Synopsis │ │ │
9503 type│def struct _mongoc_uri_t mon│goc_uri_t; │
9504 │ │ │
9505 Description│ │ │
9506 mongoc_│uri_t provides an abstractio│n on top of the MongoDB con│nection
9507 URI fo│rmat. It provides standar│dized parsing as well as conv│enience
9508 methods│for extracting useful infor│mation such as replica ho│sts or
9509 authori│zation information. │ │
9510 │ │ │
9511 See Co│nnection String URI Refer│ence on the MongoDB website f│or more
9512 informa│tion. │ │
9513 │ │ │
9514 Format │ │ │
9515 mong│odb[+srv]:// │ <1> │
9516 [│username:password@] │ <2> │
9517 h│ost1 │ <3> │
9518 [│:port1] │ <4> │
9519 [│,host2[:port2],...[,hostN[:p│ortN]]] <5> │
9520 [│/[database] │ <6> │
9521 [│?options]] │ <7> │
9522 │ │ │
9523 1. "mon│godb" is the specifier of │the MongoDB protocol. Use│ "mon‐
9524 godb+srv" with a single service name in place of "host1" to specify
9525 the initial list of servers with an SRV record.
9526
9527 2. An optional username and password.
9528
9529 3. The only required part of the uri. This specifies either a host‐
9530 name, IPv4 address, IPv6 address enclosed in "[" and "]", or UNIX
9531 domain socket.
9532
9533 4. An optional port number. Defaults to :27017.
9534
9535 5. Extra optional hosts and ports. You would specify multiple hosts,
9536 for example, for connections to replica sets.
9537
9538 6. The name of the database to authenticate if the connection string
9539 includes authentication credentials. If /database is not specified
9540 and the connection string includes credentials, defaults to the
9541 'admin' database.
9542
9543 7. Connection specific options.
9544
9545 NOTE:
9546 Option names are case-insensitive. Do not repeat the same option
9547 (e.g. "mongodb://localhost/db?opt=value1&OPT=value2") since this may
9548 have unexpected results.
9549
9550 The MongoDB C Driver exposes constants for each supported connection
9551 option. These constants make it easier to discover connection options,
9552 but their string values can be used as well.
9553
9554 For example, the following calls are equal.
9555
9556 uri = mongoc_uri_new ("mongodb://localhost/?" MONGOC_URI_APPNAME "=applicationName");
9557 uri = mongoc_uri_new ("mongodb://localhost/?appname=applicationName");
9558 uri = mongoc_uri_new ("mongodb://localhost/?appName=applicationName");
9559
9560 Replica Set Example
9561 To describe a connection to a replica set named 'test' with the follow‐
9562 ing mongod hosts:
9563
9564 · db1.example.com on port 27017
9565
9566 · db2.example.com on port 2500
9567
9568 You would use a connection string that resembles the following.
9569
9570 mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test
9571
9572 SRV Example
9573 If you have configured an SRV record with a name like "_mon‐
9574 godb._tcp.server.example.com" whose records are a list of one or more
9575 MongoDB server hostnames, use a connection string like this:
9576
9577 uri = mongoc_uri_new ("mongodb+srv://server.example.com/?replicaSet=rs&appName=applicationName");
9578
9579 The driver prefixes the service name with "_mongodb._tcp.", then per‐
9580 forms a DNS SRV query to resolve the service name to one or more host‐
9581 names. If this query succeeds, the driver performs a DNS TXT query on
9582 the service name (without the "_mongodb._tcp" prefix) for additional
9583 URI options configured as TXT records.
9584
9585 On Unix, the MongoDB C Driver relies on libresolv to look up SRV and
9586 TXT records. If libresolv is unavailable, then using a "mongodb+srv"
9587 URI will cause an error. If your libresolv lacks res_nsearch then the
9588 driver will fall back to res_search, which is not thread-safe.
9589
9590 IPv4 and IPv6
9591 If connecting to a hostname that has both IPv4 and IPv6 DNS records,
9592 the behavior follows RFC-6555. A connection to the IPv6 address is
9593 attempted first. If IPv6 fails, then a connection is attempted to the
9594 IPv4 address. If the connection attempt to IPv6 does not complete
9595 within 250ms, then IPv4 is tried in parallel. Whichever succeeds con‐
9596 nection first cancels the other. The successful DNS result is cached
9597 for 10 minutes.
9598
9599 As a consequence, attempts to connect to a mongod only listening on
9600 IPv4 may be delayed if there are both A (IPv4) and AAAA (IPv6) DNS
9601 records associated with the host.
9602
9603 To avoid a delay, configure hostnames to match the MongoDB configura‐
9604 tion. That is, only create an A record if the mongod is only listening
9605 on IPv4.
9606
9607 Connection Options
9608 ┌────────────────────┬──────────────────┬────────────────────────────────┐
9609 │Constant │ Key │ Description │
9610 ├────────────────────┼──────────────────┼────────────────────────────────┤
9611 │MON‐ │ retryreads │ If "true" and the │
9612 │GOC_URI_RETRYREADS │ │ server is a MongoDB │
9613 │ │ │ 3.6+ standalone, │
9614 │ │ │ replica set, or │
9615 │ │ │ sharded cluster, │
9616 │ │ │ the driver safely │
9617 │ │ │ retries a read that │
9618 │ │ │ failed due to a │
9619 │ │ │ network error or │
9620 │ │ │ replica set │
9621 │ │ │ failover. │
9622 ├────────────────────┼──────────────────┼────────────────────────────────┤
9623 │MONGOC_URI_RETRY‐ │ retrywrites │ If "true" and the │
9624 │WRITES │ │ server is a MongoDB │
9625 │ │ │ 3.6+ replica set or │
9626 │ │ │ sharded cluster, │
9627 │ │ │ the driver safely │
9628 │ │ │ retries a write │
9629 │ │ │ that failed due to │
9630 │ │ │ a network error or │
9631 │ │ │ replica set │
9632 │ │ │ failover. Only │
9633 │ │ │ inserts, updates of │
9634 │ │ │ single documents, │
9635 │ │ │ or deletes of sin‐ │
9636 │ │ │ gle documents are │
9637 │ │ │ retried. │
9638 ├────────────────────┼──────────────────┼────────────────────────────────┤
9639 │MONGOC_URI_APPNAME │ appname │ The client applica‐ │
9640 │ │ │ tion name. This │
9641 │ │ │ value is used by │
9642 │ │ │ MongoDB when it │
9643 │ │ │ logs connection │
9644 │ │ │ information and │
9645 │ │ │ profile informa‐ │
9646 │ │ │ tion, such as slow │
9647 │ │ │ queries. │
9648 ├────────────────────┼──────────────────┼────────────────────────────────┤
9649 │MONGOC_URI_TLS │ tls │ {true|false}, indi‐ │
9650 │ │ │ cating if TLS must │
9651 │ │ │ be used. (See also │
9652 │ │ │ mon‐ │
9653 │ │ │ goc_client_set_ssl_opts │
9654 │ │ │ and mon‐ │
9655 │ │ │ goc_client_pool_set_ssl_opts.) │
9656 ├────────────────────┼──────────────────┼────────────────────────────────┤
9657 │MONGOC_URI_COMPRES‐ │ compressors │ Comma separated list of com‐ │
9658 │SORS │ │ pressors, if any, to use to │
9659 │ │ │ compress the wire protocol │
9660 │ │ │ messages. Snappy, zlib, and │
9661 │ │ │ zstd are optional build time │
9662 │ │ │ dependencies, and enable the │
9663 │ │ │ "snappy", "zlib", and "zstd" │
9664 │ │ │ values respectively. Defaults │
9665 │ │ │ to empty (no compressors). │
9666 ├────────────────────┼──────────────────┼────────────────────────────────┤
9667 │MONGOC_URI_CONNECT‐ │ connecttimeoutms │ This setting applies to new │
9668 │TIMEOUTMS │ │ server connections. It is also │
9669 │ │ │ used as the socket timeout for │
9670 │ │ │ server discovery and monitor‐ │
9671 │ │ │ ing operations. The default is │
9672 │ │ │ 10,000 ms (10 seconds). │
9673 ├────────────────────┼──────────────────┼────────────────────────────────┤
9674 │MONGOC_URI_SOCKET‐ │ sockettimeoutms │ The time in milliseconds to │
9675 │TIMEOUTMS │ │ attempt to send or receive on │
9676 │ │ │ a socket before the attempt │
9677 │ │ │ times out. The default is │
9678 │ │ │ 300,000 (5 minutes). │
9679 └────────────────────┴──────────────────┴────────────────────────────────┘
9680
9681
9682
9683
9684 │MONGOC_URI_REPLI‐ │ replicaset │ The name of the Replica Set │
9685 │CASET │ │ that the driver should connect │
9686 │ │ │ to. │
9687 ├────────────────────┼──────────────────┼────────────────────────────────┤
9688 │MONGOC_URI_ZLIBCOM‐ │ zlibcompression‐ │ When the MONGOC_URI_COMPRES‐ │
9689 │PRESSIONLEVEL │ level │ SORS includes "zlib" this │
9690 │ │ │ options configures the zlib │
9691 │ │ │ compression level, when the │
9692 │ │ │ zlib compressor is used to │
9693 │ │ │ compress client data. │
9694 └────────────────────┴──────────────────┴────────────────────────────────┘
9695
9696 Setting any of the *timeoutMS options above to 0 will be interpreted as
9697 "use the default value".
9698
9699 Authentication Options
9700 ┌────────────────────┬────────────────────┬─────────────────────────┐
9701 │Constant │ Key │ Description │
9702 ├────────────────────┼────────────────────┼─────────────────────────┤
9703 │MONGOC_URI_AUTH‐ │ authmechanism │ Specifies the mech‐ │
9704 │MECHANISM │ │ anism to use when │
9705 │ │ │ authenticating as │
9706 │ │ │ the provided user. │
9707 │ │ │ See Authentication │
9708 │ │ │ for supported val‐ │
9709 │ │ │ ues. │
9710 ├────────────────────┼────────────────────┼─────────────────────────┤
9711 │MONGOC_URI_AUTH‐ │ authmechanismprop‐ │ Certain authentica‐ │
9712 │MECHANISMPROPERTIES │ erties │ tion mechanisms │
9713 │ │ │ have additional │
9714 │ │ │ options that can be │
9715 │ │ │ configured. These │
9716 │ │ │ options should be │
9717 │ │ │ provided as comma │
9718 │ │ │ separated │
9719 │ │ │ option_key:option_value │
9720 │ │ │ pair and provided │
9721 │ │ │ as authMechanism‐ │
9722 │ │ │ Properties. │
9723 ├────────────────────┼────────────────────┼─────────────────────────┤
9724 │MONGOC_URI_AUTH‐ │ authsource │ The authSource defines │
9725 │SOURCE │ │ the database that │
9726 │ │ │ should be used to │
9727 │ │ │ authenticate to. It is │
9728 │ │ │ unnecessary to provide │
9729 │ │ │ this option the data‐ │
9730 │ │ │ base name is the same │
9731 │ │ │ as the database used in │
9732 │ │ │ the URI. │
9733 └────────────────────┴────────────────────┴─────────────────────────┘
9734
9735 Mechanism Properties
9736 ┌────────────────────┬───────────────────┬─────────────────────┐
9737 │Constant │ Key │ Description │
9738 ├────────────────────┼───────────────────┼─────────────────────┤
9739 │MONGOC_URI_CANONI‐ │ canonicalizehost‐ │ Use the canonical │
9740 │CALIZEHOSTNAME │ name │ hostname of the │
9741 │ │ │ service, rather │
9742 │ │ │ than its configured │
9743 │ │ │ alias, when authen‐ │
9744 │ │ │ ticating with │
9745 │ │ │ Cyrus-SASL Ker‐ │
9746 │ │ │ beros. │
9747 ├────────────────────┼───────────────────┼─────────────────────┤
9748 │MONGOC_URI_GSSAPIS‐ │ gssapiservicename │ Use alternative │
9749 │ERVICENAME │ │ service name. The │
9750 │ │ │ default is mongodb. │
9751 └────────────────────┴───────────────────┴─────────────────────┘
9752
9753 TLS Options
9754 ┌────────────────────┬─────────────────────┬─────────────────────┐
9755 │Constant │ Key │ Description │
9756 ├────────────────────┼─────────────────────┼─────────────────────┤
9757 │MONGOC_URI_TLS │ tls │ {true|false}, indi‐ │
9758 │ │ │ cating if TLS must │
9759 │ │ │ be used. │
9760 └────────────────────┴─────────────────────┴─────────────────────┘
9761
9762
9763 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ Path to PEM format‐ │
9764 │TIFICATEKEYFILE │ file │ ted Private Key, │
9765 │ │ │ with its Public │
9766 │ │ │ Certificate con‐ │
9767 │ │ │ catenated at the │
9768 │ │ │ end. │
9769 ├────────────────────┼─────────────────────┼─────────────────────┤
9770 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ The password, if │
9771 │TIFICATEKEYPASSWORD │ password │ any, to use to │
9772 │ │ │ unlock encrypted │
9773 │ │ │ Private Key. │
9774 ├────────────────────┼─────────────────────┼─────────────────────┤
9775 │MON‐ │ tlscafile │ One, or a bundle │
9776 │GOC_URI_TLSCAFILE │ │ of, Certificate │
9777 │ │ │ Authorities whom │
9778 │ │ │ should be consid‐ │
9779 │ │ │ ered to be trusted. │
9780 ├────────────────────┼─────────────────────┼─────────────────────┤
9781 │MONGOC_URI_TLSAL‐ │ tlsallowinvalidcer‐ │ Accept and ignore │
9782 │LOWINVALIDCERTIFI‐ │ tificates │ certificate verifi‐ │
9783 │CATES │ │ cation errors (e.g. │
9784 │ │ │ untrusted issuer, │
9785 │ │ │ expired, etc.) │
9786 ├────────────────────┼─────────────────────┼─────────────────────┤
9787 │MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │ Ignore hostname │
9788 │LOWINVALIDHOSTNAMES │ hostnames │ verification of the │
9789 │ │ │ certificate (e.g. │
9790 │ │ │ Man In The Middle, │
9791 │ │ │ using valid cer‐ │
9792 │ │ │ tificate, but │
9793 │ │ │ issued for another │
9794 │ │ │ hostname) │
9795 ├────────────────────┼─────────────────────┼─────────────────────┤
9796 │MONGOC_URI_TLSINSE‐ │ tlsinsecure │ {true|false}, indi‐ │
9797 │CURE │ │ cating if insecure │
9798 │ │ │ TLS options should │
9799 │ │ │ be used. Currently │
9800 │ │ │ this implies MON‐ │
9801 │ │ │ GOC_URI_TLSALLOWIN‐ │
9802 │ │ │ VALIDCERTIFICATES │
9803 │ │ │ and MON‐ │
9804 │ │ │ GOC_URI_TLSALLOWIN‐ │
9805 │ │ │ VALIDHOSTNAMES. │
9806 ├────────────────────┼─────────────────────┼─────────────────────┤
9807 │MONGOC_URI_TLSDIS‐ │ tlsdisablecertifi‐ │ {true|false}, indi‐ │
9808 │ABLECERTIFICATERE‐ │ caterevocationcheck │ cates if revocation │
9809 │VOCATIONCHECK │ │ checking (CRL / │
9810 │ │ │ OCSP) should be │
9811 │ │ │ disabled. │
9812 ├────────────────────┼─────────────────────┼─────────────────────┤
9813 │MONGOC_URI_TLSDIS‐ │ tlsdisableocspend‐ │ {true|false}, indi‐ │
9814 │ABLEOCSPEND‐ │ pointcheck │ cates if OCSP │
9815 │POINTCHECK │ │ responder endpoints │
9816 │ │ │ should not be │
9817 │ │ │ requested when an │
9818 │ │ │ OCSP response is │
9819 │ │ │ not stapled. │
9820 └────────────────────┴─────────────────────┴─────────────────────┘
9821
9822 See configuring_tls for details about these options and about building
9823 libmongoc with TLS support.
9824
9825 Deprecated SSL Options
9826 The following options have been deprecated and may be removed from
9827 future releases of libmongoc.
9828
9829 ┌──────────────────────┬──────────────────┬───────────────────┬──────────────────┐
9830 │Constant │ Key │ Deprecated For │ Key │
9831 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9832 │MONGOC_URI_SSL │ ssl │ MONGOC_URI_TLS │ tls │
9833 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9834 │MON‐ │ sslclientcer‐ │ MON‐ │ tlscertifi‐ │
9835 │GOC_URI_SSLCLIENTCER‐ │ tificatekeyfile │ GOC_URI_TLSCER‐ │ catekeyfile │
9836 │TIFICATEKEYFILE │ │ TIFICATEKEYFILE │ │
9837 └──────────────────────┴──────────────────┴───────────────────┴──────────────────┘
9838
9839
9840
9841
9842 │MON‐ │ sslclientcer‐ │ MON‐ │ tlscertifi‐ │
9843 │GOC_URI_SSLCLIENTCER‐ │ tificatekeypass‐ │ GOC_URI_TLSCER‐ │ catekeypassword │
9844 │TIFICATEKEYPASSWORD │ word │ TIFICATEKEYPASS‐ │ │
9845 │ │ │ WORD │ │
9846 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9847 │MONGOC_URI_SSLCER‐ │ sslcertifi‐ │ MON‐ │ tlscafile │
9848 │TIFICATEAUTHORITYFILE │ cateauthority‐ │ GOC_URI_TLSCAFILE │ │
9849 │ │ file │ │ │
9850 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9851 │MONGOC_URI_SSLALLOW‐ │ sslallowinvalid‐ │ MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │
9852 │INVALIDCERTIFICATES │ certificates │ LOWINVALIDCER‐ │ certificates │
9853 │ │ │ TIFICATES │ │
9854 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9855 │MONGOC_URI_SSLALLOW‐ │ sslallowinvalid‐ │ MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │
9856 │INVALIDHOSTNAMES │ hostnames │ LOWINVALIDHOST‐ │ hostnames │
9857 │ │ │ NAMES │ │
9858 └──────────────────────┴──────────────────┴───────────────────┴──────────────────┘
9859
9860 Server Discovery, Monitoring, and Selection Options
9861 Clients in a mongoc_client_pool_t share a topology scanner that runs on
9862 a background thread. The thread wakes every heartbeatFrequencyMS
9863 (default 10 seconds) to scan all MongoDB servers in parallel. Whenever
9864 an application operation requires a server that is not known--for exam‐
9865 ple, if there is no known primary and your application attempts an
9866 insert--the thread rescans all servers every half-second. In this situ‐
9867 ation the pooled client waits up to serverSelectionTimeoutMS (default
9868 30 seconds) for the thread to find a server suitable for the operation,
9869 then returns an error with domain MONGOC_ERROR_SERVER_SELECTION.
9870
9871 Technically, the total time an operation may wait while a pooled client
9872 scans the topology is controlled both by serverSelectionTimeoutMS and
9873 connectTimeoutMS. The longest wait occurs if the last scan begins just
9874 at the end of the selection timeout, and a slow or down server requires
9875 the full connection timeout before the client gives up.
9876
9877 A non-pooled client is single-threaded. Every heartbeatFrequencyMS, it
9878 blocks the next application operation while it does a parallel scan.
9879 This scan takes as long as needed to check the slowest server: roughly
9880 connectTimeoutMS. Therefore the default heartbeatFrequencyMS for sin‐
9881 gle-threaded clients is greater than for pooled clients: 60 seconds.
9882
9883 By default, single-threaded (non-pooled) clients scan only once when an
9884 operation requires a server that is not known. If you attempt an insert
9885 and there is no known primary, the client checks all servers once try‐
9886 ing to find it, then succeeds or returns an error with domain MON‐
9887 GOC_ERROR_SERVER_SELECTION. But if you set serverSelectionTryOnce to
9888 "false", the single-threaded client loops, checking all servers every
9889 half-second, until serverSelectionTimeoutMS.
9890
9891 The total time an operation may wait for a single-threaded client to
9892 scan the topology is determined by connectTimeoutMS in the try-once
9893 case, or serverSelectionTimeoutMS and connectTimeoutMS if serverSelec‐
9894 tionTryOnce is set "false".
9895
9896 ┌────────────────────┬─────────────────────┬─────────────────────┐
9897 │Constant │ Key │ Description │
9898 ├────────────────────┼─────────────────────┼─────────────────────┤
9899 │MONGOC_URI_HEART‐ │ heartbeatfrequen‐ │ The interval │
9900 │BEATFREQUENCYMS │ cyms │ between server mon‐ │
9901 │ │ │ itoring checks. │
9902 │ │ │ Defaults to │
9903 │ │ │ 10,000ms (10 sec‐ │
9904 │ │ │ onds) in pooled │
9905 │ │ │ (multi-threaded) │
9906 │ │ │ mode, 60,000ms (60 │
9907 │ │ │ seconds) in │
9908 │ │ │ non-pooled mode │
9909 │ │ │ (single-threaded). │
9910 ├────────────────────┼─────────────────────┼─────────────────────┤
9911 │MONGOC_URI_SERVERS‐ │ serverselection‐ │ A timeout in mil‐ │
9912 │ELECTIONTIMEOUTMS │ timeoutms │ liseconds to block │
9913 │ │ │ for server selec‐ │
9914 │ │ │ tion before throw‐ │
9915 │ │ │ ing an exception. │
9916 │ │ │ The default is │
9917 │ │ │ 30,0000ms (30 sec‐ │
9918 │ │ │ onds). │
9919 └────────────────────┴─────────────────────┴─────────────────────┘
9920
9921 │MONGOC_URI_SERVERS‐ │ serverselectiontry‐ │ If "true", the │
9922 │ELECTIONTRYONCE │ once │ driver scans the │
9923 │ │ │ topology exactly │
9924 │ │ │ once after server │
9925 │ │ │ selection fails, │
9926 │ │ │ then either selects │
9927 │ │ │ a server or returns │
9928 │ │ │ an error. If it is │
9929 │ │ │ false, then the │
9930 │ │ │ driver repeatedly │
9931 │ │ │ searches for a │
9932 │ │ │ suitable server for │
9933 │ │ │ up to serverSelec‐ │
9934 │ │ │ tionTimeoutMS mil‐ │
9935 │ │ │ liseconds (pausing │
9936 │ │ │ a half second │
9937 │ │ │ between attempts). │
9938 │ │ │ The default for │
9939 │ │ │ serverSelectionTry‐ │
9940 │ │ │ Once is "false" for │
9941 │ │ │ pooled clients, │
9942 │ │ │ otherwise "true". │
9943 │ │ │ Pooled clients │
9944 │ │ │ ignore serverSelec‐ │
9945 │ │ │ tionTryOnce; they │
9946 │ │ │ signal the thread │
9947 │ │ │ to rescan the │
9948 │ │ │ topology every │
9949 │ │ │ half-second until │
9950 │ │ │ serverSelection‐ │
9951 │ │ │ TimeoutMS expires. │
9952 ├────────────────────┼─────────────────────┼─────────────────────┤
9953 │MONGOC_URI_SOCK‐ │ socketcheckinter‐ │ Only applies to │
9954 │ETCHECKINTERVALMS │ valms │ single threaded │
9955 │ │ │ clients. If a │
9956 │ │ │ socket has not been │
9957 │ │ │ used within this │
9958 │ │ │ time, its connec‐ │
9959 │ │ │ tion is checked │
9960 │ │ │ with a quick │
9961 │ │ │ "isMaster" call │
9962 │ │ │ before it is used │
9963 │ │ │ again. Defaults to │
9964 │ │ │ 5,000ms (5 sec‐ │
9965 │ │ │ onds). │
9966 ├────────────────────┼─────────────────────┼─────────────────────┤
9967 │MONGOC_URI_DIRECT‐ │ directconnection │ If "true", the │
9968 │CONNECTION │ │ driver connects to │
9969 │ │ │ a single server │
9970 │ │ │ directly and will │
9971 │ │ │ not monitor addi‐ │
9972 │ │ │ tional servers. If │
9973 │ │ │ "false", the driver │
9974 │ │ │ connects based on │
9975 │ │ │ the presence and │
9976 │ │ │ value of the repli‐ │
9977 │ │ │ caSet option. │
9978 └────────────────────┴─────────────────────┴─────────────────────┘
9979
9980 Setting any of the *TimeoutMS options above to 0 will be interpreted as
9981 "use the default value".
9982
9983 Connection Pool Options
9984 These options govern the behavior of a mongoc_client_pool_t. They are
9985 ignored by a non-pooled mongoc_client_t.
9986
9987 ┌────────────────────┬────────────────────┬─────────────────────┐
9988 │Constant │ Key │ Description │
9989 └────────────────────┴────────────────────┴─────────────────────┘
9990
9991
9992
9993
9994
9995
9996
9997
9998
9999
10000 │MONGOC_URI_MAXPOOL‐ │ maxpoolsize │ The maximum number │
10001 │SIZE │ │ of clients created │
10002 │ │ │ by a mon‐ │
10003 │ │ │ goc_client_pool_t │
10004 │ │ │ total (both in the │
10005 │ │ │ pool and checked │
10006 │ │ │ out). The default │
10007 │ │ │ value is 100. Once │
10008 │ │ │ it is reached, mon‐ │
10009 │ │ │ goc_client_pool_pop │
10010 │ │ │ blocks until │
10011 │ │ │ another thread │
10012 │ │ │ pushes a client. │
10013 ├────────────────────┼────────────────────┼─────────────────────┤
10014 │MONGOC_URI_MINPOOL‐ │ minpoolsize │ Deprecated. This │
10015 │SIZE │ │ option's behavior │
10016 │ │ │ does not match its │
10017 │ │ │ name, and its │
10018 │ │ │ actual behavior │
10019 │ │ │ will likely hurt │
10020 │ │ │ performance. │
10021 ├────────────────────┼────────────────────┼─────────────────────┤
10022 │MONGOC_URI_MAXIDLE‐ │ maxidletimems │ Not implemented. │
10023 │TIMEMS │ │ │
10024 ├────────────────────┼────────────────────┼─────────────────────┤
10025 │MONGOC_URI_WAIT‐ │ waitqueuemultiple │ Not implemented. │
10026 │QUEUEMULTIPLE │ │ │
10027 ├────────────────────┼────────────────────┼─────────────────────┤
10028 │MONGOC_URI_WAIT‐ │ waitqueuetimeoutms │ The maximum time to │
10029 │QUEUETIMEOUTMS │ │ wait for a client │
10030 │ │ │ to become available │
10031 │ │ │ from the pool. │
10032 └────────────────────┴────────────────────┴─────────────────────┘
10033
10034 Write Concern Options
10035 ┌───────────────────┬────────────┬─────────────────────┐
10036 │Constant │ Key │ Description │
10037 └───────────────────┴────────────┴─────────────────────┘
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079 MONGOC_URI_W w Determines the
10080 write concern
10081 (guarantee). Valid
10082 values:
10083
10084 · 0 = The
10085 driver
10086 will not
10087 acknowl‐
10088 edge write
10089 operations
10090 but will
10091 pass or
10092 handle any
10093 network
10094 and socket
10095 errors
10096 that it
10097 receives
10098 to the
10099 client. If
10100 you dis‐
10101 able write
10102 concern
10103 but enable
10104 the get‐
10105 LastError
10106 command’s
10107 w option,
10108 w over‐
10109 rides the
10110 w option.
10111
10112 · 1 = Pro‐
10113 vides
10114 basic
10115 acknowl‐
10116 edgement
10117 of write
10118 opera‐
10119 tions. By
10120 specifying
10121 1, you
10122 require
10123 that a
10124 standalone
10125 mongod
10126 instance,
10127 or the
10128 primary
10129 for
10130 replica
10131 sets,
10132 acknowl‐
10133 edge all
10134 write
10135 opera‐
10136 tions. For
10137 drivers
10138 released
10139 after the
10140 default
10141 write con‐
10142 cern
10143 change,
10144 this is
10145 the
10146 default
10147 write con‐
10148 cern set‐
10149 ting.
10150
10151 · majority =
10152 For
10153 replica
10154 sets, if
10155 you spec‐
10156 ify the
10157 special
10158 majority
10159 value to w
10160 option,
10161 write
10162 operations
10163 will only
10164 return
10165 success‐
10166 fully
10167 after a
10168 majority
10169 of the
10170 configured
10171 replica
10172 set mem‐
10173 bers have
10174 acknowl‐
10175 edged the
10176 write
10177 operation.
10178
10179 · n = For
10180 replica
10181 sets, if
10182 you spec‐
10183 ify a num‐
10184 ber n
10185 greater
10186 than 1,
10187 operations
10188 with this
10189 write con‐
10190 cern
10191 return
10192 only after
10193 n members
10194 of the set
10195 have
10196 acknowl‐
10197 edged the
10198 write. If
10199 you set n
10200 to a num‐
10201 ber that
10202 is greater
10203 than the
10204 number of
10205 available
10206 set mem‐
10207 bers or
10208 members
10209 that hold
10210 data, Mon‐
10211 goDB will
10212 wait,
10213 poten‐
10214 tially
10215 indefi‐
10216 nitely,
10217 for these
10218 members to
10219 become
10220 available.
10221
10222 · tags = For
10223 replica
10224 sets, you
10225 can spec‐
10226 ify a tag
10227 set to
10228 require
10229 that all
10230 members of
10231 the set
10232 that have
10233 these tags
10234 configured
10235 return
10236 confirma‐
10237 tion of
10238 the write
10239 operation.
10240 ├───────────────────┼────────────┼─────────────────────┤
10241 │MONGOC_URI_WTIME‐ │ wtimeoutms │ The time in mil‐ │
10242 │OUTMS │ │ liseconds to wait │
10243 │ │ │ for replication to │
10244 │ │ │ succeed, as speci‐ │
10245 │ │ │ fied in the w │
10246 │ │ │ option, before tim‐ │
10247 │ │ │ ing out. When │
10248 │ │ │ wtimeoutMS is 0, │
10249 │ │ │ write operations │
10250 │ │ │ will never time │
10251 │ │ │ out. │
10252 ├───────────────────┼────────────┼─────────────────────┤
10253 │MONGOC_URI_JOURNAL │ journal │ Controls whether │
10254 │ │ │ write operations │
10255 │ │ │ will wait until the │
10256 │ │ │ mongod acknowledges │
10257 │ │ │ the write opera‐ │
10258 │ │ │ tions and commits │
10259 │ │ │ the data to the on │
10260 │ │ │ disk journal. │
10261 │ │ │ │
10262 │ │ │ · true = │
10263 │ │ │ Enables │
10264 │ │ │ journal │
10265 │ │ │ commit │
10266 │ │ │ acknowl‐ │
10267 │ │ │ edgement │
10268 │ │ │ write con‐ │
10269 │ │ │ cern. │
10270 │ │ │ Equivalent │
10271 │ │ │ to speci‐ │
10272 │ │ │ fying the │
10273 │ │ │ getLastEr‐ │
10274 │ │ │ ror com‐ │
10275 │ │ │ mand with │
10276 │ │ │ the j │
10277 │ │ │ option │
10278 │ │ │ enabled. │
10279 │ │ │ │
10280 │ │ │ · false = │
10281 │ │ │ Does not │
10282 │ │ │ require │
10283 │ │ │ that mon‐ │
10284 │ │ │ god commit │
10285 │ │ │ write │
10286 │ │ │ operations │
10287 │ │ │ to the │
10288 │ │ │ journal │
10289 │ │ │ before │
10290 │ │ │ acknowl‐ │
10291 │ │ │ edging the │
10292 │ │ │ write │
10293 │ │ │ operation. │
10294 │ │ │ This is │
10295 │ │ │ the │
10296 │ │ │ default │
10297 │ │ │ option for │
10298 │ │ │ the jour‐ │
10299 │ │ │ nal param‐ │
10300 │ │ │ eter. │
10301 └───────────────────┴────────────┴─────────────────────┘
10302
10303 Read Concern Options
10304 ┌────────────────────┬──────────────────┬─────────────────────┐
10305 │Constant │ Key │ Description │
10306 ├────────────────────┼──────────────────┼─────────────────────┤
10307 │MONGOC_URI_READCON‐ │ readconcernlevel │ The level of isola‐ │
10308 │CERNLEVEL │ │ tion for read oper‐ │
10309 │ │ │ ations. If the │
10310 │ │ │ level is left │
10311 │ │ │ unspecified, the │
10312 │ │ │ server default will │
10313 │ │ │ be used. See │
10314 │ │ │ readConcern in the │
10315 │ │ │ MongoDB Manual for │
10316 │ │ │ details. │
10317 └────────────────────┴──────────────────┴─────────────────────┘
10318
10319 Read Preference Options
10320 When connected to a replica set, the driver chooses which member to
10321 query using the read preference:
10322
10323 1. Choose members whose type matches "readPreference".
10324
10325 2. From these, if there are any tags sets configured, choose members
10326 matching the first tag set. If there are none, fall back to the next
10327 tag set and so on, until some members are chosen or the tag sets are
10328 exhausted.
10329
10330 3. From the chosen servers, distribute queries randomly among the
10331 server with the fastest round-trip times. These include the server
10332 with the fastest time and any whose round-trip time is no more than
10333 "localThresholdMS" slower.
10334
10335 ┌─────────────────────┬─────────────────────┬──────────────────────────┐
10336 │Constant │ Key │ Description │
10337 ├─────────────────────┼─────────────────────┼──────────────────────────┤
10338 │MONGOC_URI_READ‐ │ readpreference │ Specifies the │
10339 │PREFERENCE │ │ replica set read │
10340 │ │ │ preference for this │
10341 │ │ │ connection. This │
10342 │ │ │ setting overrides │
10343 │ │ │ any slaveOk value. │
10344 │ │ │ The read preference │
10345 │ │ │ values are the fol‐ │
10346 │ │ │ lowing: │
10347 │ │ │ │
10348 │ │ │ · primary │
10349 │ │ │ (default) │
10350 │ │ │ │
10351 │ │ │ · prima‐ │
10352 │ │ │ ryPre‐ │
10353 │ │ │ ferred │
10354 │ │ │ │
10355 │ │ │ · secondary │
10356 │ │ │ │
10357 │ │ │ · sec‐ │
10358 │ │ │ ondaryPre‐ │
10359 │ │ │ ferred │
10360 │ │ │ │
10361 │ │ │ · nearest │
10362 ├─────────────────────┼─────────────────────┼──────────────────────────┤
10363 │MONGOC_URI_READ‐ │ readpreferencetags │ A representation of │
10364 │PREFERENCETAGS │ │ a tag set. See also │
10365 │ │ │ mon‐ │
10366 │ │ │ goc-read-prefs-tag-sets. │
10367 ├─────────────────────┼─────────────────────┼──────────────────────────┤
10368 │MON‐ │ localthresholdms │ How far to distribute │
10369 │GOC_URI_LOCALTHRESH‐ │ │ queries, beyond the │
10370 │OLDMS │ │ server with the fastest │
10371 │ │ │ round-trip time. By │
10372 │ │ │ default, only servers │
10373 │ │ │ within 15ms of the │
10374 │ │ │ fastest round-trip time │
10375 │ │ │ receive queries. │
10376 ├─────────────────────┼─────────────────────┼──────────────────────────┤
10377 │MONGOC_URI_MAXSTALE‐ │ maxstalenessseconds │ The maximum replication │
10378 │NESSSECONDS │ │ lag, in wall clock time, │
10379 │ │ │ that a secondary can │
10380 │ │ │ suffer and still be eli‐ │
10381 │ │ │ gible. The smallest │
10382 │ │ │ allowed value for │
10383 │ │ │ maxStalenessSeconds is │
10384 │ │ │ 90 seconds. │
10385 └─────────────────────┴─────────────────────┴──────────────────────────┘
10386
10387 NOTE:
10388 When connecting to more than one mongos, libmongoc's localThresh‐
10389 oldMS applies only to the selection of mongos servers. The threshold
10390 for selecting among replica set members in shards is controlled by
10391 the mongos's localThreshold command line option.
10392
10393 Legacy Options
10394 For historical reasons, the following options are available. They
10395 should however not be used.
10396
10397
10398 ┌───────────────────┬─────────┬─────────────────────┐
10399 │Constant │ Key │ Description │
10400 ├───────────────────┼─────────┼─────────────────────┤
10401 │MONGOC_URI_SAFE │ safe │ {true|false} Same │
10402 │ │ │ as w={1|0} │
10403 ├───────────────────┼─────────┼─────────────────────┤
10404 │MONGOC_URI_SLAVEOK │ slaveok │ When set, same as │
10405 │ │ │ readPreference=sec‐ │
10406 │ │ │ ondaryPreferred │
10407 └───────────────────┴─────────┴─────────────────────┘
10408
10409 Version Checks
10410 Conditional compilation based on mongoc version
10411
10412 Description
10413 The following preprocessor macros can be used to perform various checks
10414 based on the version of the library you are compiling against. This
10415 may be useful if you only want to enable a feature on a certain version
10416 of the library.
10417
10418 #include <mongoc/mongoc.h>
10419
10420 #define MONGOC_MAJOR_VERSION (x)
10421 #define MONGOC_MINOR_VERSION (y)
10422 #define MONGOC_MICRO_VERSION (z)
10423 #define MONGOC_VERSION_S "x.y.z"
10424 #define MONGOC_VERSION_HEX ((1 << 24) | (0 << 16) | (0 << 8) | 0)
10425 #define MONGOC_CHECK_VERSION(major, minor, micro)
10426
10427 Only compile a block on MongoDB C Driver 1.1.0 and newer.
10428
10429 #if MONGOC_CHECK_VERSION(1, 1, 0)
10430 static void
10431 do_something (void)
10432 {
10433 }
10434 #endif
10435
10436 mongoc_write_concern_t
10437 Write Concern abstraction
10438
10439 Synopsis
10440 mongoc_write_concern_t tells the driver what level of acknowledgement
10441 to await from the server. The default, MONGOC_WRITE_CONCERN_W_DEFAULT,
10442 is right for the great majority of applications.
10443
10444 You can specify a write concern on connection objects, database
10445 objects, collection objects, or per-operation. Data-modifying opera‐
10446 tions typically use the write concern of the object they operate on,
10447 and check the server response for a write concern error or write con‐
10448 cern timeout. For example, mongoc_collection_drop_index uses the col‐
10449 lection's write concern, and a write concern error or timeout in the
10450 response is considered a failure.
10451
10452 Exceptions to this principle are the generic command functions:
10453
10454 · mongoc_client_command
10455
10456 · mongoc_client_command_simple
10457
10458 · mongoc_database_command
10459
10460 · mongoc_database_command_simple
10461
10462 · mongoc_collection_command
10463
10464 · mongoc_collection_command_simple
10465
10466 These generic command functions do not automatically apply a write con‐
10467 cern, and they do not check the server response for a write concern
10468 error or write concern timeout.
10469
10470 See Write Concern on the MongoDB website for more information.
10471
10472 Write Concern Levels
10473 Set the write concern level with mongoc_write_concern_set_w.
10474
10475
10476
10477 ┌───────────────────────────┬────────────────────────────┐
10478 │MONGOC_WRITE_CON‐ │ By default, writes block │
10479 │CERN_W_DEFAULT (1) │ awaiting acknowledgement │
10480 │ │ from MongoDB. Acknowledged │
10481 │ │ write concern allows │
10482 │ │ clients to catch network, │
10483 │ │ duplicate key, and other │
10484 │ │ errors. │
10485 ├───────────────────────────┼────────────────────────────┤
10486 │MONGOC_WRITE_CON‐ │ With this write concern, │
10487 │CERN_W_UNACKNOWLEDGED (0) │ MongoDB does not acknowl‐ │
10488 │ │ edge the receipt of write │
10489 │ │ operation. Unacknowledged │
10490 │ │ is similar to errors │
10491 │ │ ignored; however, mongoc │
10492 │ │ attempts to receive and │
10493 │ │ handle network errors when │
10494 │ │ possible. │
10495 ├───────────────────────────┼────────────────────────────┤
10496 │MONGOC_WRITE_CON‐ │ Block until a write has │
10497 │CERN_W_MAJORITY (majority) │ been propagated to a │
10498 │ │ majority of the nodes in │
10499 │ │ the replica set. │
10500 ├───────────────────────────┼────────────────────────────┤
10501 │n │ Block until a write has │
10502 │ │ been propagated to at │
10503 │ │ least n nodes in the │
10504 │ │ replica set. │
10505 └───────────────────────────┴────────────────────────────┘
10506
10507 Deprecations
10508 The write concern MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED (value -1) is a
10509 deprecated synonym for MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (value 0),
10510 and will be removed in the next major release.
10511
10512 mongoc_write_concern_set_fsync is deprecated.
10513
10514 Application Performance Monitoring (APM)
10515 The MongoDB C Driver allows you to monitor all the MongoDB operations
10516 the driver executes. This event-notification system conforms to two
10517 MongoDB driver specs:
10518
10519 · Command Monitoring: events related to all application operations.
10520
10521 · SDAM Monitoring: events related to the driver's Server Discovery And
10522 Monitoring logic.
10523
10524 To receive notifications, create a mongoc_apm_callbacks_t with mon‐
10525 goc_apm_callbacks_new, set callbacks on it, then pass it to mon‐
10526 goc_client_set_apm_callbacks or mongoc_client_pool_set_apm_callbacks.
10527
10528 Command-Monitoring Example
10529 example-command-monitoring.c
10530
10531 /* gcc example-command-monitoring.c -o example-command-monitoring \
10532 * $(pkg-config --cflags --libs libmongoc-1.0) */
10533
10534 /* ./example-command-monitoring [CONNECTION_STRING] */
10535
10536 #include <mongoc/mongoc.h>
10537 #include <stdio.h>
10538
10539
10540 typedef struct {
10541 int started;
10542 int succeeded;
10543 int failed;
10544 } stats_t;
10545
10546
10547 void
10548 command_started (const mongoc_apm_command_started_t *event)
10549 {
10550 char *s;
10551
10552 s = bson_as_relaxed_extended_json (
10553 mongoc_apm_command_started_get_command (event), NULL);
10554 printf ("Command %s started on %s:\n%s\n\n",
10555 mongoc_apm_command_started_get_command_name (event),
10556 mongoc_apm_command_started_get_host (event)->host,
10557 s);
10558
10559 ((stats_t *) mongoc_apm_command_started_get_context (event))->started++;
10560
10561 bson_free (s);
10562 }
10563
10564
10565 void
10566 command_succeeded (const mongoc_apm_command_succeeded_t *event)
10567 {
10568 char *s;
10569
10570 s = bson_as_relaxed_extended_json (
10571 mongoc_apm_command_succeeded_get_reply (event), NULL);
10572 printf ("Command %s succeeded:\n%s\n\n",
10573 mongoc_apm_command_succeeded_get_command_name (event),
10574 s);
10575
10576 ((stats_t *) mongoc_apm_command_succeeded_get_context (event))->succeeded++;
10577
10578 bson_free (s);
10579 }
10580
10581
10582 void
10583 command_failed (const mongoc_apm_command_failed_t *event)
10584 {
10585 bson_error_t error;
10586
10587 mongoc_apm_command_failed_get_error (event, &error);
10588 printf ("Command %s failed:\n\"%s\"\n\n",
10589 mongoc_apm_command_failed_get_command_name (event),
10590 error.message);
10591
10592 ((stats_t *) mongoc_apm_command_failed_get_context (event))->failed++;
10593 }
10594
10595
10596 int
10597 main (int argc, char *argv[])
10598 {
10599 mongoc_client_t *client;
10600 mongoc_apm_callbacks_t *callbacks;
10601 stats_t stats = {0};
10602 mongoc_collection_t *collection;
10603 bson_error_t error;
10604 const char *uri_string =
10605 "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
10606 mongoc_uri_t *uri;
10607 const char *collection_name = "test";
10608 bson_t *docs[2];
10609
10610 mongoc_init ();
10611
10612 if (argc > 1) {
10613 uri_string = argv[1];
10614 }
10615
10616 uri = mongoc_uri_new_with_error (uri_string, &error);
10617 if (!uri) {
10618 fprintf (stderr,
10619 "failed to parse URI: %s\n"
10620 "error message: %s\n",
10621 uri_string,
10622 error.message);
10623 return EXIT_FAILURE;
10624 }
10625
10626 client = mongoc_client_new_from_uri (uri);
10627 if (!client) {
10628 return EXIT_FAILURE;
10629 }
10630
10631 mongoc_client_set_error_api (client, 2);
10632 callbacks = mongoc_apm_callbacks_new ();
10633 mongoc_apm_set_command_started_cb (callbacks, command_started);
10634 mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
10635 mongoc_apm_set_command_failed_cb (callbacks, command_failed);
10636 mongoc_client_set_apm_callbacks (
10637 client, callbacks, (void *) &stats /* context pointer */);
10638
10639 collection = mongoc_client_get_collection (client, "test", collection_name);
10640 mongoc_collection_drop (collection, NULL);
10641
10642 docs[0] = BCON_NEW ("_id", BCON_INT32 (0));
10643 docs[1] = BCON_NEW ("_id", BCON_INT32 (1));
10644 mongoc_collection_insert_many (
10645 collection, (const bson_t **) docs, 2, NULL, NULL, NULL);
10646
10647 /* duplicate key error on the second insert */
10648 mongoc_collection_insert_one (collection, docs[0], NULL, NULL, NULL);
10649
10650 mongoc_collection_destroy (collection);
10651 mongoc_apm_callbacks_destroy (callbacks);
10652 mongoc_uri_destroy (uri);
10653 mongoc_client_destroy (client);
10654
10655 printf ("started: %d\nsucceeded: %d\nfailed: %d\n",
10656 stats.started,
10657 stats.succeeded,
10658 stats.failed);
10659
10660 bson_destroy (docs[0]);
10661 bson_destroy (docs[1]);
10662
10663 mongoc_cleanup ();
10664
10665 return EXIT_SUCCESS;
10666 }
10667
10668
10669 This example program prints:
10670
10671 Command drop started on 127.0.0.1:
10672 { "drop" : "test" }
10673
10674 Command drop succeeded:
10675 { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }
10676
10677 Command insert started on 127.0.0.1:
10678 {
10679 "insert" : "test",
10680 "ordered" : true,
10681 "documents" : [
10682 { "_id" : 0 }, { "_id" : 1 }
10683 ]
10684 }
10685
10686 Command insert succeeded:
10687 { "n" : 2, "ok" : 1.0 }
10688
10689 Command insert started on 127.0.0.1:
10690 {
10691 "insert" : "test",
10692 "ordered" : true,
10693 "documents" : [
10694 { "_id" : 0 }
10695 ]
10696 }
10697
10698 Command insert succeeded:
10699 {
10700 "n" : 0,
10701 "writeErrors" : [
10702 { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
10703 ],
10704 "ok" : 1.0
10705 }
10706
10707 started: 3
10708 succeeded: 3
10709 failed: 0
10710
10711 The output has been edited and formatted for clarity. Depending on your
10712 server configuration, messages may include metadata like database name,
10713 logical session ids, or cluster times that are not shown here.
10714
10715 The final "insert" command is considered successful, despite the
10716 writeError, because the server replied to the overall command with
10717 "ok": 1.
10718
10719 SDAM Monitoring Example
10720 example-sdam-monitoring.c
10721
10722 /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
10723 * $(pkg-config --cflags --libs libmongoc-1.0) */
10724
10725 /* ./example-sdam-monitoring [CONNECTION_STRING] */
10726
10727 #include <mongoc/mongoc.h>
10728 #include <stdio.h>
10729
10730
10731 typedef struct {
10732 int server_changed_events;
10733 int server_opening_events;
10734 int server_closed_events;
10735 int topology_changed_events;
10736 int topology_opening_events;
10737 int topology_closed_events;
10738 int heartbeat_started_events;
10739 int heartbeat_succeeded_events;
10740 int heartbeat_failed_events;
10741 } stats_t;
10742
10743
10744 static void
10745 server_changed (const mongoc_apm_server_changed_t *event)
10746 {
10747 stats_t *context;
10748 const mongoc_server_description_t *prev_sd, *new_sd;
10749
10750 context = (stats_t *) mongoc_apm_server_changed_get_context (event);
10751 context->server_changed_events++;
10752
10753 prev_sd = mongoc_apm_server_changed_get_previous_description (event);
10754 new_sd = mongoc_apm_server_changed_get_new_description (event);
10755
10756 printf ("server changed: %s %s -> %s\n",
10757 mongoc_apm_server_changed_get_host (event)->host_and_port,
10758 mongoc_server_description_type (prev_sd),
10759 mongoc_server_description_type (new_sd));
10760 }
10761
10762
10763 static void
10764 server_opening (const mongoc_apm_server_opening_t *event)
10765 {
10766 stats_t *context;
10767
10768 context = (stats_t *) mongoc_apm_server_opening_get_context (event);
10769 context->server_opening_events++;
10770
10771 printf ("server opening: %s\n",
10772 mongoc_apm_server_opening_get_host (event)->host_and_port);
10773 }
10774
10775
10776 static void
10777 server_closed (const mongoc_apm_server_closed_t *event)
10778 {
10779 stats_t *context;
10780
10781 context = (stats_t *) mongoc_apm_server_closed_get_context (event);
10782 context->server_closed_events++;
10783
10784 printf ("server closed: %s\n",
10785 mongoc_apm_server_closed_get_host (event)->host_and_port);
10786 }
10787
10788
10789 static void
10790 topology_changed (const mongoc_apm_topology_changed_t *event)
10791 {
10792 stats_t *context;
10793 const mongoc_topology_description_t *prev_td;
10794 const mongoc_topology_description_t *new_td;
10795 mongoc_server_description_t **prev_sds;
10796 size_t n_prev_sds;
10797 mongoc_server_description_t **new_sds;
10798 size_t n_new_sds;
10799 size_t i;
10800 mongoc_read_prefs_t *prefs;
10801
10802 context = (stats_t *) mongoc_apm_topology_changed_get_context (event);
10803 context->topology_changed_events++;
10804
10805 prev_td = mongoc_apm_topology_changed_get_previous_description (event);
10806 prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds);
10807 new_td = mongoc_apm_topology_changed_get_new_description (event);
10808 new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds);
10809
10810 printf ("topology changed: %s -> %s\n",
10811 mongoc_topology_description_type (prev_td),
10812 mongoc_topology_description_type (new_td));
10813
10814 if (n_prev_sds) {
10815 printf (" previous servers:\n");
10816 for (i = 0; i < n_prev_sds; i++) {
10817 printf (" %s %s\n",
10818 mongoc_server_description_type (prev_sds[i]),
10819 mongoc_server_description_host (prev_sds[i])->host_and_port);
10820 }
10821 }
10822
10823 if (n_new_sds) {
10824 printf (" new servers:\n");
10825 for (i = 0; i < n_new_sds; i++) {
10826 printf (" %s %s\n",
10827 mongoc_server_description_type (new_sds[i]),
10828 mongoc_server_description_host (new_sds[i])->host_and_port);
10829 }
10830 }
10831
10832 prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
10833
10834 /* it is safe, and unfortunately necessary, to cast away const here */
10835 if (mongoc_topology_description_has_readable_server (
10836 (mongoc_topology_description_t *) new_td, prefs)) {
10837 printf (" secondary AVAILABLE\n");
10838 } else {
10839 printf (" secondary UNAVAILABLE\n");
10840 }
10841
10842 if (mongoc_topology_description_has_writable_server (
10843 (mongoc_topology_description_t *) new_td)) {
10844 printf (" primary AVAILABLE\n");
10845 } else {
10846 printf (" primary UNAVAILABLE\n");
10847 }
10848
10849 mongoc_read_prefs_destroy (prefs);
10850 mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds);
10851 mongoc_server_descriptions_destroy_all (new_sds, n_new_sds);
10852 }
10853
10854
10855 static void
10856 topology_opening (const mongoc_apm_topology_opening_t *event)
10857 {
10858 stats_t *context;
10859
10860 context = (stats_t *) mongoc_apm_topology_opening_get_context (event);
10861 context->topology_opening_events++;
10862
10863 printf ("topology opening\n");
10864 }
10865
10866
10867 static void
10868 topology_closed (const mongoc_apm_topology_closed_t *event)
10869 {
10870 stats_t *context;
10871
10872 context = (stats_t *) mongoc_apm_topology_closed_get_context (event);
10873 context->topology_closed_events++;
10874
10875 printf ("topology closed\n");
10876 }
10877
10878
10879 static void
10880 server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event)
10881 {
10882 stats_t *context;
10883
10884 context =
10885 (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event);
10886 context->heartbeat_started_events++;
10887
10888 printf ("%s heartbeat started\n",
10889 mongoc_apm_server_heartbeat_started_get_host (event)->host_and_port);
10890 }
10891
10892
10893 static void
10894 server_heartbeat_succeeded (
10895 const mongoc_apm_server_heartbeat_succeeded_t *event)
10896 {
10897 stats_t *context;
10898 char *reply;
10899
10900 context =
10901 (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event);
10902 context->heartbeat_succeeded_events++;
10903
10904 reply = bson_as_canonical_extended_json (
10905 mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL);
10906
10907 printf (
10908 "%s heartbeat succeeded: %s\n",
10909 mongoc_apm_server_heartbeat_succeeded_get_host (event)->host_and_port,
10910 reply);
10911
10912 bson_free (reply);
10913 }
10914
10915
10916 static void
10917 server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event)
10918 {
10919 stats_t *context;
10920 bson_error_t error;
10921
10922 context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event);
10923 context->heartbeat_failed_events++;
10924 mongoc_apm_server_heartbeat_failed_get_error (event, &error);
10925
10926 printf ("%s heartbeat failed: %s\n",
10927 mongoc_apm_server_heartbeat_failed_get_host (event)->host_and_port,
10928 error.message);
10929 }
10930
10931
10932 int
10933 main (int argc, char *argv[])
10934 {
10935 mongoc_client_t *client;
10936 mongoc_apm_callbacks_t *cbs;
10937 stats_t stats = {0};
10938 const char *uri_string =
10939 "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
10940 mongoc_uri_t *uri;
10941 bson_t cmd = BSON_INITIALIZER;
10942 bson_t reply;
10943 bson_error_t error;
10944
10945 mongoc_init ();
10946
10947 if (argc > 1) {
10948 uri_string = argv[1];
10949 }
10950
10951 uri = mongoc_uri_new_with_error (uri_string, &error);
10952 if (!uri) {
10953 fprintf (stderr,
10954 "failed to parse URI: %s\n"
10955 "error message: %s\n",
10956 uri_string,
10957 error.message);
10958 return EXIT_FAILURE;
10959 }
10960
10961 client = mongoc_client_new_from_uri (uri);
10962 if (!client) {
10963 return EXIT_FAILURE;
10964 }
10965
10966 mongoc_client_set_error_api (client, 2);
10967 cbs = mongoc_apm_callbacks_new ();
10968 mongoc_apm_set_server_changed_cb (cbs, server_changed);
10969 mongoc_apm_set_server_opening_cb (cbs, server_opening);
10970 mongoc_apm_set_server_closed_cb (cbs, server_closed);
10971 mongoc_apm_set_topology_changed_cb (cbs, topology_changed);
10972 mongoc_apm_set_topology_opening_cb (cbs, topology_opening);
10973 mongoc_apm_set_topology_closed_cb (cbs, topology_closed);
10974 mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started);
10975 mongoc_apm_set_server_heartbeat_succeeded_cb (cbs,
10976 server_heartbeat_succeeded);
10977 mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed);
10978 mongoc_client_set_apm_callbacks (
10979 client, cbs, (void *) &stats /* context pointer */);
10980
10981 /* the driver connects on demand to perform first operation */
10982 BSON_APPEND_INT32 (&cmd, "buildinfo", 1);
10983 mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error);
10984 mongoc_uri_destroy (uri);
10985 mongoc_client_destroy (client);
10986
10987 printf ("Events:\n"
10988 " server changed: %d\n"
10989 " server opening: %d\n"
10990 " server closed: %d\n"
10991 " topology changed: %d\n"
10992 " topology opening: %d\n"
10993 " topology closed: %d\n"
10994 " heartbeat started: %d\n"
10995 " heartbeat succeeded: %d\n"
10996 " heartbeat failed: %d\n",
10997 stats.server_changed_events,
10998 stats.server_opening_events,
10999 stats.server_closed_events,
11000 stats.topology_changed_events,
11001 stats.topology_opening_events,
11002 stats.topology_closed_events,
11003 stats.heartbeat_started_events,
11004 stats.heartbeat_succeeded_events,
11005 stats.heartbeat_failed_events);
11006
11007 bson_destroy (&cmd);
11008 bson_destroy (&reply);
11009 mongoc_apm_callbacks_destroy (cbs);
11010
11011 mongoc_cleanup ();
11012
11013 return EXIT_SUCCESS;
11014 }
11015
11016
11017 Start a 3-node replica set on localhost with set name "rs" and start
11018 the program:
11019
11020 ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"
11021
11022 This example program prints something like:
11023
11024 topology opening
11025 topology changed: Unknown -> ReplicaSetNoPrimary
11026 secondary UNAVAILABLE
11027 primary UNAVAILABLE
11028 server opening: localhost:27017
11029 server opening: localhost:27018
11030 localhost:27017 heartbeat started
11031 localhost:27018 heartbeat started
11032 localhost:27017 heartbeat succeeded: { ... reply ... }
11033 server changed: localhost:27017 Unknown -> RSPrimary
11034 server opening: localhost:27019
11035 topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
11036 new servers:
11037 RSPrimary localhost:27017
11038 secondary UNAVAILABLE
11039 primary AVAILABLE
11040 localhost:27019 heartbeat started
11041 localhost:27018 heartbeat succeeded: { ... reply ... }
11042 server changed: localhost:27018 Unknown -> RSSecondary
11043 topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
11044 previous servers:
11045 RSPrimary localhost:27017
11046 new servers:
11047 RSPrimary localhost:27017
11048 RSSecondary localhost:27018
11049 secondary AVAILABLE
11050 primary AVAILABLE
11051 localhost:27019 heartbeat succeeded: { ... reply ... }
11052 server changed: localhost:27019 Unknown -> RSSecondary
11053 topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
11054 previous servers:
11055 RSPrimary localhost:27017
11056 RSSecondary localhost:27018
11057 new servers:
11058 RSPrimary localhost:27017
11059 RSSecondary localhost:27018
11060 RSSecondary localhost:27019
11061 secondary AVAILABLE
11062 primary AVAILABLE
11063 topology closed
11064
11065 Events:
11066 server changed: 3
11067 server opening: 3
11068 server closed: 0
11069 topology changed: 4
11070 topology opening: 1
11071 topology closed: 1
11072 heartbeat started: 3
11073 heartbeat succeeded: 3
11074 heartbeat failed: 0
11075
11076 The driver connects to the mongods on ports 27017 and 27018, which were
11077 specified in the URI, and determines which is primary. It also discov‐
11078 ers the third member, "localhost:27019", and adds it to the topology.
11079
11081 MongoDB, Inc
11082
11084 2017-present, MongoDB, Inc
11085
11086
11087
11088
110891.17.4 Feb 04, 2021 MONGOC_REFERENCE(3)