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 de‐
52 pendencies. One advantage of installing libmongoc with a package man‐
53 ager is that its dependencies (including libbson) will be installed au‐
54 tomatically. If you choose to install libmongoc from distribution pack‐
55 ages, use the package manager to confirm the version being installed is
56 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 in‐
76 stalled 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 be‐
136 yond 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 in‐
157 cluded 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.6/mongo-c-driver-1.17.6.tar.gz
169 $ tar xzf mongo-c-driver-1.17.6.tar.gz
170 $ cd mongo-c-driver-1.17.6
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.6/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.6 # 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.6
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 di‐
261 rectly 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 in‐
303 stalled. 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 Op‐
462 erations 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_collection_in‐
782 sert_one to add BSON documents to the collection. This example inserts
783 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_collection_up‐
964 date_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 "my‐
1190 coll" 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 op‐
1249 erations. 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 re‐
1369 port 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 op‐
1390 tion 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 in‐
1432 stallation path of libicu, specify ICU_ROOT as a cmake option. See the
1433 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 ap‐
1504 plication 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 au‐
1536 thentication 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 ad‐
1607 dress.
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 de‐
1639 velopers 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 de‐
1649 fault. 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 un‐ │
1747 │ │ │ lock encrypted Pri‐ │
1748 │ │ │ vate Key. │
1749 ├────────────────────┼─────────────────────┼─────────────────────┤
1750 │MON‐ │ tlscafile │ One, or a bundle │
1751 │GOC_URI_TLSCAFILE │ │ of, Certificate Au‐ │
1752 │ │ │ thorities 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 is‐ │
1775 │ │ │ sued 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 MONGOC_URI_TL‐ │
1786 │ │ │ SALLOWINVALIDHOST‐ │
1787 │ │ │ NAMES. │
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 re‐ │
1797 │POINTCHECK │ │ sponder endpoints │
1798 │ │ │ should not be re‐ │
1799 │ │ │ quested 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 au‐
1833 thority specified by --tlsCAFile, or an authority trusted by the native
1834 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 po‐
1862 tentially 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 re‐
1908 vokes the server's certificate, the certificate is considered revoked
1909 (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 li‐
1915 bressl.
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 re‐
1967 vokes 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.) na‐
1977 tive 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 Tu‐
2301 torial. To establish a connection with authentication options enabled,
2302 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 ad‐
2378 dress 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 at‐
2385 tempted 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 op‐
2441 tions.
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 re‐ │ │
2479 │ │ main 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 ac‐ │ │
2488 │ │ knowledgement, be‐ │ │
2489 │ │ fore 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 re‐
2523 sponded 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 un‐
2568 blocked 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 oc‐
2612 curred. See the following example for how to robustly check for errors.
2613
2614 static void
2615 print_all_documents (mongoc_collection_t *collection)
2616 {
2617 mongoc_cursor_t *cursor;
2618 const bson_t *doc;
2619 bson_error_t error;
2620 bson_t query = BSON_INITIALIZER;
2621 char *str;
2622
2623 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
2624
2625 while (mongoc_cursor_next (cursor, &doc)) {
2626 str = bson_as_canonical_extended_json (doc, NULL);
2627 printf ("%s\n", str);
2628 bson_free (str);
2629 }
2630
2631 if (mongoc_cursor_error (cursor, &error)) {
2632 fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
2633 }
2634
2635 mongoc_cursor_destroy (cursor);
2636 }
2637
2638 Destroying Server-Side Cursors
2639 The MongoDB C driver will automatically destroy a server-side cursor
2640 when mongoc_cursor_destroy() is called. Failure to call this function
2641 when done with a cursor will leak memory client side as well as consume
2642 extra memory server side. If the cursor was configured to never time‐
2643 out, it will become a memory leak on the server.
2644
2645 Tailable Cursors
2646 Tailable cursors are cursors that remain open even after they've re‐
2647 turned a final result. This way, if more documents are added to a col‐
2648 lection (i.e., to the cursor's result set), then you can continue to
2649 call mongoc_cursor_next() to retrieve those additional results.
2650
2651 Here's a complete test case that demonstrates the use of tailable cur‐
2652 sors.
2653
2654 NOTE:
2655 Tailable cursors are for capped collections only.
2656
2657 An example to tail the oplog from a replica set.
2658
2659 mongoc-tail.c
2660
2661 #include <bson/bson.h>
2662 #include <mongoc/mongoc.h>
2663 #include <stdio.h>
2664 #include <stdlib.h>
2665
2666 #ifdef _WIN32
2667 #define sleep(_n) Sleep ((_n) *1000)
2668 #endif
2669
2670
2671 static void
2672 print_bson (const bson_t *b)
2673 {
2674 char *str;
2675
2676 str = bson_as_canonical_extended_json (b, NULL);
2677 fprintf (stdout, "%s\n", str);
2678 bson_free (str);
2679 }
2680
2681
2682 static mongoc_cursor_t *
2683 query_collection (mongoc_collection_t *collection, uint32_t last_time)
2684 {
2685 mongoc_cursor_t *cursor;
2686 bson_t query;
2687 bson_t gt;
2688 bson_t opts;
2689
2690 BSON_ASSERT (collection);
2691
2692 bson_init (&query);
2693 BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", >);
2694 BSON_APPEND_TIMESTAMP (>, "$gt", last_time, 0);
2695 bson_append_document_end (&query, >);
2696
2697 bson_init (&opts);
2698 BSON_APPEND_BOOL (&opts, "tailable", true);
2699 BSON_APPEND_BOOL (&opts, "awaitData", true);
2700
2701 cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
2702
2703 bson_destroy (&query);
2704 bson_destroy (&opts);
2705
2706 return cursor;
2707 }
2708
2709
2710 static void
2711 tail_collection (mongoc_collection_t *collection)
2712 {
2713 mongoc_cursor_t *cursor;
2714 uint32_t last_time;
2715 const bson_t *doc;
2716 bson_error_t error;
2717 bson_iter_t iter;
2718
2719 BSON_ASSERT (collection);
2720
2721 last_time = (uint32_t) time (NULL);
2722
2723 while (true) {
2724 cursor = query_collection (collection, last_time);
2725 while (!mongoc_cursor_error (cursor, &error) &&
2726 mongoc_cursor_more (cursor)) {
2727 if (mongoc_cursor_next (cursor, &doc)) {
2728 if (bson_iter_init_find (&iter, doc, "ts") &&
2729 BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
2730 bson_iter_timestamp (&iter, &last_time, NULL);
2731 }
2732 print_bson (doc);
2733 }
2734 }
2735 if (mongoc_cursor_error (cursor, &error)) {
2736 if (error.domain == MONGOC_ERROR_SERVER) {
2737 fprintf (stderr, "%s\n", error.message);
2738 exit (1);
2739 }
2740 }
2741
2742 mongoc_cursor_destroy (cursor);
2743 sleep (1);
2744 }
2745 }
2746
2747
2748 int
2749 main (int argc, char *argv[])
2750 {
2751 mongoc_collection_t *collection;
2752 mongoc_client_t *client;
2753 mongoc_uri_t *uri;
2754 bson_error_t error;
2755
2756 if (argc != 2) {
2757 fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
2758 return EXIT_FAILURE;
2759 }
2760
2761 mongoc_init ();
2762
2763 uri = mongoc_uri_new_with_error (argv[1], &error);
2764 if (!uri) {
2765 fprintf (stderr,
2766 "failed to parse URI: %s\n"
2767 "error message: %s\n",
2768 argv[1],
2769 error.message);
2770 return EXIT_FAILURE;
2771 }
2772
2773 client = mongoc_client_new_from_uri (uri);
2774 if (!client) {
2775 return EXIT_FAILURE;
2776 }
2777
2778 mongoc_client_set_error_api (client, 2);
2779
2780 collection = mongoc_client_get_collection (client, "local", "oplog.rs");
2781
2782 tail_collection (collection);
2783
2784 mongoc_collection_destroy (collection);
2785 mongoc_uri_destroy (uri);
2786 mongoc_client_destroy (client);
2787
2788 return EXIT_SUCCESS;
2789 }
2790
2791
2792 Let's compile and run this example against a replica set to see updates
2793 as they are made.
2794
2795 $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
2796 $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
2797 {
2798 "h" : -8458503739429355503,
2799 "ns" : "test.test",
2800 "o" : {
2801 "_id" : {
2802 "$oid" : "5372ab0a25164be923d10d50"
2803 }
2804 },
2805 "op" : "i",
2806 "ts" : {
2807 "$timestamp" : {
2808 "i" : 1,
2809 "t" : 1400023818
2810 }
2811 },
2812 "v" : 2
2813 }
2814
2815 The line of output is a sample from performing db.test.insert({}) from
2816 the mongo shell on the replica set.
2817
2818 See also mongoc_cursor_set_max_await_time_ms.
2819
2820 Bulk Write Operations
2821 This tutorial explains how to take advantage of MongoDB C driver bulk
2822 write operation features. Executing write operations in batches reduces
2823 the number of network round trips, increasing write throughput.
2824
2825 Bulk Insert
2826 First we need to fetch a bulk operation handle from the mongoc_collec‐
2827 tion_t.
2828
2829 mongoc_bulk_operation_t *bulk =
2830 mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2831
2832 We can now start inserting documents to the bulk operation. These will
2833 be buffered until we execute the operation.
2834
2835 The bulk operation will coalesce insertions as a single batch for each
2836 consecutive call to mongoc_bulk_operation_insert(). This creates a
2837 pipelined effect when possible.
2838
2839 To execute the bulk operation and receive the result we call mon‐
2840 goc_bulk_operation_execute().
2841
2842 bulk1.c
2843
2844 #include <assert.h>
2845 #include <mongoc/mongoc.h>
2846 #include <stdio.h>
2847
2848 static void
2849 bulk1 (mongoc_collection_t *collection)
2850 {
2851 mongoc_bulk_operation_t *bulk;
2852 bson_error_t error;
2853 bson_t *doc;
2854 bson_t reply;
2855 char *str;
2856 bool ret;
2857 int i;
2858
2859 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2860
2861 for (i = 0; i < 10000; i++) {
2862 doc = BCON_NEW ("i", BCON_INT32 (i));
2863 mongoc_bulk_operation_insert (bulk, doc);
2864 bson_destroy (doc);
2865 }
2866
2867 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2868
2869 str = bson_as_canonical_extended_json (&reply, NULL);
2870 printf ("%s\n", str);
2871 bson_free (str);
2872
2873 if (!ret) {
2874 fprintf (stderr, "Error: %s\n", error.message);
2875 }
2876
2877 bson_destroy (&reply);
2878 mongoc_bulk_operation_destroy (bulk);
2879 }
2880
2881 int
2882 main (int argc, char *argv[])
2883 {
2884 mongoc_client_t *client;
2885 mongoc_collection_t *collection;
2886 const char *uri_string = "mongodb://localhost/?appname=bulk1-example";
2887 mongoc_uri_t *uri;
2888 bson_error_t error;
2889
2890 mongoc_init ();
2891
2892 uri = mongoc_uri_new_with_error (uri_string, &error);
2893 if (!uri) {
2894 fprintf (stderr,
2895 "failed to parse URI: %s\n"
2896 "error message: %s\n",
2897 uri_string,
2898 error.message);
2899 return EXIT_FAILURE;
2900 }
2901
2902 client = mongoc_client_new_from_uri (uri);
2903 if (!client) {
2904 return EXIT_FAILURE;
2905 }
2906
2907 mongoc_client_set_error_api (client, 2);
2908 collection = mongoc_client_get_collection (client, "test", "test");
2909
2910 bulk1 (collection);
2911
2912 mongoc_uri_destroy (uri);
2913 mongoc_collection_destroy (collection);
2914 mongoc_client_destroy (client);
2915
2916 mongoc_cleanup ();
2917
2918 return EXIT_SUCCESS;
2919 }
2920
2921
2922 Example reply document:
2923
2924 {"nInserted" : 10000,
2925 "nMatched" : 0,
2926 "nModified" : 0,
2927 "nRemoved" : 0,
2928 "nUpserted" : 0,
2929 "writeErrors" : []
2930 "writeConcernErrors" : [] }
2931
2932 Mixed Bulk Write Operations
2933 MongoDB C driver also supports executing mixed bulk write operations. A
2934 batch of insert, update, and remove operations can be executed together
2935 using the bulk write operations API.
2936
2937 Ordered Bulk Write Operations
2938 Ordered bulk write operations are batched and sent to the server in the
2939 order provided for serial execution. The reply document describes the
2940 type and count of operations performed.
2941
2942 bulk2.c
2943
2944 #include <assert.h>
2945 #include <mongoc/mongoc.h>
2946 #include <stdio.h>
2947
2948 static void
2949 bulk2 (mongoc_collection_t *collection)
2950 {
2951 mongoc_bulk_operation_t *bulk;
2952 bson_error_t error;
2953 bson_t *query;
2954 bson_t *doc;
2955 bson_t *opts;
2956 bson_t reply;
2957 char *str;
2958 bool ret;
2959 int i;
2960
2961 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2962
2963 /* Remove everything */
2964 query = bson_new ();
2965 mongoc_bulk_operation_remove (bulk, query);
2966 bson_destroy (query);
2967
2968 /* Add a few documents */
2969 for (i = 1; i < 4; i++) {
2970 doc = BCON_NEW ("_id", BCON_INT32 (i));
2971 mongoc_bulk_operation_insert (bulk, doc);
2972 bson_destroy (doc);
2973 }
2974
2975 /* {_id: 1} => {$set: {foo: "bar"}} */
2976 query = BCON_NEW ("_id", BCON_INT32 (1));
2977 doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
2978 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
2979 bson_destroy (query);
2980 bson_destroy (doc);
2981
2982 /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
2983 opts = BCON_NEW ("upsert", BCON_BOOL (true));
2984 query = BCON_NEW ("_id", BCON_INT32 (4));
2985 doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
2986 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
2987 bson_destroy (query);
2988 bson_destroy (doc);
2989 bson_destroy (opts);
2990
2991 /* replace {j:1} with {j:2} */
2992 query = BCON_NEW ("j", BCON_INT32 (1));
2993 doc = BCON_NEW ("j", BCON_INT32 (2));
2994 mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
2995 bson_destroy (query);
2996 bson_destroy (doc);
2997
2998 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2999
3000 str = bson_as_canonical_extended_json (&reply, NULL);
3001 printf ("%s\n", str);
3002 bson_free (str);
3003
3004 if (!ret) {
3005 printf ("Error: %s\n", error.message);
3006 }
3007
3008 bson_destroy (&reply);
3009 mongoc_bulk_operation_destroy (bulk);
3010 }
3011
3012 int
3013 main (int argc, char *argv[])
3014 {
3015 mongoc_client_t *client;
3016 mongoc_collection_t *collection;
3017 const char *uri_string = "mongodb://localhost/?appname=bulk2-example";
3018 mongoc_uri_t *uri;
3019 bson_error_t error;
3020
3021 mongoc_init ();
3022
3023 uri = mongoc_uri_new_with_error (uri_string, &error);
3024 if (!uri) {
3025 fprintf (stderr,
3026 "failed to parse URI: %s\n"
3027 "error message: %s\n",
3028 uri_string,
3029 error.message);
3030 return EXIT_FAILURE;
3031 }
3032
3033 client = mongoc_client_new_from_uri (uri);
3034 if (!client) {
3035 return EXIT_FAILURE;
3036 }
3037
3038 mongoc_client_set_error_api (client, 2);
3039 collection = mongoc_client_get_collection (client, "test", "test");
3040
3041 bulk2 (collection);
3042
3043 mongoc_uri_destroy (uri);
3044 mongoc_collection_destroy (collection);
3045 mongoc_client_destroy (client);
3046
3047 mongoc_cleanup ();
3048
3049 return EXIT_SUCCESS;
3050 }
3051
3052
3053 Example reply document:
3054
3055 { "nInserted" : 3,
3056 "nMatched" : 2,
3057 "nModified" : 2,
3058 "nRemoved" : 10000,
3059 "nUpserted" : 1,
3060 "upserted" : [{"index" : 5, "_id" : 4}],
3061 "writeErrors" : []
3062 "writeConcernErrors" : [] }
3063
3064 The index field in the upserted array is the 0-based index of the up‐
3065 sert operation; in this example, the sixth operation of the overall
3066 bulk operation was an upsert, so its index is 5.
3067
3068 Unordered Bulk Write Operations
3069 Unordered bulk write operations are batched and sent to the server in
3070 arbitrary order where they may be executed in parallel. Any errors that
3071 occur are reported after all operations are attempted.
3072
3073 In the next example the first and third operations fail due to the
3074 unique constraint on _id. Since we are doing unordered execution the
3075 second and fourth operations succeed.
3076
3077 bulk3.c
3078
3079 #include <assert.h>
3080 #include <mongoc/mongoc.h>
3081 #include <stdio.h>
3082
3083 static void
3084 bulk3 (mongoc_collection_t *collection)
3085 {
3086 bson_t opts = BSON_INITIALIZER;
3087 mongoc_bulk_operation_t *bulk;
3088 bson_error_t error;
3089 bson_t *query;
3090 bson_t *doc;
3091 bson_t reply;
3092 char *str;
3093 bool ret;
3094
3095 /* false indicates unordered */
3096 BSON_APPEND_BOOL (&opts, "ordered", false);
3097 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3098 bson_destroy (&opts);
3099
3100 /* Add a document */
3101 doc = BCON_NEW ("_id", BCON_INT32 (1));
3102 mongoc_bulk_operation_insert (bulk, doc);
3103 bson_destroy (doc);
3104
3105 /* remove {_id: 2} */
3106 query = BCON_NEW ("_id", BCON_INT32 (2));
3107 mongoc_bulk_operation_remove_one (bulk, query);
3108 bson_destroy (query);
3109
3110 /* insert {_id: 3} */
3111 doc = BCON_NEW ("_id", BCON_INT32 (3));
3112 mongoc_bulk_operation_insert (bulk, doc);
3113 bson_destroy (doc);
3114
3115 /* replace {_id:4} {'i': 1} */
3116 query = BCON_NEW ("_id", BCON_INT32 (4));
3117 doc = BCON_NEW ("i", BCON_INT32 (1));
3118 mongoc_bulk_operation_replace_one (bulk, query, doc, false);
3119 bson_destroy (query);
3120 bson_destroy (doc);
3121
3122 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3123
3124 str = bson_as_canonical_extended_json (&reply, NULL);
3125 printf ("%s\n", str);
3126 bson_free (str);
3127
3128 if (!ret) {
3129 printf ("Error: %s\n", error.message);
3130 }
3131
3132 bson_destroy (&reply);
3133 mongoc_bulk_operation_destroy (bulk);
3134 bson_destroy (&opts);
3135 }
3136
3137 int
3138 main (int argc, char *argv[])
3139 {
3140 mongoc_client_t *client;
3141 mongoc_collection_t *collection;
3142 const char *uri_string = "mongodb://localhost/?appname=bulk3-example";
3143 mongoc_uri_t *uri;
3144 bson_error_t error;
3145
3146 mongoc_init ();
3147
3148 uri = mongoc_uri_new_with_error (uri_string, &error);
3149 if (!uri) {
3150 fprintf (stderr,
3151 "failed to parse URI: %s\n"
3152 "error message: %s\n",
3153 uri_string,
3154 error.message);
3155 return EXIT_FAILURE;
3156 }
3157
3158 client = mongoc_client_new_from_uri (uri);
3159 if (!client) {
3160 return EXIT_FAILURE;
3161 }
3162
3163 mongoc_client_set_error_api (client, 2);
3164 collection = mongoc_client_get_collection (client, "test", "test");
3165
3166 bulk3 (collection);
3167
3168 mongoc_uri_destroy (uri);
3169 mongoc_collection_destroy (collection);
3170 mongoc_client_destroy (client);
3171
3172 mongoc_cleanup ();
3173
3174 return EXIT_SUCCESS;
3175 }
3176
3177
3178 Example reply document:
3179
3180 { "nInserted" : 0,
3181 "nMatched" : 1,
3182 "nModified" : 1,
3183 "nRemoved" : 1,
3184 "nUpserted" : 0,
3185 "writeErrors" : [
3186 { "index" : 0,
3187 "code" : 11000,
3188 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
3189 { "index" : 2,
3190 "code" : 11000,
3191 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
3192 "writeConcernErrors" : [] }
3193
3194 Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }
3195
3196 The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.
3197
3198 Bulk Operation Bypassing Document Validation
3199 This feature is only available when using MongoDB 3.2 and later.
3200
3201 By default bulk operations are validated against the schema, if any is
3202 defined. In certain cases however it may be necessary to bypass the
3203 document validation.
3204
3205 bulk5.c
3206
3207 #include <assert.h>
3208 #include <mongoc/mongoc.h>
3209 #include <stdio.h>
3210
3211 static void
3212 bulk5_fail (mongoc_collection_t *collection)
3213 {
3214 mongoc_bulk_operation_t *bulk;
3215 bson_error_t error;
3216 bson_t *doc;
3217 bson_t reply;
3218 char *str;
3219 bool ret;
3220
3221 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3222
3223 /* Two inserts */
3224 doc = BCON_NEW ("_id", BCON_INT32 (31));
3225 mongoc_bulk_operation_insert (bulk, doc);
3226 bson_destroy (doc);
3227
3228 doc = BCON_NEW ("_id", BCON_INT32 (32));
3229 mongoc_bulk_operation_insert (bulk, doc);
3230 bson_destroy (doc);
3231
3232 /* The above documents do not comply to the schema validation rules
3233 * we created previously, so this will result in an error */
3234 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3235
3236 str = bson_as_canonical_extended_json (&reply, NULL);
3237 printf ("%s\n", str);
3238 bson_free (str);
3239
3240 if (!ret) {
3241 printf ("Error: %s\n", error.message);
3242 }
3243
3244 bson_destroy (&reply);
3245 mongoc_bulk_operation_destroy (bulk);
3246 }
3247
3248 static void
3249 bulk5_success (mongoc_collection_t *collection)
3250 {
3251 mongoc_bulk_operation_t *bulk;
3252 bson_error_t error;
3253 bson_t *doc;
3254 bson_t reply;
3255 char *str;
3256 bool ret;
3257
3258 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3259
3260 /* Allow this document to bypass document validation.
3261 * NOTE: When authentication is enabled, the authenticated user must have
3262 * either the "dbadmin" or "restore" roles to bypass document validation */
3263 mongoc_bulk_operation_set_bypass_document_validation (bulk, true);
3264
3265 /* Two inserts */
3266 doc = BCON_NEW ("_id", BCON_INT32 (31));
3267 mongoc_bulk_operation_insert (bulk, doc);
3268 bson_destroy (doc);
3269
3270 doc = BCON_NEW ("_id", BCON_INT32 (32));
3271 mongoc_bulk_operation_insert (bulk, doc);
3272 bson_destroy (doc);
3273
3274 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3275
3276 str = bson_as_canonical_extended_json (&reply, NULL);
3277 printf ("%s\n", str);
3278 bson_free (str);
3279
3280 if (!ret) {
3281 printf ("Error: %s\n", error.message);
3282 }
3283
3284 bson_destroy (&reply);
3285 mongoc_bulk_operation_destroy (bulk);
3286 }
3287
3288 int
3289 main (int argc, char *argv[])
3290 {
3291 bson_t *options;
3292 bson_error_t error;
3293 mongoc_client_t *client;
3294 mongoc_collection_t *collection;
3295 mongoc_database_t *database;
3296 const char *uri_string = "mongodb://localhost/?appname=bulk5-example";
3297 mongoc_uri_t *uri;
3298
3299 mongoc_init ();
3300
3301 uri = mongoc_uri_new_with_error (uri_string, &error);
3302 if (!uri) {
3303 fprintf (stderr,
3304 "failed to parse URI: %s\n"
3305 "error message: %s\n",
3306 uri_string,
3307 error.message);
3308 return EXIT_FAILURE;
3309 }
3310
3311 client = mongoc_client_new_from_uri (uri);
3312 if (!client) {
3313 return EXIT_FAILURE;
3314 }
3315
3316 mongoc_client_set_error_api (client, 2);
3317 database = mongoc_client_get_database (client, "testasdf");
3318
3319 /* Create schema validator */
3320 options = BCON_NEW (
3321 "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
3322 collection =
3323 mongoc_database_create_collection (database, "collname", options, &error);
3324
3325 if (collection) {
3326 bulk5_fail (collection);
3327 bulk5_success (collection);
3328 mongoc_collection_destroy (collection);
3329 } else {
3330 fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
3331 }
3332
3333 bson_free (options);
3334 mongoc_uri_destroy (uri);
3335 mongoc_database_destroy (database);
3336 mongoc_client_destroy (client);
3337
3338 mongoc_cleanup ();
3339
3340 return EXIT_SUCCESS;
3341 }
3342
3343
3344 Running the above example will result in:
3345
3346 { "nInserted" : 0,
3347 "nMatched" : 0,
3348 "nModified" : 0,
3349 "nRemoved" : 0,
3350 "nUpserted" : 0,
3351 "writeErrors" : [
3352 { "index" : 0,
3353 "code" : 121,
3354 "errmsg" : "Document failed validation" } ] }
3355
3356 Error: Document failed validation
3357
3358 { "nInserted" : 2,
3359 "nMatched" : 0,
3360 "nModified" : 0,
3361 "nRemoved" : 0,
3362 "nUpserted" : 0,
3363 "writeErrors" : [] }
3364
3365 The bson_error_t domain is MONGOC_ERROR_COMMAND.
3366
3367 Bulk Operation Write Concerns
3368 By default bulk operations are executed with the write_concern of the
3369 collection they are executed against. A custom write concern can be
3370 passed to the mongoc_collection_create_bulk_operation_with_opts()
3371 method. Write concern errors (e.g. wtimeout) will be reported after all
3372 operations are attempted, regardless of execution order.
3373
3374 bulk4.c
3375
3376 #include <assert.h>
3377 #include <mongoc/mongoc.h>
3378 #include <stdio.h>
3379
3380 static void
3381 bulk4 (mongoc_collection_t *collection)
3382 {
3383 bson_t opts = BSON_INITIALIZER;
3384 mongoc_write_concern_t *wc;
3385 mongoc_bulk_operation_t *bulk;
3386 bson_error_t error;
3387 bson_t *doc;
3388 bson_t reply;
3389 char *str;
3390 bool ret;
3391
3392 wc = mongoc_write_concern_new ();
3393 mongoc_write_concern_set_w (wc, 4);
3394 mongoc_write_concern_set_wtimeout_int64 (wc, 100); /* milliseconds */
3395 mongoc_write_concern_append (wc, &opts);
3396
3397 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3398
3399 /* Two inserts */
3400 doc = BCON_NEW ("_id", BCON_INT32 (10));
3401 mongoc_bulk_operation_insert (bulk, doc);
3402 bson_destroy (doc);
3403
3404 doc = BCON_NEW ("_id", BCON_INT32 (11));
3405 mongoc_bulk_operation_insert (bulk, doc);
3406 bson_destroy (doc);
3407
3408 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3409
3410 str = bson_as_canonical_extended_json (&reply, NULL);
3411 printf ("%s\n", str);
3412 bson_free (str);
3413
3414 if (!ret) {
3415 printf ("Error: %s\n", error.message);
3416 }
3417
3418 bson_destroy (&reply);
3419 mongoc_bulk_operation_destroy (bulk);
3420 mongoc_write_concern_destroy (wc);
3421 bson_destroy (&opts);
3422 }
3423
3424 int
3425 main (int argc, char *argv[])
3426 {
3427 mongoc_client_t *client;
3428 mongoc_collection_t *collection;
3429 const char *uri_string = "mongodb://localhost/?appname=bulk4-example";
3430 mongoc_uri_t *uri;
3431 bson_error_t error;
3432
3433 mongoc_init ();
3434
3435 uri = mongoc_uri_new_with_error (uri_string, &error);
3436 if (!uri) {
3437 fprintf (stderr,
3438 "failed to parse URI: %s\n"
3439 "error message: %s\n",
3440 uri_string,
3441 error.message);
3442 return EXIT_FAILURE;
3443 }
3444
3445 client = mongoc_client_new_from_uri (uri);
3446 if (!client) {
3447 return EXIT_FAILURE;
3448 }
3449
3450 mongoc_client_set_error_api (client, 2);
3451 collection = mongoc_client_get_collection (client, "test", "test");
3452
3453 bulk4 (collection);
3454
3455 mongoc_uri_destroy (uri);
3456 mongoc_collection_destroy (collection);
3457 mongoc_client_destroy (client);
3458
3459 mongoc_cleanup ();
3460
3461 return EXIT_SUCCESS;
3462 }
3463
3464
3465 Example reply document and error message:
3466
3467 { "nInserted" : 2,
3468 "nMatched" : 0,
3469 "nModified" : 0,
3470 "nRemoved" : 0,
3471 "nUpserted" : 0,
3472 "writeErrors" : [],
3473 "writeConcernErrors" : [
3474 { "code" : 64,
3475 "errmsg" : "waiting for replication timed out" }
3476 ] }
3477
3478 Error: waiting for replication timed out
3479
3480 The bson_error_t domain is MONGOC_ERROR_WRITE_CONCERN if there are
3481 write concern errors and no write errors. Write errors indicate failed
3482 operations, so they take precedence over write concern errors, which
3483 mean merely that the write concern is not satisfied yet.
3484
3485 Setting Collation Order
3486 This feature is only available when using MongoDB 3.4 and later.
3487
3488 bulk-collation.c
3489
3490 #include <mongoc/mongoc.h>
3491 #include <stdio.h>
3492
3493 static void
3494 bulk_collation (mongoc_collection_t *collection)
3495 {
3496 mongoc_bulk_operation_t *bulk;
3497 bson_t *opts;
3498 bson_t *doc;
3499 bson_t *selector;
3500 bson_t *update;
3501 bson_error_t error;
3502 bson_t reply;
3503 char *str;
3504 uint32_t ret;
3505
3506 /* insert {_id: "one"} and {_id: "One"} */
3507 bulk = mongoc_collection_create_bulk_operation_with_opts (
3508 collection, NULL);
3509 doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
3510 mongoc_bulk_operation_insert (bulk, doc);
3511 bson_destroy (doc);
3512
3513 doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
3514 mongoc_bulk_operation_insert (bulk, doc);
3515 bson_destroy (doc);
3516
3517 /* "One" normally sorts before "one"; make "one" come first */
3518 opts = BCON_NEW ("collation",
3519 "{",
3520 "locale",
3521 BCON_UTF8 ("en_US"),
3522 "caseFirst",
3523 BCON_UTF8 ("lower"),
3524 "}");
3525
3526 /* set x=1 on the document with _id "One", which now sorts after "one" */
3527 update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
3528 selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
3529 mongoc_bulk_operation_update_one_with_opts (
3530 bulk, selector, update, opts, &error);
3531
3532 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3533
3534 str = bson_as_canonical_extended_json (&reply, NULL);
3535 printf ("%s\n", str);
3536 bson_free (str);
3537
3538 if (!ret) {
3539 printf ("Error: %s\n", error.message);
3540 }
3541
3542 bson_destroy (&reply);
3543 bson_destroy (update);
3544 bson_destroy (selector);
3545 bson_destroy (opts);
3546 mongoc_bulk_operation_destroy (bulk);
3547 }
3548
3549 int
3550 main (int argc, char *argv[])
3551 {
3552 mongoc_client_t *client;
3553 mongoc_collection_t *collection;
3554 const char *uri_string = "mongodb://localhost/?appname=bulk-collation";
3555 mongoc_uri_t *uri;
3556 bson_error_t error;
3557
3558 mongoc_init ();
3559
3560 uri = mongoc_uri_new_with_error (uri_string, &error);
3561 if (!uri) {
3562 fprintf (stderr,
3563 "failed to parse URI: %s\n"
3564 "error message: %s\n",
3565 uri_string,
3566 error.message);
3567 return EXIT_FAILURE;
3568 }
3569
3570 client = mongoc_client_new_from_uri (uri);
3571 if (!client) {
3572 return EXIT_FAILURE;
3573 }
3574
3575 mongoc_client_set_error_api (client, 2);
3576 collection = mongoc_client_get_collection (client, "db", "collection");
3577 bulk_collation (collection);
3578
3579 mongoc_uri_destroy (uri);
3580 mongoc_collection_destroy (collection);
3581 mongoc_client_destroy (client);
3582
3583 mongoc_cleanup ();
3584
3585 return EXIT_SUCCESS;
3586 }
3587
3588
3589 Running the above example will result in:
3590
3591 { "nInserted" : 2,
3592 "nMatched" : 1,
3593 "nModified" : 1,
3594 "nRemoved" : 0,
3595 "nUpserted" : 0,
3596 "writeErrors" : [ ]
3597 }
3598
3599 Unacknowledged Bulk Writes
3600 Set "w" to zero for an unacknowledged write. The driver sends unac‐
3601 knowledged writes using the legacy opcodes OP_INSERT, OP_UPDATE, and
3602 OP_DELETE.
3603
3604 bulk6.c
3605
3606 #include <mongoc/mongoc.h>
3607 #include <stdio.h>
3608
3609 static void
3610 bulk6 (mongoc_collection_t *collection)
3611 {
3612 bson_t opts = BSON_INITIALIZER;
3613 mongoc_write_concern_t *wc;
3614 mongoc_bulk_operation_t *bulk;
3615 bson_error_t error;
3616 bson_t *doc;
3617 bson_t *selector;
3618 bson_t reply;
3619 char *str;
3620 bool ret;
3621
3622 wc = mongoc_write_concern_new ();
3623 mongoc_write_concern_set_w (wc, 0);
3624 mongoc_write_concern_append (wc, &opts);
3625
3626 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3627
3628 doc = BCON_NEW ("_id", BCON_INT32 (10));
3629 mongoc_bulk_operation_insert (bulk, doc);
3630 bson_destroy (doc);
3631
3632 selector = BCON_NEW ("_id", BCON_INT32 (11));
3633 mongoc_bulk_operation_remove_one (bulk, selector);
3634 bson_destroy (selector);
3635
3636 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3637
3638 str = bson_as_canonical_extended_json (&reply, NULL);
3639 printf ("%s\n", str);
3640 bson_free (str);
3641
3642 if (!ret) {
3643 printf ("Error: %s\n", error.message);
3644 }
3645
3646 bson_destroy (&reply);
3647 mongoc_bulk_operation_destroy (bulk);
3648 mongoc_write_concern_destroy (wc);
3649 bson_destroy (&opts);
3650 }
3651
3652 int
3653 main (int argc, char *argv[])
3654 {
3655 mongoc_client_t *client;
3656 mongoc_collection_t *collection;
3657 const char *uri_string = "mongodb://localhost/?appname=bulk6-example";
3658 mongoc_uri_t *uri;
3659 bson_error_t error;
3660
3661 mongoc_init ();
3662
3663 uri = mongoc_uri_new_with_error (uri_string, &error);
3664 if (!uri) {
3665 fprintf (stderr,
3666 "failed to parse URI: %s\n"
3667 "error message: %s\n",
3668 uri_string,
3669 error.message);
3670 return EXIT_FAILURE;
3671 }
3672
3673 client = mongoc_client_new_from_uri (uri);
3674 if (!client) {
3675 return EXIT_FAILURE;
3676 }
3677
3678 mongoc_client_set_error_api (client, 2);
3679 collection = mongoc_client_get_collection (client, "test", "test");
3680
3681 bulk6 (collection);
3682
3683 mongoc_uri_destroy (uri);
3684 mongoc_collection_destroy (collection);
3685 mongoc_client_destroy (client);
3686
3687 mongoc_cleanup ();
3688
3689 return EXIT_SUCCESS;
3690 }
3691
3692
3693 The reply document is empty:
3694
3695 { }
3696
3697 Further Reading
3698 See the Driver Bulk API Spec, which describes bulk write operations for
3699 all MongoDB drivers.
3700
3701 Aggregation Framework Examples
3702 This document provides a number of practical examples that display the
3703 capabilities of the aggregation framework.
3704
3705 The Aggregations using the Zip Codes Data Set examples uses a publicly
3706 available data set of all zipcodes and populations in the United
3707 States. These data are available at: zips.json.
3708
3709 Requirements
3710 Let's check if everything is installed.
3711
3712 Use the following command to load zips.json data set into mongod in‐
3713 stance:
3714
3715 $ mongoimport --drop -d test -c zipcodes zips.json
3716
3717 Let's use the MongoDB shell to verify that everything was imported suc‐
3718 cessfully.
3719
3720 $ mongo test
3721 connecting to: test
3722 > db.zipcodes.count()
3723 29467
3724 > db.zipcodes.findOne()
3725 {
3726 "_id" : "35004",
3727 "city" : "ACMAR",
3728 "loc" : [
3729 -86.51557,
3730 33.584132
3731 ],
3732 "pop" : 6055,
3733 "state" : "AL"
3734 }
3735
3736 Aggregations using the Zip Codes Data Set
3737 Each document in this collection has the following form:
3738
3739 {
3740 "_id" : "35004",
3741 "city" : "Acmar",
3742 "state" : "AL",
3743 "pop" : 6055,
3744 "loc" : [-86.51557, 33.584132]
3745 }
3746
3747 In these documents:
3748
3749 • The _id field holds the zipcode as a string.
3750
3751 • The city field holds the city name.
3752
3753 • The state field holds the two letter state abbreviation.
3754
3755 • The pop field holds the population.
3756
3757 • The loc field holds the location as a [latitude, longitude] array.
3758
3759 States with Populations Over 10 Million
3760 To get all states with a population greater than 10 million, use the
3761 following aggregation pipeline:
3762
3763 aggregation1.c
3764
3765 #include <mongoc/mongoc.h>
3766 #include <stdio.h>
3767
3768 static void
3769 print_pipeline (mongoc_collection_t *collection)
3770 {
3771 mongoc_cursor_t *cursor;
3772 bson_error_t error;
3773 const bson_t *doc;
3774 bson_t *pipeline;
3775 char *str;
3776
3777 pipeline = BCON_NEW ("pipeline",
3778 "[",
3779 "{",
3780 "$group",
3781 "{",
3782 "_id",
3783 "$state",
3784 "total_pop",
3785 "{",
3786 "$sum",
3787 "$pop",
3788 "}",
3789 "}",
3790 "}",
3791 "{",
3792 "$match",
3793 "{",
3794 "total_pop",
3795 "{",
3796 "$gte",
3797 BCON_INT32 (10000000),
3798 "}",
3799 "}",
3800 "}",
3801 "]");
3802
3803 cursor = mongoc_collection_aggregate (
3804 collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
3805
3806 while (mongoc_cursor_next (cursor, &doc)) {
3807 str = bson_as_canonical_extended_json (doc, NULL);
3808 printf ("%s\n", str);
3809 bson_free (str);
3810 }
3811
3812 if (mongoc_cursor_error (cursor, &error)) {
3813 fprintf (stderr, "Cursor Failure: %s\n", error.message);
3814 }
3815
3816 mongoc_cursor_destroy (cursor);
3817 bson_destroy (pipeline);
3818 }
3819
3820 int
3821 main (int argc, char *argv[])
3822 {
3823 mongoc_client_t *client;
3824 mongoc_collection_t *collection;
3825 const char *uri_string =
3826 "mongodb://localhost:27017/?appname=aggregation-example";
3827 mongoc_uri_t *uri;
3828 bson_error_t error;
3829
3830 mongoc_init ();
3831
3832 uri = mongoc_uri_new_with_error (uri_string, &error);
3833 if (!uri) {
3834 fprintf (stderr,
3835 "failed to parse URI: %s\n"
3836 "error message: %s\n",
3837 uri_string,
3838 error.message);
3839 return EXIT_FAILURE;
3840 }
3841
3842 client = mongoc_client_new_from_uri (uri);
3843 if (!client) {
3844 return EXIT_FAILURE;
3845 }
3846
3847 mongoc_client_set_error_api (client, 2);
3848 collection = mongoc_client_get_collection (client, "test", "zipcodes");
3849
3850 print_pipeline (collection);
3851
3852 mongoc_uri_destroy (uri);
3853 mongoc_collection_destroy (collection);
3854 mongoc_client_destroy (client);
3855
3856 mongoc_cleanup ();
3857
3858 return EXIT_SUCCESS;
3859 }
3860
3861
3862 You should see a result like the following:
3863
3864 { "_id" : "PA", "total_pop" : 11881643 }
3865 { "_id" : "OH", "total_pop" : 10847115 }
3866 { "_id" : "NY", "total_pop" : 17990455 }
3867 { "_id" : "FL", "total_pop" : 12937284 }
3868 { "_id" : "TX", "total_pop" : 16986510 }
3869 { "_id" : "IL", "total_pop" : 11430472 }
3870 { "_id" : "CA", "total_pop" : 29760021 }
3871
3872 The above aggregation pipeline is build from two pipeline operators:
3873 $group and $match.
3874
3875 The $group pipeline operator requires _id field where we specify group‐
3876 ing; remaining fields specify how to generate composite value and must
3877 use one of the group aggregation functions: $addToSet, $first, $last,
3878 $max, $min, $avg, $push, $sum. The $match pipeline operator syntax is
3879 the same as the read operation query syntax.
3880
3881 The $group process reads all documents and for each state it creates a
3882 separate document, for example:
3883
3884 { "_id" : "WA", "total_pop" : 4866692 }
3885
3886 The total_pop field uses the $sum aggregation function to sum the val‐
3887 ues of all pop fields in the source documents.
3888
3889 Documents created by $group are piped to the $match pipeline operator.
3890 It returns the documents with the value of total_pop field greater than
3891 or equal to 10 million.
3892
3893 Average City Population by State
3894 To get the first three states with the greatest average population per
3895 city, use the following aggregation:
3896
3897 pipeline = BCON_NEW ("pipeline", "[",
3898 "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
3899 "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
3900 "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
3901 "{", "$limit", BCON_INT32 (3) "}",
3902 "]");
3903
3904 This aggregate pipeline produces:
3905
3906 { "_id" : "DC", "avg_city_pop" : 303450.0 }
3907 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3908 { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
3909
3910 The above aggregation pipeline is build from three pipeline operators:
3911 $group, $sort and $limit.
3912
3913 The first $group operator creates the following documents:
3914
3915 { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
3916
3917 Note, that the $group operator can't use nested documents except the
3918 _id field.
3919
3920 The second $group uses these documents to create the following docu‐
3921 ments:
3922
3923 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3924
3925 These documents are sorted by the avg_city_pop field in descending or‐
3926 der. Finally, the $limit pipeline operator returns the first 3 docu‐
3927 ments from the sorted set.
3928
3929 distinct and mapReduce
3930 This document provides some practical, simple, examples to demonstrate
3931 the distinct and mapReduce commands.
3932
3933 Setup
3934 First we'll write some code to insert sample data:
3935
3936 doc-common-insert.c
3937
3938 /* Don't try to compile this file on its own. It's meant to be #included
3939 by example code */
3940
3941 /* Insert some sample data */
3942 bool
3943 insert_data (mongoc_collection_t *collection)
3944 {
3945 mongoc_bulk_operation_t *bulk;
3946 enum N { ndocs = 4 };
3947 bson_t *docs[ndocs];
3948 bson_error_t error;
3949 int i = 0;
3950 bool ret;
3951
3952 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3953
3954 docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
3955 docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
3956 docs[2] = BCON_NEW (
3957 "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
3958 docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
3959
3960 for (i = 0; i < ndocs; i++) {
3961 mongoc_bulk_operation_insert (bulk, docs[i]);
3962 bson_destroy (docs[i]);
3963 docs[i] = NULL;
3964 }
3965
3966 ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
3967
3968 if (!ret) {
3969 fprintf (stderr, "Error inserting data: %s\n", error.message);
3970 }
3971
3972 mongoc_bulk_operation_destroy (bulk);
3973 return ret;
3974 }
3975
3976 /* A helper which we'll use a lot later on */
3977 void
3978 print_res (const bson_t *reply)
3979 {
3980 char *str;
3981 BSON_ASSERT (reply);
3982 str = bson_as_canonical_extended_json (reply, NULL);
3983 printf ("%s\n", str);
3984 bson_free (str);
3985 }
3986
3987
3988 distinct command
3989 This is how to use the distinct command to get the distinct values of x
3990 which are greater than 1:
3991
3992 distinct.c
3993
3994 bool
3995 distinct (mongoc_database_t *database)
3996 {
3997 bson_t *command;
3998 bson_t reply;
3999 bson_error_t error;
4000 bool res;
4001 bson_iter_t iter;
4002 bson_iter_t array_iter;
4003 double val;
4004
4005 command = BCON_NEW ("distinct",
4006 BCON_UTF8 (COLLECTION_NAME),
4007 "key",
4008 BCON_UTF8 ("x"),
4009 "query",
4010 "{",
4011 "x",
4012 "{",
4013 "$gt",
4014 BCON_DOUBLE (1.0),
4015 "}",
4016 "}");
4017 res =
4018 mongoc_database_command_simple (database, command, NULL, &reply, &error);
4019 if (!res) {
4020 fprintf (stderr, "Error with distinct: %s\n", error.message);
4021 goto cleanup;
4022 }
4023
4024 /* Do something with reply (in this case iterate through the values) */
4025 if (!(bson_iter_init_find (&iter, &reply, "values") &&
4026 BSON_ITER_HOLDS_ARRAY (&iter) &&
4027 bson_iter_recurse (&iter, &array_iter))) {
4028 fprintf (stderr, "Couldn't extract \"values\" field from response\n");
4029 goto cleanup;
4030 }
4031
4032 while (bson_iter_next (&array_iter)) {
4033 if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
4034 val = bson_iter_double (&array_iter);
4035 printf ("Next double: %f\n", val);
4036 }
4037 }
4038
4039 cleanup:
4040 /* cleanup */
4041 bson_destroy (command);
4042 bson_destroy (&reply);
4043 return res;
4044 }
4045
4046
4047 mapReduce - basic example
4048 A simple example using the map reduce framework. It simply adds up the
4049 number of occurrences of each "tag".
4050
4051 First define the map and reduce functions:
4052
4053 constants.c
4054
4055 const char *const COLLECTION_NAME = "things";
4056
4057 /* Our map function just emits a single (key, 1) pair for each tag
4058 in the array: */
4059 const char *const MAPPER = "function () {"
4060 "this.tags.forEach(function(z) {"
4061 "emit(z, 1);"
4062 "});"
4063 "}";
4064
4065 /* The reduce function sums over all of the emitted values for a
4066 given key: */
4067 const char *const REDUCER = "function (key, values) {"
4068 "var total = 0;"
4069 "for (var i = 0; i < values.length; i++) {"
4070 "total += values[i];"
4071 "}"
4072 "return total;"
4073 "}";
4074 /* Note We can't just return values.length as the reduce function
4075 might be called iteratively on the results of other reduce
4076 steps. */
4077
4078
4079 Run the mapReduce command. Use the generic command helpers (e.g. mon‐
4080 goc_database_command_simple()). Do not the read command helpers (e.g.
4081 mongoc_database_read_command_with_opts()) because they are considered
4082 retryable read operations. If retryable reads are enabled, those opera‐
4083 tions will retry once on a retryable error, giving undesirable behavior
4084 for mapReduce.
4085
4086 map-reduce-basic.c
4087
4088 bool
4089 map_reduce_basic (mongoc_database_t *database)
4090 {
4091 bson_t reply;
4092 bson_t *command;
4093 bool res;
4094 bson_error_t error;
4095 mongoc_cursor_t *cursor;
4096 const bson_t *doc;
4097
4098 bool query_done = false;
4099
4100 const char *out_collection_name = "outCollection";
4101 mongoc_collection_t *out_collection;
4102
4103 /* Empty find query */
4104 bson_t find_query = BSON_INITIALIZER;
4105
4106 /* Construct the mapReduce command */
4107
4108 /* Other arguments can also be specified here, like "query" or
4109 "limit" and so on */
4110 command = BCON_NEW ("mapReduce",
4111 BCON_UTF8 (COLLECTION_NAME),
4112 "map",
4113 BCON_CODE (MAPPER),
4114 "reduce",
4115 BCON_CODE (REDUCER),
4116 "out",
4117 BCON_UTF8 (out_collection_name));
4118 res =
4119 mongoc_database_command_simple (database, command, NULL, &reply, &error);
4120
4121 if (!res) {
4122 fprintf (stderr, "MapReduce failed: %s\n", error.message);
4123 goto cleanup;
4124 }
4125
4126 /* Do something with the reply (it doesn't contain the mapReduce results) */
4127 print_res (&reply);
4128
4129 /* Now we'll query outCollection to see what the results are */
4130 out_collection =
4131 mongoc_database_get_collection (database, out_collection_name);
4132 cursor = mongoc_collection_find_with_opts (
4133 out_collection, &find_query, NULL, NULL);
4134 query_done = true;
4135
4136 /* Do something with the results */
4137 while (mongoc_cursor_next (cursor, &doc)) {
4138 print_res (doc);
4139 }
4140
4141 if (mongoc_cursor_error (cursor, &error)) {
4142 fprintf (stderr, "ERROR: %s\n", error.message);
4143 res = false;
4144 goto cleanup;
4145 }
4146
4147 cleanup:
4148 /* cleanup */
4149 if (query_done) {
4150 mongoc_cursor_destroy (cursor);
4151 mongoc_collection_destroy (out_collection);
4152 }
4153
4154 bson_destroy (&reply);
4155 bson_destroy (command);
4156
4157 return res;
4158 }
4159
4160
4161 mapReduce - more complicated example
4162 You must have replica set running for this.
4163
4164 In this example we contact a secondary in the replica set and do an
4165 "inline" map reduce, so the results are returned immediately:
4166
4167 map-reduce-advanced.c
4168
4169 bool
4170 map_reduce_advanced (mongoc_database_t *database)
4171 {
4172 bson_t *command;
4173 bson_error_t error;
4174 bool res = true;
4175 mongoc_cursor_t *cursor;
4176 mongoc_read_prefs_t *read_pref;
4177 const bson_t *doc;
4178
4179 /* Construct the mapReduce command */
4180 /* Other arguments can also be specified here, like "query" or "limit"
4181 and so on */
4182
4183 /* Read the results inline from a secondary replica */
4184 command = BCON_NEW ("mapReduce",
4185 BCON_UTF8 (COLLECTION_NAME),
4186 "map",
4187 BCON_CODE (MAPPER),
4188 "reduce",
4189 BCON_CODE (REDUCER),
4190 "out",
4191 "{",
4192 "inline",
4193 "1",
4194 "}");
4195
4196 read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
4197 cursor = mongoc_database_command (
4198 database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
4199
4200 /* Do something with the results */
4201 while (mongoc_cursor_next (cursor, &doc)) {
4202 print_res (doc);
4203 }
4204
4205 if (mongoc_cursor_error (cursor, &error)) {
4206 fprintf (stderr, "ERROR: %s\n", error.message);
4207 res = false;
4208 }
4209
4210 mongoc_cursor_destroy (cursor);
4211 mongoc_read_prefs_destroy (read_pref);
4212 bson_destroy (command);
4213
4214 return res;
4215 }
4216
4217
4218 Running the Examples
4219 Here's how to run the example code
4220
4221 basic-aggregation.c
4222
4223 /*
4224 * Copyright 2016 MongoDB, Inc.
4225 *
4226 * Licensed under the Apache License, Version 2.0 (the "License");
4227 * you may not use this file except in compliance with the License.
4228 * You may obtain a copy of the License at
4229 *
4230 * http://www.apache.org/licenses/LICENSE-2.0
4231 *
4232 * Unless required by applicable law or agreed to in writing, software
4233 * distributed under the License is distributed on an "AS IS" BASIS,
4234 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4235 * See the License for the specific language governing permissions and
4236 * limitations under the License.
4237 */
4238
4239
4240 #include <mongoc/mongoc.h>
4241 #include <stdio.h>
4242
4243
4244 #include "constants.c"
4245
4246 #include "../doc-common-insert.c"
4247 #include "distinct.c"
4248 #include "map-reduce-basic.c"
4249 #include "map-reduce-advanced.c"
4250
4251
4252 int
4253 main (int argc, char *argv[])
4254 {
4255 mongoc_database_t *database = NULL;
4256 mongoc_client_t *client = NULL;
4257 mongoc_collection_t *collection = NULL;
4258 mongoc_uri_t *uri = NULL;
4259 bson_error_t error;
4260 char *host_and_port = NULL;
4261 int exit_code = EXIT_FAILURE;
4262
4263 if (argc != 2) {
4264 fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
4265 fprintf (stderr,
4266 "the connection string can be of the following forms:\n");
4267 fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
4268 fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
4269 fprintf (stderr,
4270 "mongodb://user:pass@localhost:27017\t"
4271 "local machine on port 27017, and authenticate with username "
4272 "user and password pass\n");
4273 return exit_code;
4274 }
4275
4276 mongoc_init ();
4277
4278 if (strncmp (argv[1], "mongodb://", 10) == 0) {
4279 host_and_port = bson_strdup (argv[1]);
4280 } else {
4281 host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
4282 }
4283
4284 uri = mongoc_uri_new_with_error (host_and_port, &error);
4285 if (!uri) {
4286 fprintf (stderr,
4287 "failed to parse URI: %s\n"
4288 "error message: %s\n",
4289 host_and_port,
4290 error.message);
4291 goto cleanup;
4292 }
4293
4294 client = mongoc_client_new_from_uri (uri);
4295 if (!client) {
4296 goto cleanup;
4297 }
4298
4299 mongoc_client_set_error_api (client, 2);
4300 database = mongoc_client_get_database (client, "test");
4301 collection = mongoc_database_get_collection (database, COLLECTION_NAME);
4302
4303 printf ("Inserting data\n");
4304 if (!insert_data (collection)) {
4305 goto cleanup;
4306 }
4307
4308 printf ("distinct\n");
4309 if (!distinct (database)) {
4310 goto cleanup;
4311 }
4312
4313 printf ("map reduce\n");
4314 if (!map_reduce_basic (database)) {
4315 goto cleanup;
4316 }
4317
4318 printf ("more complicated map reduce\n");
4319 if (!map_reduce_advanced (database)) {
4320 goto cleanup;
4321 }
4322
4323 exit_code = EXIT_SUCCESS;
4324
4325 cleanup:
4326 if (collection) {
4327 mongoc_collection_destroy (collection);
4328 }
4329
4330 if (database) {
4331 mongoc_database_destroy (database);
4332 }
4333
4334 if (client) {
4335 mongoc_client_destroy (client);
4336 }
4337
4338 if (uri) {
4339 mongoc_uri_destroy (uri);
4340 }
4341
4342 if (host_and_port) {
4343 bson_free (host_and_port);
4344 }
4345
4346 mongoc_cleanup ();
4347 return exit_code;
4348 }
4349
4350
4351 If you want to try the advanced map reduce example with a secondary,
4352 start a replica set (instructions for how to do this can be found
4353 here).
4354
4355 Otherwise, just start an instance of MongoDB:
4356
4357 $ mongod
4358
4359 Now compile and run the example program:
4360
4361 $ cd examples/basic_aggregation/
4362 $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
4363 $ ./agg-example localhost
4364
4365 Inserting data
4366 distinct
4367 Next double: 2.000000
4368 Next double: 3.000000
4369 map reduce
4370 { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
4371 { "_id" : "cat", "value" : 63 }
4372 { "_id" : "dog", "value" : 42 }
4373 { "_id" : "mouse", "value" : 21 }
4374 more complicated map reduce
4375 { "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 }
4376
4377 Using libmongoc in a Microsoft Visual Studio project
4378 Download and install libmongoc on your system, then open Visual Studio,
4379 select "File→New→Project...", and create a new Win32 Console Applica‐
4380 tion. [image]
4381
4382 Remember to switch the platform from 32-bit to 64-bit: [image]
4383
4384 Right-click on your console application in the Solution Explorer and
4385 select "Properties". Choose to edit properties for "All Configura‐
4386 tions", expand the "C/C++" options and choose "General". Add to the
4387 "Additional Include Directories" these paths:
4388
4389 C:\mongo-c-driver\include\libbson-1.0
4390 C:\mongo-c-driver\include\libmongoc-1.0
4391 [image]
4392
4393 (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
4394 include paths will be different.)
4395
4396 Also in the Properties dialog, expand the "Linker" options and choose
4397 "Input", and add to the "Additional Dependencies" these libraries:
4398
4399 C:\mongo-c-driver\lib\bson-1.0.lib
4400 C:\mongo-c-driver\lib\mongoc-1.0.lib
4401 [image]
4402
4403 Adding these libraries as dependencies provides linker symbols to build
4404 your application, but to actually run it, libbson's and libmongoc's
4405 DLLs must be in your executable path. Select "Debugging" in the Proper‐
4406 ties dialog, and set the "Environment" option to:
4407
4408 PATH=c:/mongo-c-driver/bin
4409 [image]
4410
4411 Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
4412
4413 #include <mongoc/mongoc.h>
4414
4415 Static linking
4416 Following the instructions above, you have dynamically linked your ap‐
4417 plication to the libbson and libmongoc DLLs. This is usually the right
4418 choice. If you want to link statically instead, update your "Additional
4419 Dependencies" list by removing bson-1.0.lib and mongoc-1.0.lib and re‐
4420 placing them with these libraries:
4421
4422 C:\mongo-c-driver\lib\bson-static-1.0.lib
4423 C:\mongo-c-driver\lib\mongoc-static-1.0.lib
4424 ws2_32.lib
4425 Secur32.lib
4426 Crypt32.lib
4427 BCrypt.lib
4428 [image]
4429
4430 (To explain the purpose of each library: bson-static-1.0.lib and mon‐
4431 goc-static-1.0.lib are static archives of the driver code. The socket
4432 library ws2_32 is required by libbson, which uses the socket routine
4433 gethostname to help guarantee ObjectId uniqueness. The BCrypt library
4434 is used by libmongoc for TLS connections to MongoDB, and Secur32 and
4435 Crypt32 are required for enterprise authentication methods like Ker‐
4436 beros.)
4437
4438 Finally, define two preprocessor symbols before including mongoc/mon‐
4439 goc.h in your stdafx.h:
4440
4441 #define BSON_STATIC
4442 #define MONGOC_STATIC
4443 #include <mongoc/mongoc.h>
4444
4445 Making these changes to your project is only required for static link‐
4446 ing; for most people, the dynamic-linking instructions above are pre‐
4447 ferred.
4448
4449 Next Steps
4450 Now you can build and debug applications in Visual Studio that use
4451 libbson and libmongoc. Proceed to making-a-connection in the tutorial
4452 to learn how connect to MongoDB and perform operations.
4453
4454 Creating Indexes
4455 To create indexes on a MongoDB collection, execute the createIndexes
4456 command with a command function like mongoc_database_write_com‐
4457 mand_with_opts or mongoc_collection_write_command_with_opts. See the
4458 MongoDB Manual entry for the createIndexes command for details.
4459
4460 Example
4461 example-create-indexes.c
4462
4463 /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
4464 * --libs libmongoc-1.0) */
4465
4466 /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */
4467
4468 #include <mongoc/mongoc.h>
4469 #include <stdio.h>
4470 #include <stdlib.h>
4471
4472 int
4473 main (int argc, char *argv[])
4474 {
4475 mongoc_client_t *client;
4476 const char *uri_string =
4477 "mongodb://127.0.0.1/?appname=create-indexes-example";
4478 mongoc_uri_t *uri;
4479 mongoc_database_t *db;
4480 const char *collection_name = "test";
4481 bson_t keys;
4482 char *index_name;
4483 bson_t *create_indexes;
4484 bson_t reply;
4485 char *reply_str;
4486 bson_error_t error;
4487 bool r;
4488
4489 mongoc_init ();
4490
4491 if (argc > 1) {
4492 uri_string = argv[1];
4493 }
4494
4495 if (argc > 2) {
4496 collection_name = argv[2];
4497 }
4498
4499 uri = mongoc_uri_new_with_error (uri_string, &error);
4500 if (!uri) {
4501 fprintf (stderr,
4502 "failed to parse URI: %s\n"
4503 "error message: %s\n",
4504 uri_string,
4505 error.message);
4506 return EXIT_FAILURE;
4507 }
4508
4509 client = mongoc_client_new_from_uri (uri);
4510 if (!client) {
4511 return EXIT_FAILURE;
4512 }
4513
4514 mongoc_client_set_error_api (client, 2);
4515 db = mongoc_client_get_database (client, "test");
4516
4517 /* ascending index on field "x" */
4518 bson_init (&keys);
4519 BSON_APPEND_INT32 (&keys, "x", 1);
4520 index_name = mongoc_collection_keys_to_index_string (&keys);
4521 create_indexes = BCON_NEW ("createIndexes",
4522 BCON_UTF8 (collection_name),
4523 "indexes",
4524 "[",
4525 "{",
4526 "key",
4527 BCON_DOCUMENT (&keys),
4528 "name",
4529 BCON_UTF8 (index_name),
4530 "}",
4531 "]");
4532
4533 r = mongoc_database_write_command_with_opts (
4534 db, create_indexes, NULL /* opts */, &reply, &error);
4535
4536 reply_str = bson_as_json (&reply, NULL);
4537 printf ("%s\n", reply_str);
4538
4539 if (!r) {
4540 fprintf (stderr, "Error in createIndexes: %s\n", error.message);
4541 }
4542
4543 bson_free (index_name);
4544 bson_free (reply_str);
4545 bson_destroy (&reply);
4546 bson_destroy (create_indexes);
4547 mongoc_database_destroy (db);
4548 mongoc_uri_destroy (uri);
4549 mongoc_client_destroy (client);
4550
4551 mongoc_cleanup ();
4552
4553 return r ? EXIT_SUCCESS : EXIT_FAILURE;
4554 }
4555
4556
4557 Aids for Debugging
4558 GDB
4559 This repository contains a .gdbinit file that contains helper functions
4560 to aid debugging of data structures. GDB will load this file
4561 automatically if you have added the directory which contains the
4562 .gdbinit file to GDB's auto-load safe-path, and you start GDB from the
4563 directory which holds the .gdbinit file.
4564
4565 You can see the safe-path with show auto-load safe-path on a GDB
4566 prompt. You can configure it by setting it in ~/.gdbinit with:
4567
4568 add-auto-load-safe-path /path/to/mongo-c-driver
4569
4570 If you haven't added the path to your auto-load safe-path, or start GDB
4571 in another directory, load the file with:
4572
4573 source path/to/mongo-c-driver/.gdbinit
4574
4575 The .gdbinit file defines the printbson function, which shows the con‐
4576 tents of a bson_t * variable. If you have a local bson_t, then you
4577 must prefix the variable with a &.
4578
4579 An example GDB session looks like:
4580
4581 (gdb) printbson bson
4582 ALLOC [0x555556cd7310 + 0] (len=475)
4583 {
4584 'bool' : true,
4585 'int32' : NumberInt("42"),
4586 'int64' : NumberLong("3000000042"),
4587 'string' : "Stŕìñg",
4588 'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
4589 'utcDateTime' : UTCDateTime(1511277299031),
4590 'arrayOfInts' : [
4591 '0' : NumberInt("1"),
4592 '1' : NumberInt("2")
4593 ],
4594 'embeddedDocument' : {
4595 'arrayOfStrings' : [
4596 '0' : "one",
4597 '1' : "two"
4598 ],
4599 'double' : 2.718280,
4600 'notherDoc' : {
4601 'true' : NumberInt("1"),
4602 'false' : false
4603 }
4604 },
4605 'binary' : Binary("02", "3031343532333637"),
4606 'regex' : Regex("@[a-z]+@", "im"),
4607 'null' : null,
4608 'js' : JavaScript("print foo"),
4609 'jsws' : JavaScript("print foo") with scope: {
4610 'f' : NumberInt("42"),
4611 'a' : [
4612 '0' : 3.141593,
4613 '1' : 2.718282
4614 ]
4615 },
4616 'timestamp' : Timestamp(4294967295, 4294967295),
4617 'double' : 3.141593
4618 }
4619
4620 LLDB
4621 This repository also includes a script that customizes LLDB's standard
4622 print command to print a bson_t or bson_t * as JSON:
4623
4624 (lldb) print b
4625 (bson_t) $0 = {"x": 1, "y": 2}
4626
4627 The custom bson command provides more options:
4628
4629 (lldb) bson --verbose b
4630 len=19
4631 flags=INLINE|STATIC
4632 {
4633 "x": 1,
4634 "y": 2
4635 }
4636 (lldb) bson --raw b
4637 '\x13\x00\x00\x00\x10x\x00\x01\x00\x00\x00\x10y\x00\x02\x00\x00\x00\x00'
4638
4639 Type help bson for a list of options.
4640
4641 The script requires a build of libbson with debug symbols, and an in‐
4642 stallation of PyMongo. Install PyMongo with:
4643
4644 python -m pip install pymongo
4645
4646 If you see "No module named pip" then you must install pip, then run
4647 the previous command again.
4648
4649 Create a file ~/.lldbinit containing:
4650
4651 command script import /path/to/mongo-c-driver/lldb_bson.py
4652
4653 If you see "bson command installed by lldb_bson" at the beginning of
4654 your LLDB session, you've installed the script correctly.
4655
4656 Using Client-Side Field Level Encryption
4657 New in MongoDB 4.2, Client-Side Field Level Encryption (also referred
4658 to as Client-Side Encryption) allows administrators and developers to
4659 encrypt specific data fields in addition to other MongoDB encryption
4660 features.
4661
4662 With Client-Side Encryption, developers can encrypt fields client side
4663 without any server-side configuration or directives. Client-Side En‐
4664 cryption supports workloads where applications must guarantee that
4665 unauthorized parties, including server administrators, cannot read the
4666 encrypted data.
4667
4668 Automatic encryption, where sensitive fields in commands are encrypted
4669 automatically, requires an Enterprise-only process to do query analy‐
4670 sis.
4671
4672 Installation
4673 libmongocrypt
4674 There is a separate library, libmongocrypt, that must be installed
4675 prior to configuring libmongoc to enable Client-Side Encryption.
4676
4677 libmongocrypt depends on libbson. To build libmongoc with Client-Side
4678 Encryption support you must:
4679
4680 1. Install libbson
4681
4682 2. Build and install libmongocrypt
4683
4684 3. Build libmongoc
4685
4686 To install libbson, follow the instructions to install with a package
4687 manager: Install libbson with a Package Manager or build from source
4688 with cmake (disable building libmongoc with -DENABLE_MONGOC=OFF):
4689
4690 $ cd mongo-c-driver
4691 $ mkdir cmake-build && cd cmake-build
4692 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=OFF ..
4693 $ cmake --build . --target install
4694
4695 To build and install libmongocrypt, clone the repository and configure
4696 as follows:
4697
4698 $ cd libmongocrypt
4699 $ mkdir cmake-build && cd cmake-build
4700 $ cmake -DENABLE_SHARED_BSON=ON ..
4701 $ cmake --build . --target install
4702
4703 Then, you should be able to build libmongoc with Client-Side Encryp‐
4704 tion.
4705
4706 $ cd mongo-c-driver
4707 $ mkdir cmake-build && cd cmake-build
4708 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=ON -DENABLE_CLIENT_SIDE_ENCRYPTION=ON ..
4709 $ cmake --build . --target install
4710
4711 mongocryptd
4712 The mongocryptd binary is required for automatic Client-Side Encryption
4713 and is included as a component in the MongoDB Enterprise Server pack‐
4714 age. For detailed installation instructions see the MongoDB documenta‐
4715 tion on mongocryptd.
4716
4717 mongocryptd performs the following:
4718
4719 • Parses the automatic encryption rules specified to the database con‐
4720 nection. If the JSON schema contains invalid automatic encryption
4721 syntax or any document validation syntax, mongocryptd returns an er‐
4722 ror.
4723
4724 • Uses the specified automatic encryption rules to mark fields in read
4725 and write operations for encryption.
4726
4727 • Rejects read/write operations that may return unexpected or incorrect
4728 results when applied to an encrypted field. For supported and unsup‐
4729 ported operations, see Read/Write Support with Automatic Field Level
4730 Encryption.
4731
4732 A mongoc_client_t configured with auto encryption will automatically
4733 spawn the mongocryptd process from the application's PATH. Applications
4734 can control the spawning behavior as part of the automatic encryption
4735 options. For example, to set a custom path to the mongocryptd process,
4736 set the mongocryptdSpawnPath with mongoc_auto_encryption_opts_set_ex‐
4737 tra().
4738
4739 bson_t *extra = BCON_NEW ("mongocryptdSpawnPath", "/path/to/mongocryptd");
4740 mongoc_auto_encryption_opts_set_extra (opts, extra);
4741
4742 To control the logging output of mongocryptd pass mongocryptdSpawnArgs
4743 to mongoc_auto_encryption_opts_set_extra():
4744
4745 bson_t *extra = BCON_NEW ("mongocryptdSpawnArgs",
4746 "[", "--logpath=/path/to/mongocryptd.log", "--logappend", "]");
4747 mongoc_auto_encryption_opts_set_extra (opts, extra);
4748
4749 If your application wishes to manage the mongocryptd process manually,
4750 it is possible to disable spawning mongocryptd:
4751
4752 bson_t *extra = BCON_NEW ("mongocryptdBypassSpawn",
4753 BCON_BOOL(true), "mongocryptdURI", "mongodb://localhost:27020");
4754 mongoc_auto_encryption_opts_set_extra (opts, extra);
4755
4756 mongocryptd is only responsible for supporting automatic Client-Side
4757 Encryption in the driver and does not itself perform any encryption or
4758 decryption.
4759
4760 Automatic Client-Side Field Level Encryption
4761 Automatic Client-Side Encryption is enabled by calling mon‐
4762 goc_client_enable_auto_encryption() on a mongoc_client_t. The following
4763 examples show how to set up automatic client-side field level encryp‐
4764 tion using mongoc_client_encryption_t to create a new encryption data
4765 key.
4766
4767 NOTE:
4768 Automatic client-side field level encryption requires MongoDB 4.2
4769 enterprise or a MongoDB 4.2 Atlas cluster. The community version of
4770 the server supports automatic decryption as well as Explicit Encryp‐
4771 tion.
4772
4773 Providing Local Automatic Encryption Rules
4774 The following example shows how to specify automatic encryption rules
4775 using a schema map set with mongoc_auto_encryp‐
4776 tion_opts_set_schema_map(). The automatic encryption rules are ex‐
4777 pressed using a strict subset of the JSON Schema syntax.
4778
4779 Supplying a schema map provides more security than relying on JSON
4780 Schemas obtained from the server. It protects against a malicious
4781 server advertising a false JSON Schema, which could trick the client
4782 into sending unencrypted data that should be encrypted.
4783
4784 JSON Schemas supplied in the schema map only apply to configuring auto‐
4785 matic client-side field level encryption. Other validation rules in the
4786 JSON schema will not be enforced by the driver and will result in an
4787 error:
4788
4789 client-side-encryption-schema-map.c
4790
4791 #include <mongoc/mongoc.h>
4792 #include <stdio.h>
4793 #include <stdlib.h>
4794
4795 #include "client-side-encryption-helpers.h"
4796
4797 /* Helper method to create a new data key in the key vault, a schema to use that
4798 * key, and writes the schema to a file for later use. */
4799 static bool
4800 create_schema_file (bson_t *kms_providers,
4801 const char *keyvault_db,
4802 const char *keyvault_coll,
4803 mongoc_client_t *keyvault_client,
4804 bson_error_t *error)
4805 {
4806 mongoc_client_encryption_t *client_encryption = NULL;
4807 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
4808 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
4809 bson_value_t datakey_id = {0};
4810 char *keyaltnames[] = {"mongoc_encryption_example_1"};
4811 bson_t *schema = NULL;
4812 char *schema_string = NULL;
4813 size_t schema_string_len;
4814 FILE *outfile = NULL;
4815 bool ret = false;
4816
4817 client_encryption_opts = mongoc_client_encryption_opts_new ();
4818 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
4819 kms_providers);
4820 mongoc_client_encryption_opts_set_keyvault_namespace (
4821 client_encryption_opts, keyvault_db, keyvault_coll);
4822 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
4823 keyvault_client);
4824
4825 client_encryption =
4826 mongoc_client_encryption_new (client_encryption_opts, error);
4827 if (!client_encryption) {
4828 goto fail;
4829 }
4830
4831 /* Create a new data key and json schema for the encryptedField.
4832 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
4833 */
4834 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
4835 mongoc_client_encryption_datakey_opts_set_keyaltnames (
4836 datakey_opts, keyaltnames, 1);
4837 if (!mongoc_client_encryption_create_datakey (
4838 client_encryption, "local", datakey_opts, &datakey_id, error)) {
4839 goto fail;
4840 }
4841
4842 /* Create a schema describing that "encryptedField" is a string encrypted
4843 * with the newly created data key using deterministic encryption. */
4844 schema = BCON_NEW ("properties",
4845 "{",
4846 "encryptedField",
4847 "{",
4848 "encrypt",
4849 "{",
4850 "keyId",
4851 "[",
4852 BCON_BIN (datakey_id.value.v_binary.subtype,
4853 datakey_id.value.v_binary.data,
4854 datakey_id.value.v_binary.data_len),
4855 "]",
4856 "bsonType",
4857 "string",
4858 "algorithm",
4859 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
4860 "}",
4861 "}",
4862 "}",
4863 "bsonType",
4864 "object");
4865
4866 /* Use canonical JSON so that other drivers and tools will be
4867 * able to parse the MongoDB extended JSON file. */
4868 schema_string = bson_as_canonical_extended_json (schema, &schema_string_len);
4869 outfile = fopen ("jsonSchema.json", "w");
4870 if (0 == fwrite (schema_string, sizeof (char), schema_string_len, outfile)) {
4871 fprintf (stderr, "failed to write to file\n");
4872 goto fail;
4873 }
4874
4875 ret = true;
4876 fail:
4877 mongoc_client_encryption_destroy (client_encryption);
4878 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
4879 mongoc_client_encryption_opts_destroy (client_encryption_opts);
4880 bson_free (schema_string);
4881 bson_destroy (schema);
4882 bson_value_destroy (&datakey_id);
4883 if (outfile) {
4884 fclose (outfile);
4885 }
4886 return true;
4887 }
4888
4889 /* This example demonstrates how to use automatic encryption with a client-side
4890 * schema map using the enterprise version of MongoDB */
4891 int
4892 main (int argc, char **argv)
4893 {
4894 /* The collection used to store the encryption data keys. */
4895 #define KEYVAULT_DB "encryption"
4896 #define KEYVAULT_COLL "__libmongocTestKeyVault"
4897 /* The collection used to store the encrypted documents in this example. */
4898 #define ENCRYPTED_DB "test"
4899 #define ENCRYPTED_COLL "coll"
4900
4901 int exit_status = EXIT_FAILURE;
4902 bool ret;
4903 uint8_t *local_masterkey = NULL;
4904 uint32_t local_masterkey_len;
4905 bson_t *kms_providers = NULL;
4906 bson_error_t error = {0};
4907 bson_t *index_keys = NULL;
4908 char *index_name = NULL;
4909 bson_t *create_index_cmd = NULL;
4910 bson_json_reader_t *reader = NULL;
4911 bson_t schema = BSON_INITIALIZER;
4912 bson_t *schema_map = NULL;
4913
4914 /* The MongoClient used to access the key vault (keyvault_namespace). */
4915 mongoc_client_t *keyvault_client = NULL;
4916 mongoc_collection_t *keyvault_coll = NULL;
4917 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
4918 mongoc_client_t *client = NULL;
4919 mongoc_collection_t *coll = NULL;
4920 bson_t *to_insert = NULL;
4921 mongoc_client_t *unencrypted_client = NULL;
4922 mongoc_collection_t *unencrypted_coll = NULL;
4923
4924 mongoc_init ();
4925
4926 /* Configure the master key. This must be the same master key that was used
4927 * to create the encryption key. */
4928 local_masterkey =
4929 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
4930 if (!local_masterkey || local_masterkey_len != 96) {
4931 fprintf (stderr,
4932 "Specify LOCAL_MASTERKEY environment variable as a "
4933 "secure random 96 byte hex value.\n");
4934 goto fail;
4935 }
4936
4937 kms_providers = BCON_NEW ("local",
4938 "{",
4939 "key",
4940 BCON_BIN (0, local_masterkey, local_masterkey_len),
4941 "}");
4942
4943 /* Set up the key vault for this example. */
4944 keyvault_client = mongoc_client_new (
4945 "mongodb://localhost/?appname=client-side-encryption-keyvault");
4946 keyvault_coll = mongoc_client_get_collection (
4947 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
4948 mongoc_collection_drop (keyvault_coll, NULL);
4949
4950 /* Create a unique index to ensure that two data keys cannot share the same
4951 * keyAltName. This is recommended practice for the key vault. */
4952 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
4953 index_name = mongoc_collection_keys_to_index_string (index_keys);
4954 create_index_cmd = BCON_NEW ("createIndexes",
4955 KEYVAULT_COLL,
4956 "indexes",
4957 "[",
4958 "{",
4959 "key",
4960 BCON_DOCUMENT (index_keys),
4961 "name",
4962 index_name,
4963 "unique",
4964 BCON_BOOL (true),
4965 "partialFilterExpression",
4966 "{",
4967 "keyAltNames",
4968 "{",
4969 "$exists",
4970 BCON_BOOL (true),
4971 "}",
4972 "}",
4973 "}",
4974 "]");
4975 ret = mongoc_client_command_simple (keyvault_client,
4976 KEYVAULT_DB,
4977 create_index_cmd,
4978 NULL /* read prefs */,
4979 NULL /* reply */,
4980 &error);
4981
4982 if (!ret) {
4983 goto fail;
4984 }
4985
4986 /* Create a new data key and a schema using it for encryption. Save the
4987 * schema to the file jsonSchema.json */
4988 ret = create_schema_file (
4989 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
4990
4991 if (!ret) {
4992 goto fail;
4993 }
4994
4995 /* Load the JSON Schema and construct the local schema_map option. */
4996 reader = bson_json_reader_new_from_file ("jsonSchema.json", &error);
4997 if (!reader) {
4998 goto fail;
4999 }
5000
5001 bson_json_reader_read (reader, &schema, &error);
5002
5003 /* Construct the schema map, mapping the namespace of the collection to the
5004 * schema describing encryption. */
5005 schema_map =
5006 BCON_NEW (ENCRYPTED_DB "." ENCRYPTED_COLL, BCON_DOCUMENT (&schema));
5007
5008 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5009 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
5010 keyvault_client);
5011 mongoc_auto_encryption_opts_set_keyvault_namespace (
5012 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5013 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5014 kms_providers);
5015 mongoc_auto_encryption_opts_set_schema_map (auto_encryption_opts,
5016 schema_map);
5017
5018 client =
5019 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5020
5021 /* Enable automatic encryption. It will determine that encryption is
5022 * necessary from the schema map instead of relying on the server to provide
5023 * a schema. */
5024 ret = mongoc_client_enable_auto_encryption (
5025 client, auto_encryption_opts, &error);
5026 if (!ret) {
5027 goto fail;
5028 }
5029
5030 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5031
5032 /* Clear old data */
5033 mongoc_collection_drop (coll, NULL);
5034
5035 to_insert = BCON_NEW ("encryptedField", "123456789");
5036 ret = mongoc_collection_insert_one (
5037 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5038 if (!ret) {
5039 goto fail;
5040 }
5041 printf ("decrypted document: ");
5042 if (!print_one_document (coll, &error)) {
5043 goto fail;
5044 }
5045 printf ("\n");
5046
5047 unencrypted_client = mongoc_client_new (
5048 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
5049 unencrypted_coll = mongoc_client_get_collection (
5050 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5051 printf ("encrypted document: ");
5052 if (!print_one_document (unencrypted_coll, &error)) {
5053 goto fail;
5054 }
5055 printf ("\n");
5056
5057 exit_status = EXIT_SUCCESS;
5058 fail:
5059 if (error.code) {
5060 fprintf (stderr, "error: %s\n", error.message);
5061 }
5062
5063 bson_free (local_masterkey);
5064 bson_destroy (kms_providers);
5065 mongoc_collection_destroy (keyvault_coll);
5066 bson_destroy (index_keys);
5067 bson_free (index_name);
5068 bson_destroy (create_index_cmd);
5069 bson_json_reader_destroy (reader);
5070 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5071 mongoc_collection_destroy (coll);
5072 mongoc_client_destroy (client);
5073 bson_destroy (to_insert);
5074 mongoc_collection_destroy (unencrypted_coll);
5075 mongoc_client_destroy (unencrypted_client);
5076 mongoc_client_destroy (keyvault_client);
5077 bson_destroy (&schema);
5078 bson_destroy (schema_map);
5079 mongoc_cleanup ();
5080 return exit_status;
5081 }
5082
5083 Server-Side Field Level Encryption Enforcement
5084 The MongoDB 4.2 server supports using schema validation to enforce en‐
5085 cryption of specific fields in a collection. This schema validation
5086 will prevent an application from inserting unencrypted values for any
5087 fields marked with the "encrypt" JSON schema keyword.
5088
5089 The following example shows how to set up automatic client-side field
5090 level encryption using mongoc_client_encryption_t to create a new en‐
5091 cryption data key and create a collection with the Automatic Encryption
5092 JSON Schema Syntax:
5093
5094 client-side-encryption-server-schema.c
5095
5096 #include <mongoc/mongoc.h>
5097 #include <stdio.h>
5098 #include <stdlib.h>
5099
5100 #include "client-side-encryption-helpers.h"
5101
5102 /* Helper method to create and return a JSON schema to use for encryption.
5103 The caller will use the returned schema for server-side encryption validation.
5104 */
5105 static bson_t *
5106 create_schema (bson_t *kms_providers,
5107 const char *keyvault_db,
5108 const char *keyvault_coll,
5109 mongoc_client_t *keyvault_client,
5110 bson_error_t *error)
5111 {
5112 mongoc_client_encryption_t *client_encryption = NULL;
5113 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5114 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5115 bson_value_t datakey_id = {0};
5116 char *keyaltnames[] = {"mongoc_encryption_example_2"};
5117 bson_t *schema = NULL;
5118
5119 client_encryption_opts = mongoc_client_encryption_opts_new ();
5120 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5121 kms_providers);
5122 mongoc_client_encryption_opts_set_keyvault_namespace (
5123 client_encryption_opts, keyvault_db, keyvault_coll);
5124 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5125 keyvault_client);
5126
5127 client_encryption =
5128 mongoc_client_encryption_new (client_encryption_opts, error);
5129 if (!client_encryption) {
5130 goto fail;
5131 }
5132
5133 /* Create a new data key and json schema for the encryptedField.
5134 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5135 */
5136 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5137 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5138 datakey_opts, keyaltnames, 1);
5139 if (!mongoc_client_encryption_create_datakey (
5140 client_encryption, "local", datakey_opts, &datakey_id, error)) {
5141 goto fail;
5142 }
5143
5144 /* Create a schema describing that "encryptedField" is a string encrypted
5145 * with the newly created data key using deterministic encryption. */
5146 schema = BCON_NEW ("properties",
5147 "{",
5148 "encryptedField",
5149 "{",
5150 "encrypt",
5151 "{",
5152 "keyId",
5153 "[",
5154 BCON_BIN (datakey_id.value.v_binary.subtype,
5155 datakey_id.value.v_binary.data,
5156 datakey_id.value.v_binary.data_len),
5157 "]",
5158 "bsonType",
5159 "string",
5160 "algorithm",
5161 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
5162 "}",
5163 "}",
5164 "}",
5165 "bsonType",
5166 "object");
5167
5168 fail:
5169 mongoc_client_encryption_destroy (client_encryption);
5170 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5171 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5172 bson_value_destroy (&datakey_id);
5173 return schema;
5174 }
5175
5176 /* This example demonstrates how to use automatic encryption with a server-side
5177 * schema using the enterprise version of MongoDB */
5178 int
5179 main (int argc, char **argv)
5180 {
5181 /* The collection used to store the encryption data keys. */
5182 #define KEYVAULT_DB "encryption"
5183 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5184 /* The collection used to store the encrypted documents in this example. */
5185 #define ENCRYPTED_DB "test"
5186 #define ENCRYPTED_COLL "coll"
5187
5188 int exit_status = EXIT_FAILURE;
5189 bool ret;
5190 uint8_t *local_masterkey = NULL;
5191 uint32_t local_masterkey_len;
5192 bson_t *kms_providers = NULL;
5193 bson_error_t error = {0};
5194 bson_t *index_keys = NULL;
5195 char *index_name = NULL;
5196 bson_t *create_index_cmd = NULL;
5197 bson_json_reader_t *reader = NULL;
5198 bson_t *schema = NULL;
5199
5200 /* The MongoClient used to access the key vault (keyvault_namespace). */
5201 mongoc_client_t *keyvault_client = NULL;
5202 mongoc_collection_t *keyvault_coll = NULL;
5203 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
5204 mongoc_client_t *client = NULL;
5205 mongoc_collection_t *coll = NULL;
5206 bson_t *to_insert = NULL;
5207 mongoc_client_t *unencrypted_client = NULL;
5208 mongoc_collection_t *unencrypted_coll = NULL;
5209 bson_t *create_cmd = NULL;
5210 bson_t *create_cmd_opts = NULL;
5211 mongoc_write_concern_t *wc = NULL;
5212
5213 mongoc_init ();
5214
5215 /* Configure the master key. This must be the same master key that was used
5216 * to create
5217 * the encryption key. */
5218 local_masterkey =
5219 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5220 if (!local_masterkey || local_masterkey_len != 96) {
5221 fprintf (stderr,
5222 "Specify LOCAL_MASTERKEY environment variable as a "
5223 "secure random 96 byte hex value.\n");
5224 goto fail;
5225 }
5226
5227 kms_providers = BCON_NEW ("local",
5228 "{",
5229 "key",
5230 BCON_BIN (0, local_masterkey, local_masterkey_len),
5231 "}");
5232
5233 /* Set up the key vault for this example. */
5234 keyvault_client = mongoc_client_new (
5235 "mongodb://localhost/?appname=client-side-encryption-keyvault");
5236 keyvault_coll = mongoc_client_get_collection (
5237 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
5238 mongoc_collection_drop (keyvault_coll, NULL);
5239
5240 /* Create a unique index to ensure that two data keys cannot share the same
5241 * keyAltName. This is recommended practice for the key vault. */
5242 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5243 index_name = mongoc_collection_keys_to_index_string (index_keys);
5244 create_index_cmd = BCON_NEW ("createIndexes",
5245 KEYVAULT_COLL,
5246 "indexes",
5247 "[",
5248 "{",
5249 "key",
5250 BCON_DOCUMENT (index_keys),
5251 "name",
5252 index_name,
5253 "unique",
5254 BCON_BOOL (true),
5255 "partialFilterExpression",
5256 "{",
5257 "keyAltNames",
5258 "{",
5259 "$exists",
5260 BCON_BOOL (true),
5261 "}",
5262 "}",
5263 "}",
5264 "]");
5265 ret = mongoc_client_command_simple (keyvault_client,
5266 KEYVAULT_DB,
5267 create_index_cmd,
5268 NULL /* read prefs */,
5269 NULL /* reply */,
5270 &error);
5271
5272 if (!ret) {
5273 goto fail;
5274 }
5275
5276 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5277 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
5278 keyvault_client);
5279 mongoc_auto_encryption_opts_set_keyvault_namespace (
5280 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5281 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5282 kms_providers);
5283 schema = create_schema (
5284 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
5285
5286 if (!schema) {
5287 goto fail;
5288 }
5289
5290 client =
5291 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5292 ret = mongoc_client_enable_auto_encryption (
5293 client, auto_encryption_opts, &error);
5294 if (!ret) {
5295 goto fail;
5296 }
5297
5298 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5299
5300 /* Clear old data */
5301 mongoc_collection_drop (coll, NULL);
5302
5303 /* Create the collection with the encryption JSON Schema. */
5304 create_cmd = BCON_NEW ("create",
5305 ENCRYPTED_COLL,
5306 "validator",
5307 "{",
5308 "$jsonSchema",
5309 BCON_DOCUMENT (schema),
5310 "}");
5311 wc = mongoc_write_concern_new ();
5312 mongoc_write_concern_set_wmajority (wc, 0);
5313 create_cmd_opts = bson_new ();
5314 mongoc_write_concern_append (wc, create_cmd_opts);
5315 ret = mongoc_client_command_with_opts (client,
5316 ENCRYPTED_DB,
5317 create_cmd,
5318 NULL /* read prefs */,
5319 create_cmd_opts,
5320 NULL /* reply */,
5321 &error);
5322 if (!ret) {
5323 goto fail;
5324 }
5325
5326 to_insert = BCON_NEW ("encryptedField", "123456789");
5327 ret = mongoc_collection_insert_one (
5328 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5329 if (!ret) {
5330 goto fail;
5331 }
5332 printf ("decrypted document: ");
5333 if (!print_one_document (coll, &error)) {
5334 goto fail;
5335 }
5336 printf ("\n");
5337
5338 unencrypted_client = mongoc_client_new (
5339 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
5340 unencrypted_coll = mongoc_client_get_collection (
5341 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5342 printf ("encrypted document: ");
5343 if (!print_one_document (unencrypted_coll, &error)) {
5344 goto fail;
5345 }
5346 printf ("\n");
5347
5348 /* Expect a server-side error if inserting with the unencrypted collection.
5349 */
5350 ret = mongoc_collection_insert_one (
5351 unencrypted_coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5352 if (!ret) {
5353 printf ("insert with unencrypted collection failed: %s\n", error.message);
5354 memset (&error, 0, sizeof (error));
5355 }
5356
5357 exit_status = EXIT_SUCCESS;
5358 fail:
5359 if (error.code) {
5360 fprintf (stderr, "error: %s\n", error.message);
5361 }
5362
5363 bson_free (local_masterkey);
5364 bson_destroy (kms_providers);
5365 mongoc_collection_destroy (keyvault_coll);
5366 bson_destroy (index_keys);
5367 bson_free (index_name);
5368 bson_destroy (create_index_cmd);
5369 bson_json_reader_destroy (reader);
5370 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5371 mongoc_collection_destroy (coll);
5372 mongoc_client_destroy (client);
5373 bson_destroy (to_insert);
5374 mongoc_collection_destroy (unencrypted_coll);
5375 mongoc_client_destroy (unencrypted_client);
5376 mongoc_client_destroy (keyvault_client);
5377 bson_destroy (schema);
5378 bson_destroy (create_cmd);
5379 bson_destroy (create_cmd_opts);
5380 mongoc_write_concern_destroy (wc);
5381
5382 mongoc_cleanup ();
5383 return exit_status;
5384 }
5385
5386 Explicit Encryption
5387 Explicit encryption is a MongoDB community feature and does not use the
5388 mongocryptd process. Explicit encryption is provided by the mon‐
5389 goc_client_encryption_t class, for example:
5390
5391 client-side-encryption-explicit.c
5392
5393 #include <mongoc/mongoc.h>
5394 #include <stdio.h>
5395 #include <stdlib.h>
5396
5397 #include "client-side-encryption-helpers.h"
5398
5399 /* This example demonstrates how to use explicit encryption and decryption using
5400 * the community version of MongoDB */
5401 int
5402 main (int argc, char **argv)
5403 {
5404 /* The collection used to store the encryption data keys. */
5405 #define KEYVAULT_DB "encryption"
5406 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5407 /* The collection used to store the encrypted documents in this example. */
5408 #define ENCRYPTED_DB "test"
5409 #define ENCRYPTED_COLL "coll"
5410
5411 int exit_status = EXIT_FAILURE;
5412 bool ret;
5413 uint8_t *local_masterkey = NULL;
5414 uint32_t local_masterkey_len;
5415 bson_t *kms_providers = NULL;
5416 bson_error_t error = {0};
5417 bson_t *index_keys = NULL;
5418 char *index_name = NULL;
5419 bson_t *create_index_cmd = NULL;
5420 bson_t *schema = NULL;
5421 mongoc_client_t *client = NULL;
5422 mongoc_collection_t *coll = NULL;
5423 mongoc_collection_t *keyvault_coll = NULL;
5424 bson_t *to_insert = NULL;
5425 bson_t *create_cmd = NULL;
5426 bson_t *create_cmd_opts = NULL;
5427 mongoc_write_concern_t *wc = NULL;
5428 mongoc_client_encryption_t *client_encryption = NULL;
5429 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5430 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5431 char *keyaltnames[] = {"mongoc_encryption_example_3"};
5432 bson_value_t datakey_id = {0};
5433 bson_value_t encrypted_field = {0};
5434 bson_value_t to_encrypt = {0};
5435 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
5436 bson_value_t decrypted = {0};
5437
5438 mongoc_init ();
5439
5440 /* Configure the master key. This must be the same master key that was used
5441 * to create the encryption key. */
5442 local_masterkey =
5443 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5444 if (!local_masterkey || local_masterkey_len != 96) {
5445 fprintf (stderr,
5446 "Specify LOCAL_MASTERKEY environment variable as a "
5447 "secure random 96 byte hex value.\n");
5448 goto fail;
5449 }
5450
5451 kms_providers = BCON_NEW ("local",
5452 "{",
5453 "key",
5454 BCON_BIN (0, local_masterkey, local_masterkey_len),
5455 "}");
5456
5457 /* The mongoc_client_t used to read/write application data. */
5458 client =
5459 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5460 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5461
5462 /* Clear old data */
5463 mongoc_collection_drop (coll, NULL);
5464
5465 /* Set up the key vault for this example. */
5466 keyvault_coll =
5467 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
5468 mongoc_collection_drop (keyvault_coll, NULL);
5469
5470 /* Create a unique index to ensure that two data keys cannot share the same
5471 * keyAltName. This is recommended practice for the key vault. */
5472 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5473 index_name = mongoc_collection_keys_to_index_string (index_keys);
5474 create_index_cmd = BCON_NEW ("createIndexes",
5475 KEYVAULT_COLL,
5476 "indexes",
5477 "[",
5478 "{",
5479 "key",
5480 BCON_DOCUMENT (index_keys),
5481 "name",
5482 index_name,
5483 "unique",
5484 BCON_BOOL (true),
5485 "partialFilterExpression",
5486 "{",
5487 "keyAltNames",
5488 "{",
5489 "$exists",
5490 BCON_BOOL (true),
5491 "}",
5492 "}",
5493 "}",
5494 "]");
5495 ret = mongoc_client_command_simple (client,
5496 KEYVAULT_DB,
5497 create_index_cmd,
5498 NULL /* read prefs */,
5499 NULL /* reply */,
5500 &error);
5501
5502 if (!ret) {
5503 goto fail;
5504 }
5505
5506 client_encryption_opts = mongoc_client_encryption_opts_new ();
5507 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5508 kms_providers);
5509 mongoc_client_encryption_opts_set_keyvault_namespace (
5510 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5511
5512 /* Set a mongoc_client_t to use for reading/writing to the key vault. This
5513 * can be the same mongoc_client_t used by the main application. */
5514 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5515 client);
5516 client_encryption =
5517 mongoc_client_encryption_new (client_encryption_opts, &error);
5518 if (!client_encryption) {
5519 goto fail;
5520 }
5521
5522 /* Create a new data key for the encryptedField.
5523 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5524 */
5525 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5526 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5527 datakey_opts, keyaltnames, 1);
5528 if (!mongoc_client_encryption_create_datakey (
5529 client_encryption, "local", datakey_opts, &datakey_id, &error)) {
5530 goto fail;
5531 }
5532
5533 /* Explicitly encrypt a field */
5534 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
5535 mongoc_client_encryption_encrypt_opts_set_algorithm (
5536 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
5537 mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts, &datakey_id);
5538 to_encrypt.value_type = BSON_TYPE_UTF8;
5539 to_encrypt.value.v_utf8.str = "123456789";
5540 to_encrypt.value.v_utf8.len = strlen (to_encrypt.value.v_utf8.str);
5541
5542 ret = mongoc_client_encryption_encrypt (
5543 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
5544 if (!ret) {
5545 goto fail;
5546 }
5547
5548 to_insert = bson_new ();
5549 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
5550 ret = mongoc_collection_insert_one (
5551 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5552 if (!ret) {
5553 goto fail;
5554 }
5555
5556 printf ("encrypted document: ");
5557 if (!print_one_document (coll, &error)) {
5558 goto fail;
5559 }
5560 printf ("\n");
5561
5562 /* Explicitly decrypt a field */
5563 ret = mongoc_client_encryption_decrypt (
5564 client_encryption, &encrypted_field, &decrypted, &error);
5565 if (!ret) {
5566 goto fail;
5567 }
5568 printf ("decrypted value: %s\n", decrypted.value.v_utf8.str);
5569
5570 exit_status = EXIT_SUCCESS;
5571 fail:
5572 if (error.code) {
5573 fprintf (stderr, "error: %s\n", error.message);
5574 }
5575
5576 bson_free (local_masterkey);
5577 bson_destroy (kms_providers);
5578 mongoc_collection_destroy (keyvault_coll);
5579 bson_destroy (index_keys);
5580 bson_free (index_name);
5581 bson_destroy (create_index_cmd);
5582 mongoc_collection_destroy (coll);
5583 mongoc_client_destroy (client);
5584 bson_destroy (to_insert);
5585 bson_destroy (schema);
5586 bson_destroy (create_cmd);
5587 bson_destroy (create_cmd_opts);
5588 mongoc_write_concern_destroy (wc);
5589 mongoc_client_encryption_destroy (client_encryption);
5590 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5591 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5592 bson_value_destroy (&encrypted_field);
5593 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
5594 bson_value_destroy (&decrypted);
5595 bson_value_destroy (&datakey_id);
5596
5597 mongoc_cleanup ();
5598 return exit_status;
5599 }
5600
5601 Explicit Encryption with Automatic Decryption
5602 Although automatic encryption requires MongoDB 4.2 enterprise or a Mon‐
5603 goDB 4.2 Atlas cluster, automatic decryption is supported for all
5604 users. To configure automatic decryption without automatic encryption
5605 set bypass_auto_encryption=True in mongoc_auto_encryption_opts_t:
5606
5607 client-side-encryption-auto-decryption.c
5608
5609 #include <mongoc/mongoc.h>
5610 #include <stdio.h>
5611 #include <stdlib.h>
5612
5613 #include "client-side-encryption-helpers.h"
5614
5615 /* This example demonstrates how to set up automatic decryption without
5616 * automatic encryption using the community version of MongoDB */
5617 int
5618 main (int argc, char **argv)
5619 {
5620 /* The collection used to store the encryption data keys. */
5621 #define KEYVAULT_DB "encryption"
5622 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5623 /* The collection used to store the encrypted documents in this example. */
5624 #define ENCRYPTED_DB "test"
5625 #define ENCRYPTED_COLL "coll"
5626
5627 int exit_status = EXIT_FAILURE;
5628 bool ret;
5629 uint8_t *local_masterkey = NULL;
5630 uint32_t local_masterkey_len;
5631 bson_t *kms_providers = NULL;
5632 bson_error_t error = {0};
5633 bson_t *index_keys = NULL;
5634 char *index_name = NULL;
5635 bson_t *create_index_cmd = NULL;
5636 bson_t *schema = NULL;
5637 mongoc_client_t *client = NULL;
5638 mongoc_collection_t *coll = NULL;
5639 mongoc_collection_t *keyvault_coll = NULL;
5640 bson_t *to_insert = NULL;
5641 bson_t *create_cmd = NULL;
5642 bson_t *create_cmd_opts = NULL;
5643 mongoc_write_concern_t *wc = NULL;
5644 mongoc_client_encryption_t *client_encryption = NULL;
5645 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5646 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5647 char *keyaltnames[] = {"mongoc_encryption_example_4"};
5648 bson_value_t datakey_id = {0};
5649 bson_value_t encrypted_field = {0};
5650 bson_value_t to_encrypt = {0};
5651 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
5652 bson_value_t decrypted = {0};
5653 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
5654 mongoc_client_t *unencrypted_client = NULL;
5655 mongoc_collection_t *unencrypted_coll = NULL;
5656
5657 mongoc_init ();
5658
5659 /* Configure the master key. This must be the same master key that was used
5660 * to create the encryption key. */
5661 local_masterkey =
5662 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5663 if (!local_masterkey || local_masterkey_len != 96) {
5664 fprintf (stderr,
5665 "Specify LOCAL_MASTERKEY environment variable as a "
5666 "secure random 96 byte hex value.\n");
5667 goto fail;
5668 }
5669
5670 kms_providers = BCON_NEW ("local",
5671 "{",
5672 "key",
5673 BCON_BIN (0, local_masterkey, local_masterkey_len),
5674 "}");
5675
5676 client =
5677 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5678 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5679 mongoc_auto_encryption_opts_set_keyvault_namespace (
5680 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5681 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5682 kms_providers);
5683
5684 /* Setting bypass_auto_encryption to true disables automatic encryption but
5685 * keeps the automatic decryption behavior. bypass_auto_encryption will also
5686 * disable spawning mongocryptd */
5687 mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts,
5688 true);
5689
5690 /* Once bypass_auto_encryption is set, community users can enable auto
5691 * encryption on the client. This will, in fact, only perform automatic
5692 * decryption. */
5693 ret = mongoc_client_enable_auto_encryption (
5694 client, auto_encryption_opts, &error);
5695 if (!ret) {
5696 goto fail;
5697 }
5698
5699 /* Now that automatic decryption is on, we can test it by inserting a
5700 * document with an explicitly encrypted value into the collection. When we
5701 * look up the document later, it should be automatically decrypted for us.
5702 */
5703 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5704
5705 /* Clear old data */
5706 mongoc_collection_drop (coll, NULL);
5707
5708 /* Set up the key vault for this example. */
5709 keyvault_coll =
5710 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
5711 mongoc_collection_drop (keyvault_coll, NULL);
5712
5713 /* Create a unique index to ensure that two data keys cannot share the same
5714 * keyAltName. This is recommended practice for the key vault. */
5715 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5716 index_name = mongoc_collection_keys_to_index_string (index_keys);
5717 create_index_cmd = BCON_NEW ("createIndexes",
5718 KEYVAULT_COLL,
5719 "indexes",
5720 "[",
5721 "{",
5722 "key",
5723 BCON_DOCUMENT (index_keys),
5724 "name",
5725 index_name,
5726 "unique",
5727 BCON_BOOL (true),
5728 "partialFilterExpression",
5729 "{",
5730 "keyAltNames",
5731 "{",
5732 "$exists",
5733 BCON_BOOL (true),
5734 "}",
5735 "}",
5736 "}",
5737 "]");
5738 ret = mongoc_client_command_simple (client,
5739 KEYVAULT_DB,
5740 create_index_cmd,
5741 NULL /* read prefs */,
5742 NULL /* reply */,
5743 &error);
5744
5745 if (!ret) {
5746 goto fail;
5747 }
5748
5749 client_encryption_opts = mongoc_client_encryption_opts_new ();
5750 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5751 kms_providers);
5752 mongoc_client_encryption_opts_set_keyvault_namespace (
5753 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5754
5755 /* The key vault client is used for reading to/from the key vault. This can
5756 * be the same mongoc_client_t used by the application. */
5757 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5758 client);
5759 client_encryption =
5760 mongoc_client_encryption_new (client_encryption_opts, &error);
5761 if (!client_encryption) {
5762 goto fail;
5763 }
5764
5765 /* Create a new data key for the encryptedField.
5766 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5767 */
5768 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5769 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5770 datakey_opts, keyaltnames, 1);
5771 ret = mongoc_client_encryption_create_datakey (
5772 client_encryption, "local", datakey_opts, &datakey_id, &error);
5773 if (!ret) {
5774 goto fail;
5775 }
5776
5777 /* Explicitly encrypt a field. */
5778 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
5779 mongoc_client_encryption_encrypt_opts_set_algorithm (
5780 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
5781 mongoc_client_encryption_encrypt_opts_set_keyaltname (
5782 encrypt_opts, "mongoc_encryption_example_4");
5783 to_encrypt.value_type = BSON_TYPE_UTF8;
5784 to_encrypt.value.v_utf8.str = "123456789";
5785 to_encrypt.value.v_utf8.len = strlen (to_encrypt.value.v_utf8.str);
5786
5787 ret = mongoc_client_encryption_encrypt (
5788 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
5789 if (!ret) {
5790 goto fail;
5791 }
5792
5793 to_insert = bson_new ();
5794 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
5795 ret = mongoc_collection_insert_one (
5796 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5797 if (!ret) {
5798 goto fail;
5799 }
5800
5801 /* When we retrieve the document, any encrypted fields will get automatically
5802 * decrypted by the driver. */
5803 printf ("decrypted document: ");
5804 if (!print_one_document (coll, &error)) {
5805 goto fail;
5806 }
5807 printf ("\n");
5808
5809 unencrypted_client =
5810 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5811 unencrypted_coll = mongoc_client_get_collection (
5812 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5813
5814 printf ("encrypted document: ");
5815 if (!print_one_document (unencrypted_coll, &error)) {
5816 goto fail;
5817 }
5818 printf ("\n");
5819
5820 exit_status = EXIT_SUCCESS;
5821 fail:
5822 if (error.code) {
5823 fprintf (stderr, "error: %s\n", error.message);
5824 }
5825
5826 bson_free (local_masterkey);
5827 bson_destroy (kms_providers);
5828 mongoc_collection_destroy (keyvault_coll);
5829 bson_destroy (index_keys);
5830 bson_free (index_name);
5831 bson_destroy (create_index_cmd);
5832 mongoc_collection_destroy (coll);
5833 mongoc_client_destroy (client);
5834 bson_destroy (to_insert);
5835 bson_destroy (schema);
5836 bson_destroy (create_cmd);
5837 bson_destroy (create_cmd_opts);
5838 mongoc_write_concern_destroy (wc);
5839 mongoc_client_encryption_destroy (client_encryption);
5840 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5841 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5842 bson_value_destroy (&encrypted_field);
5843 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
5844 bson_value_destroy (&decrypted);
5845 bson_value_destroy (&datakey_id);
5846 mongoc_collection_destroy (unencrypted_coll);
5847 mongoc_client_destroy (unencrypted_client);
5848 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5849
5850 mongoc_cleanup ();
5851 return exit_status;
5852 }
5853
5854 API Reference
5855 Initialization and cleanup
5856 Synopsis
5857 Initialize the MongoDB C Driver by calling mongoc_init exactly once at
5858 the beginning of your program. It is responsible for initializing
5859 global state such as process counters, SSL, and threading primitives.
5860
5861 Exception to this is mongoc_log_set_handler(), which should be called
5862 before mongoc_init() or some log traces would not use your log handling
5863 function. See Custom Log Handlers for a detailed example.
5864
5865 Call mongoc_cleanup exactly once at the end of your program to release
5866 all memory and other resources allocated by the driver. You must not
5867 call any other MongoDB C Driver functions after mongoc_cleanup. Note
5868 that mongoc_init does not reinitialize the driver after mongoc_cleanup.
5869
5870 Deprecated feature: automatic initialization and cleanup
5871 On some platforms the driver can automatically call mongoc_init before
5872 main, and call mongoc_cleanup as the process exits. This is problematic
5873 in situations where related libraries also execute cleanup code on
5874 shutdown, and it creates inconsistent rules across platforms. Therefore
5875 the automatic initialization and cleanup feature is deprecated, and
5876 will be dropped in version 2.0. Meanwhile, for backward compatibility,
5877 the feature is enabled by default on platforms where it is available.
5878
5879 For portable, future-proof code, always call mongoc_init and mon‐
5880 goc_cleanup yourself, and configure the driver like:
5881
5882 cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO
5883
5884 Logging
5885 MongoDB C driver Logging Abstraction
5886
5887 Synopsis
5888 typedef enum {
5889 MONGOC_LOG_LEVEL_ERROR,
5890 MONGOC_LOG_LEVEL_CRITICAL,
5891 MONGOC_LOG_LEVEL_WARNING,
5892 MONGOC_LOG_LEVEL_MESSAGE,
5893 MONGOC_LOG_LEVEL_INFO,
5894 MONGOC_LOG_LEVEL_DEBUG,
5895 MONGOC_LOG_LEVEL_TRACE,
5896 } mongoc_log_level_t;
5897
5898 #define MONGOC_ERROR(...)
5899 #define MONGOC_CRITICAL(...)
5900 #define MONGOC_WARNING(...)
5901 #define MONGOC_MESSAGE(...)
5902 #define MONGOC_INFO(...)
5903 #define MONGOC_DEBUG(...)
5904
5905 typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
5906 const char *log_domain,
5907 const char *message,
5908 void *user_data);
5909
5910 void
5911 mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
5912 void
5913 mongoc_log (mongoc_log_level_t log_level,
5914 const char *log_domain,
5915 const char *format,
5916 ...) BSON_GNUC_PRINTF (3, 4);
5917 const char *
5918 mongoc_log_level_str (mongoc_log_level_t log_level);
5919 void
5920 mongoc_log_default_handler (mongoc_log_level_t log_level,
5921 const char *log_domain,
5922 const char *message,
5923 void *user_data);
5924 void
5925 mongoc_log_trace_enable (void);
5926 void
5927 mongoc_log_trace_disable (void);
5928
5929 The MongoDB C driver comes with an abstraction for logging that you can
5930 use in your application, or integrate with an existing logging system.
5931
5932 Macros
5933 To make logging a little less painful, various helper macros are pro‐
5934 vided. See the following example.
5935
5936 #undef MONGOC_LOG_DOMAIN
5937 #define MONGOC_LOG_DOMAIN "my-custom-domain"
5938
5939 MONGOC_WARNING ("An error occurred: %s", strerror (errno));
5940
5941 Custom Log Handlers
5942 The default log handler prints a timestamp and the log message to std‐
5943 out, or to stderr for warnings, critical messages, and errors.
5944 You can override the handler with mongoc_log_set_handler().
5945 Your handler function is called in a mutex for thread safety.
5946
5947 For example, you could register a custom handler to suppress messages
5948 at INFO level and below:
5949
5950 void
5951 my_logger (mongoc_log_level_t log_level,
5952 const char *log_domain,
5953 const char *message,
5954 void *user_data)
5955 {
5956 /* smaller values are more important */
5957 if (log_level < MONGOC_LOG_LEVEL_INFO) {
5958 mongoc_log_default_handler (log_level, log_domain, message, user_data);
5959 }
5960 }
5961
5962 int
5963 main (int argc, char *argv[])
5964 {
5965 mongoc_log_set_handler (my_logger, NULL);
5966 mongoc_init ();
5967
5968 /* ... your code ... */
5969
5970 mongoc_cleanup ();
5971 return 0;
5972 }
5973
5974 Note that in the example above mongoc_log_set_handler() is called be‐
5975 fore mongoc_init(). Otherwise, some log traces could not be processed
5976 by the log handler.
5977
5978 To restore the default handler:
5979
5980 mongoc_log_set_handler (mongoc_log_default_handler, NULL);
5981
5982 Disable logging
5983 To disable all logging, including warnings, critical messages and er‐
5984 rors, provide an empty log handler:
5985
5986 mongoc_log_set_handler (NULL, NULL);
5987
5988 Tracing
5989 If compiling your own copy of the MongoDB C driver, consider configur‐
5990 ing with -DENABLE_TRACING=ON to enable function tracing and hex dumps
5991 of network packets to STDERR and STDOUT during development and debug‐
5992 ging.
5993
5994 This is especially useful when debugging what may be going on inter‐
5995 nally in the driver.
5996
5997 Trace messages can be enabled and disabled by calling mon‐
5998 goc_log_trace_enable() and mongoc_log_trace_disable()
5999
6000 NOTE:
6001 Compiling the driver with -DENABLE_TRACING=ON will affect its per‐
6002 formance. Disabling tracing with mongoc_log_trace_disable() signifi‐
6003 cantly reduces the overhead, but cannot remove it completely.
6004 « index
6005
6006 Error Reporting
6007 Description
6008 Many C Driver functions report errors by returning false or -1 and
6009 filling out a bson_error_t structure with an error domain, error code,
6010 and message. Use domain to determine which subsystem generated the er‐
6011 ror, and code for the specific error. message is a human-readable error
6012 description.
6013
6014 See also: Handling Errors in libbson.
6015
6016 ┌────────────────────┬──────────────────────────────────┬────────────────────────┐
6017 │Domain │ Code │ Description │
6018 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6019 │MONGOC_ERROR_CLIENT │ MONGOC_ER‐ │ You tried to send a │
6020 │ │ ROR_CLIENT_TOO_BIG │ message larger than │
6021 │ │ │ the server's max │
6022 │ │ │ message size. │
6023 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6024 │ │ MONGOC_ER‐ │ Wrong credentials, │
6025 │ │ ROR_CLIENT_AUTHEN‐ │ or failure sending │
6026 │ │ TICATE │ or receiving au‐ │
6027 │ │ │ thentication mes‐ │
6028 │ │ │ sages. │
6029 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6030 │ │ MONGOC_ER‐ │ You tried an TLS │
6031 │ │ ROR_CLIENT_NO_AC‐ │ connection but the │
6032 │ │ CEPTABLE_PEER │ driver was not │
6033 │ │ │ built with TLS. │
6034 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6035 │ │ MONGOC_ER‐ │ You began iterating │
6036 │ │ ROR_CLIENT_IN_EX‐ │ an exhaust cursor, │
6037 │ │ HAUST │ then tried to begin │
6038 │ │ │ another operation │
6039 │ │ │ with the same mon‐ │
6040 │ │ │ goc_client_t. │
6041 └────────────────────┴──────────────────────────────────┴────────────────────────┘
6042
6043
6044 │ │ MONGOC_ER‐ │ Failure related to │
6045 │ │ ROR_CLIENT_SES‐ │ creating or using a │
6046 │ │ SION_FAILURE │ logical session. │
6047 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6048 │ │ MONGOC_ER‐ │ Failure related to │
6049 │ │ ROR_CLIENT_IN‐ │ arguments passed │
6050 │ │ VALID_ENCRYP‐ │ when initializing │
6051 │ │ TION_ARG │ Client-Side Field │
6052 │ │ │ Level Encryption. │
6053 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6054 │ │ MONGOC_ER‐ │ Failure related to │
6055 │ │ ROR_CLIENT_IN‐ │ Client-Side Field │
6056 │ │ VALID_ENCRYP‐ │ Level Encryption. │
6057 │ │ TION_STATE │ │
6058 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6059 │MONGOC_ERROR_STREAM │ MONGOC_ER‐ │ DNS failure. │
6060 │ │ ROR_STREAM_NAME_RES‐ │ │
6061 │ │ OLUTION │ │
6062 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6063 │ │ MONGOC_ER‐ │ Timeout communicat‐ │
6064 │ │ ROR_STREAM_SOCKET │ ing with server, or │
6065 │ │ │ connection closed. │
6066 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6067 │ │ MONGOC_ER‐ │ Failed to connect │
6068 │ │ ROR_STREAM_CONNECT │ to server. │
6069 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6070 │MONGOC_ERROR_PROTO‐ │ MONGOC_ERROR_PROTO‐ │ Corrupt response │
6071 │COL │ COL_INVALID_REPLY │ from server. │
6072 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6073 │ │ MONGOC_ERROR_PROTO‐ │ The server version │
6074 │ │ COL_BAD_WIRE_VERSION │ is too old or too │
6075 │ │ │ new to communicate │
6076 │ │ │ with the driver. │
6077 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6078 │MONGOC_ERROR_CURSOR │ MONGOC_ERROR_CUR‐ │ You passed bad ar‐ │
6079 │ │ SOR_INVALID_CURSOR │ guments to mon‐ │
6080 │ │ │ goc_collec‐ │
6081 │ │ │ tion_find_with_opts, │
6082 │ │ │ or you called mon‐ │
6083 │ │ │ goc_cursor_next on │
6084 │ │ │ a completed or │
6085 │ │ │ failed cursor, or │
6086 │ │ │ the cursor timed │
6087 │ │ │ out on the server. │
6088 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6089 │ │ MONGOC_ER‐ │ A resume token was │
6090 │ │ ROR_CHANGE_STREAM_NO_RE‐ │ not returned in a │
6091 │ │ SUME_TOKEN │ document found with │
6092 │ │ │ mon‐ │
6093 │ │ │ goc_change_stream_next │
6094 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6095 │MONGOC_ERROR_QUERY │ MONGOC_ERROR_QUERY_FAIL‐ │ Error API Version 1: │
6096 │ │ URE │ Server error from com‐ │
6097 │ │ │ mand or query. The │
6098 │ │ │ server error message │
6099 │ │ │ is in message. │
6100 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6101 │MONGOC_ERROR_SERVER │ MONGOC_ERROR_QUERY_FAIL‐ │ Error API Version 2: │
6102 │ │ URE │ Server error from com‐ │
6103 │ │ │ mand or query. The │
6104 │ │ │ server error message │
6105 │ │ │ is in message. │
6106 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6107 │MONGOC_ERROR_SASL │ A SASL error code. │ man sasl_errors for a │
6108 │ │ │ list of codes. │
6109 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6110 │MONGOC_ERROR_BSON │ MONGOC_ERROR_BSON_IN‐ │ You passed an invalid │
6111 │ │ VALID │ or oversized BSON doc‐ │
6112 │ │ │ ument as a parameter, │
6113 │ │ │ or called mongoc_col‐ │
6114 │ │ │ lection_create_index │
6115 │ │ │ with invalid keys, or │
6116 │ │ │ the server reply was │
6117 │ │ │ corrupt. │
6118 └────────────────────┴──────────────────────────────────┴────────────────────────┘
6119
6120
6121 │MONGOC_ERROR_NAME‐ │ MONGOC_ERROR_NAME‐ │ You tried to create a │
6122 │SPACE │ SPACE_INVALID │ collection with an in‐ │
6123 │ │ │ valid name. │
6124 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6125 │MONGOC_ERROR_COM‐ │ MONGOC_ERROR_COMMAND_IN‐ │ Many functions set │
6126 │MAND │ VALID_ARG │ this error code when │
6127 │ │ │ passed bad parameters. │
6128 │ │ │ Print the error mes‐ │
6129 │ │ │ sage for details. │
6130 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6131 │ │ MONGOC_ERROR_PROTO‐ │ You tried to use a │
6132 │ │ COL_BAD_WIRE_VERSION │ command option the │
6133 │ │ │ server does not sup‐ │
6134 │ │ │ port. │
6135 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6136 │ │ MONGOC_ERROR_DUPLI‐ │ An insert or update │
6137 │ │ CATE_KEY │ failed because because │
6138 │ │ │ of a duplicate _id or │
6139 │ │ │ other unique-index vi‐ │
6140 │ │ │ olation. │
6141 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6142 │ │ MONGOC_ER‐ │ The operation failed │
6143 │ │ ROR_MAX_TIME_MS_EXPIRED │ because maxTimeMS ex‐ │
6144 │ │ │ pired. │
6145 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6146 │ │ MONGOC_ERROR_SERVER_SE‐ │ The serverId option │
6147 │ │ LECTION_INVALID_ID │ for an operation con‐ │
6148 │ │ │ flicts with the pinned │
6149 │ │ │ server for that opera‐ │
6150 │ │ │ tion's client session │
6151 │ │ │ (denoted by the ses‐ │
6152 │ │ │ sionId option). │
6153 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6154 │MONGOC_ERROR_COM‐ │ Error code from server. │ Error API Version 1: │
6155 │MAND │ │ Server error from a │
6156 │ │ │ command. The server │
6157 │ │ │ error message is in │
6158 │ │ │ message. │
6159 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6160 │MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: │
6161 │ │ │ Server error from a │
6162 │ │ │ command. The server │
6163 │ │ │ error message is in │
6164 │ │ │ message. │
6165 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6166 │MONGOC_ERROR_COL‐ │ MONGOC_ERROR_COLLEC‐ │ Invalid or empty input │
6167 │LECTION │ TION_INSERT_FAILED, MON‐ │ to mongoc_collec‐ │
6168 │ │ GOC_ERROR_COLLECTION_UP‐ │ tion_insert_one, mon‐ │
6169 │ │ DATE_FAILED, MONGOC_ER‐ │ goc_collection_in‐ │
6170 │ │ ROR_COLLEC‐ │ sert_bulk, mongoc_col‐ │
6171 │ │ TION_DELETE_FAILED. │ lection_update_one, │
6172 │ │ │ mongoc_collection_up‐ │
6173 │ │ │ date_many, mongoc_col‐ │
6174 │ │ │ lection_replace_one, │
6175 │ │ │ mongoc_collec‐ │
6176 │ │ │ tion_delete_one, or │
6177 │ │ │ mongoc_collec‐ │
6178 │ │ │ tion_delete_many. │
6179 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6180 │MONGOC_ERROR_COL‐ │ Error code from server. │ Error API Version 1: │
6181 │LECTION │ │ Server error from mon‐ │
6182 │ │ │ goc_collection_in‐ │
6183 │ │ │ sert_one, mongoc_col‐ │
6184 │ │ │ lection_insert_bulk, │
6185 │ │ │ mongoc_collection_up‐ │
6186 │ │ │ date_one, mongoc_col‐ │
6187 │ │ │ lection_update_many, │
6188 │ │ │ mongoc_collection_re‐ │
6189 │ │ │ place_one, │
6190 └────────────────────┴──────────────────────────────────┴────────────────────────┘
6191
6192
6193
6194
6195
6196
6197
6198 │MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: │
6199 │ │ │ Server error from mon‐ │
6200 │ │ │ goc_collection_in‐ │
6201 │ │ │ sert_one, mongoc_col‐ │
6202 │ │ │ lection_insert_bulk, │
6203 │ │ │ mongoc_collection_up‐ │
6204 │ │ │ date_one, mongoc_col‐ │
6205 │ │ │ lection_update_many, │
6206 │ │ │ mongoc_collection_re‐ │
6207 │ │ │ place_one, │
6208 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6209 │MONGOC_ERROR_GRIDFS │ MONGOC_ER‐ │ The GridFS file is │
6210 │ │ ROR_GRIDFS_CHUNK_MISSING │ missing a document in │
6211 │ │ │ its chunks collection. │
6212 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6213 │ │ MONGOC_ERROR_GRIDFS_COR‐ │ A data inconsistency │
6214 │ │ RUPT │ was detected in │
6215 │ │ │ GridFS. │
6216 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6217 │ │ MONGOC_ERROR_GRIDFS_IN‐ │ You passed a NULL │
6218 │ │ VALID_FILENAME │ filename to mon‐ │
6219 │ │ │ goc_gridfs_re‐ │
6220 │ │ │ move_by_filename. │
6221 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6222 │ │ MONGOC_ERROR_GRIDFS_PRO‐ │ You called mon‐ │
6223 │ │ TOCOL_ERROR │ goc_gridfs_file_set_id │
6224 │ │ │ after mon‐ │
6225 │ │ │ goc_gridfs_file_save, │
6226 │ │ │ or tried to write on a │
6227 │ │ │ closed GridFS stream. │
6228 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6229 │ │ MONGOC_ER‐ │ A GridFS file is miss‐ │
6230 │ │ ROR_GRIDFS_BUCKET_FILE_NOT_FOUND │ ing from files collec‐ │
6231 │ │ │ tion. │
6232 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6233 │ │ MONGOC_ER‐ │ An error occurred on a │
6234 │ │ ROR_GRIDFS_BUCKET_STREAM │ stream created from a │
6235 │ │ │ GridFS operation like │
6236 │ │ │ mon‐ │
6237 │ │ │ goc_gridfs_bucket_up‐ │
6238 │ │ │ load_from_stream. │
6239 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6240 │MONGOC_ERROR_SCRAM │ MONGOC_ERROR_SCRAM_PROTOCOL_ER‐ │ Failure in SCRAM-SHA-1 │
6241 │ │ ROR │ authentication. │
6242 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6243 │MONGOC_ER‐ │ MONGOC_ERROR_SERVER_SELEC‐ │ No replica set member │
6244 │ROR_SERVER_SELEC‐ │ TION_FAILURE │ or mongos is avail‐ │
6245 │TION │ │ able, or none matches │
6246 │ │ │ your read preference, │
6247 │ │ │ or you supplied an in‐ │
6248 │ │ │ valid mon‐ │
6249 │ │ │ goc_read_prefs_t. │
6250 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6251 │MONGOC_ER‐ │ Error code from server. │ There was a write con‐ │
6252 │ROR_WRITE_CONCERN │ │ cern error or timeout │
6253 │ │ │ from the server. │
6254 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6255 │MONGOC_ERROR_TRANS‐ │ MONGOC_ERROR_TRANSACTION_INVALID │ You attempted to start │
6256 │ACTION │ │ a transaction when one │
6257 │ │ │ is already in │
6258 │ │ │ progress, or commit or │
6259 │ │ │ abort when there is no │
6260 │ │ │ transaction. │
6261 ├────────────────────┼──────────────────────────────────┼────────────────────────┤
6262 │MONGOC_ER‐ │ Error code produced by libmon‐ │ An error occurred in │
6263 │ROR_CLIENT_SIDE_EN‐ │ gocrypt. │ the library responsi‐ │
6264 │CRYPTION │ │ ble for Client Side │
6265 │ │ │ Encryption │
6266 └────────────────────┴──────────────────────────────────┴────────────────────────┘
6267
6268 Error Labels
6269 In some cases your application must make decisions based on what cate‐
6270 gory of error the driver has returned, but these categories do not cor‐
6271 respond perfectly to an error domain or code. In such cases, error la‐
6272 bels provide a reliable way to determine how your application should
6273 respond to an error.
6274
6275 Any C Driver function that has a bson_t out-parameter named reply may
6276 include error labels to the reply, in the form of a BSON field named
6277 "errorLabels" containing an array of strings:
6278
6279 { "errorLabels": [ "TransientTransactionError" ] }
6280
6281 Use mongoc_error_has_label to test if a reply contains a specific la‐
6282 bel. See mongoc_client_session_start_transaction for example code that
6283 demonstrates the use of error labels in application logic.
6284
6285 The following error labels are currently defined. Future versions of
6286 MongoDB may introduce new labels.
6287
6288 TransientTransactionError
6289 Within a multi-document transaction, certain errors can leave the
6290 transaction in an unknown or aborted state. These include write con‐
6291 flicts, primary stepdowns, and network errors. In response, the appli‐
6292 cation should abort the transaction and try the same sequence of opera‐
6293 tions again in a new transaction.
6294
6295 UnknownTransactionCommitResult
6296 When mongoc_client_session_commit_transaction encounters a network er‐
6297 ror or certain server errors, it is not known whether the transaction
6298 was committed. Applications should attempt to commit the transaction
6299 again until: the commit succeeds, the commit fails with an error not
6300 labeled "UnknownTransactionCommitResult", or the application chooses to
6301 give up.
6302
6303 Setting the Error API Version
6304 The driver's error reporting began with a design flaw: when the error
6305 domain is MONGOC_ERROR_COLLECTION, MONGOC_ERROR_QUERY, or MONGOC_ER‐
6306 ROR_COMMAND, the error code might originate from the server or the
6307 driver. An application cannot always know where an error originated,
6308 and therefore cannot tell what the code means.
6309
6310 For example, if mongoc_collection_update_one sets the error's domain to
6311 MONGOC_ERROR_COLLECTION and its code to 24, the application cannot know
6312 whether 24 is the generic driver error code MONGOC_ERROR_COLLECTION_UP‐
6313 DATE_FAILED or the specific server error code "LockTimeout".
6314
6315 To fix this flaw while preserving backward compatibility, the C Driver
6316 1.4 introduces "Error API Versions". Version 1, the default Error API
6317 Version, maintains the flawed behavior. Version 2 adds a new error do‐
6318 main, MONGOC_ERROR_SERVER. In Version 2, error codes originating on the
6319 server always have error domain MONGOC_ERROR_SERVER or MONGOC_ER‐
6320 ROR_WRITE_CONCERN. When the driver uses Version 2 the application can
6321 always determine the origin and meaning of error codes. New applica‐
6322 tions should use Version 2, and existing applications should be updated
6323 to use Version 2 as well.
6324
6325 ┌──────────────────────┬────────────────────┬─────────────────────┐
6326 │Error Source │ API Version 1 │ API Version 2 │
6327 ├──────────────────────┼────────────────────┼─────────────────────┤
6328 │mongoc_cursor_error │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6329 ├──────────────────────┼────────────────────┼─────────────────────┤
6330 │mongoc_client_com‐ │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6331 │mand_with_opts, │ │ │
6332 │mongoc_data‐ │ │ │
6333 │base_com‐ │ │ │
6334 │mand_with_opts, and │ │ │
6335 │other command func‐ │ │ │
6336 │tions │ │ │
6337 ├──────────────────────┼────────────────────┼─────────────────────┤
6338 │mongoc_collec‐ │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6339 │tion_count_with_opts │ │ │
6340 │mon‐ │ │ │
6341 │goc_client_get_data‐ │ │ │
6342 │base_names_with_opts, │ │ │
6343 │and other command │ │ │
6344 │helper functions │ │ │
6345 └──────────────────────┴────────────────────┴─────────────────────┘
6346
6347
6348
6349
6350
6351
6352 │mongoc_collection_in‐ │ MONGOC_ERROR_COM‐ │ MONGOC_ERROR_SERVER │
6353 │sert_one mongoc_col‐ │ MAND │ │
6354 │lection_insert_bulk │ │ │
6355 │mongoc_collection_up‐ │ │ │
6356 │date_one mongoc_col‐ │ │ │
6357 │lection_update_many │ │ │
6358 │mongoc_collection_re‐ │ │ │
6359 │place_one mongoc_col‐ │ │ │
6360 │lection_delete_one │ │ │
6361 │mongoc_collec‐ │ │ │
6362 │tion_delete_many │ │ │
6363 ├──────────────────────┼────────────────────┼─────────────────────┤
6364 │mongoc_bulk_opera‐ │ MONGOC_ERROR_COM‐ │ MONGOC_ERROR_SERVER │
6365 │tion_execute │ MAND │ │
6366 ├──────────────────────┼────────────────────┼─────────────────────┤
6367 │Write-concern timeout │ MONGOC_ER‐ │ MONGOC_ER‐ │
6368 │ │ ROR_WRITE_CONCERN │ ROR_WRITE_CONCERN │
6369 └──────────────────────┴────────────────────┴─────────────────────┘
6370
6371 The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY
6372 and MONGOC_ERROR_API_VERSION_2. Set the version with mon‐
6373 goc_client_set_error_api or mongoc_client_pool_set_error_api.
6374
6375 See Also
6376 MongoDB Server Error Codes
6377
6378 Object Lifecycle
6379 This page documents the order of creation and destruction for libmon‐
6380 goc's main struct types.
6381
6382 Clients and pools
6383 Call mongoc_init() once, before calling any other libmongoc functions,
6384 and call mongoc_cleanup() once before your program exits.
6385
6386 A program that uses libmongoc from multiple threads should create a
6387 mongoc_client_pool_t with mongoc_client_pool_new(). Each thread ac‐
6388 quires a mongoc_client_t from the pool with mongoc_client_pool_pop()
6389 and returns it with mongoc_client_pool_push() when the thread is fin‐
6390 ished using it. To destroy the pool, first return all clients, then
6391 call mongoc_client_pool_destroy().
6392
6393 If your program uses libmongoc from only one thread, create a mon‐
6394 goc_client_t directly with mongoc_client_new() or mon‐
6395 goc_client_new_from_uri(). Destroy it with mongoc_client_destroy().
6396
6397 Databases, collections, and related objects
6398 You can create a mongoc_database_t or mongoc_collection_t from a mon‐
6399 goc_client_t, and create a mongoc_cursor_t or mongoc_bulk_operation_t
6400 from a mongoc_collection_t.
6401
6402 Each of these objects must be destroyed before the client they were
6403 created from, but their lifetimes are otherwise independent.
6404
6405 GridFS objects
6406 You can create a mongoc_gridfs_t from a mongoc_client_t, create a mon‐
6407 goc_gridfs_file_t or mongoc_gridfs_file_list_t from a mongoc_gridfs_t,
6408 create a mongoc_gridfs_file_t from a mongoc_gridfs_file_list_t, and
6409 create a mongoc_stream_t from a mongoc_gridfs_file_t.
6410
6411 Each of these objects depends on the object it was created from. Always
6412 destroy GridFS objects in the reverse of the order they were created.
6413 The sole exception is that a mongoc_gridfs_file_t need not be destroyed
6414 before the mongoc_gridfs_file_list_t it was created from.
6415
6416 GridFS bucket objects
6417 Create mongoc_gridfs_bucket_t with a mongoc_database_t derived from a
6418 mongoc_client_t. The mongoc_database_t is independent from the mon‐
6419 goc_gridfs_bucket_t. But the mongoc_client_t must outlive the mon‐
6420 goc_gridfs_bucket_t.
6421
6422 A mongoc_stream_t may be created from the mongoc_gridfs_bucket_t. The
6423 mongoc_gridfs_bucket_t must outlive the mongoc_stream_t.
6424
6425 Sessions
6426 Start a session with mongoc_client_start_session, use the session for a
6427 sequence of operations and multi-document transactions, then free it
6428 with mongoc_client_session_destroy(). Any mongoc_cursor_t or mon‐
6429 goc_change_stream_t using a session must be destroyed before the ses‐
6430 sion, and a session must be destroyed before the mongoc_client_t it
6431 came from.
6432
6433 By default, sessions are causally consistent. To disable causal consis‐
6434 tency, before starting a session create a mongoc_session_opt_t with
6435 mongoc_session_opts_new() and call mongoc_session_opts_set_causal_con‐
6436 sistency(), then free the struct with mongoc_session_opts_destroy.
6437
6438 Unacknowledged writes are prohibited with sessions.
6439
6440 A mongoc_client_session_t must be used by only one thread at a time.
6441 Due to session pooling, mongoc_client_start_session may return a ses‐
6442 sion that has been idle for some time and is about to be closed after
6443 its idle timeout. Use the session within one minute of acquiring it to
6444 refresh the session and avoid a timeout.
6445
6446 Client Side Encryption
6447 When configuring a mongoc_client_t for automatic encryption via mon‐
6448 goc_client_enable_auto_encryption(), if a separate key vault client is
6449 set in the options (via mongoc_auto_encryption_opts_set_key‐
6450 vault_client()) the key vault client must outlive the encrypted client.
6451
6452 When configuring a mongoc_client_pool_t for automatic encryption via
6453 mongoc_client_pool_enable_auto_encryption(), if a separate key vault
6454 client pool is set in the options (via mongoc_auto_encryp‐
6455 tion_opts_set_keyvault_client_pool()) the key vault client pool must
6456 outlive the encrypted client pool.
6457
6458 When creating a mongoc_client_encryption_t, the configured key vault
6459 client (set via mongoc_client_encryption_opts_set_keyvault_client())
6460 must outlive the mongoc_client_encryption_t.
6461
6462 GridFS
6463 The C driver includes two APIs for GridFS.
6464
6465 The older API consists of mongoc_gridfs_t and its derivatives. It con‐
6466 tains deprecated API, does not support read preferences, and is not
6467 recommended in new applications. It does not conform to the MongoDB
6468 GridFS specification.
6469
6470 The newer API consists of mongoc_gridfs_bucket_t and allows upload‐
6471 ing/downloading through derived mongoc_stream_t objects. It conforms to
6472 the MongoDB GridFS specification.
6473
6474 There is not always a straightforward upgrade path from an application
6475 built with mongoc_gridfs_t to mongoc_gridfs_bucket_t (e.g. a mon‐
6476 goc_gridfs_file_t provides functions to seek but mongoc_stream_t does
6477 not). But users are encouraged to upgrade when possible.
6478
6479 mongoc_auto_encryption_opts_t
6480 Options for enabling automatic encryption and decryption for
6481 Client-Side Field Level Encryption.
6482
6483 Synopsis
6484 typedef struct _mongoc_auto_encryption_opts_t mongoc_auto_encryption_opts_t;
6485
6486 See Also
6487 • The guide for Using Client-Side Field Level Encryption
6488
6489 mongoc_bulk_operation_t
6490 Bulk Write Operations
6491
6492 Synopsis
6493 typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t;
6494
6495 The opaque type mongoc_bulk_operation_t provides an abstraction for
6496 submitting multiple write operations as a single batch.
6497
6498 After adding all of the write operations to the mongoc_bulk_opera‐
6499 tion_t, call mongoc_bulk_operation_execute() to execute the operation.
6500
6501 WARNING:
6502 It is only valid to call mongoc_bulk_operation_execute() once. The
6503 mongoc_bulk_operation_t must be destroyed afterwards.
6504
6505 See Also
6506 Bulk Write Operations
6507
6508 mongoc_change_stream_t
6509 Synopsis
6510 #include <mongoc/mongoc.h>
6511
6512 typedef struct _mongoc_change_stream_t mongoc_change_stream_t;
6513
6514 mongoc_change_stream_t is a handle to a change stream. A collection
6515 change stream can be obtained using mongoc_collection_watch.
6516
6517 It is recommended to use a mongoc_change_stream_t and its functions in‐
6518 stead of a raw aggregation with a $changeStream stage. For more infor‐
6519 mation see the MongoDB Manual Entry on Change Streams.
6520
6521 Example
6522 example-collection-watch.c
6523
6524 #include <mongoc/mongoc.h>
6525
6526 int
6527 main ()
6528 {
6529 bson_t empty = BSON_INITIALIZER;
6530 const bson_t *doc;
6531 bson_t *to_insert = BCON_NEW ("x", BCON_INT32 (1));
6532 const bson_t *err_doc;
6533 bson_error_t error;
6534 const char *uri_string;
6535 mongoc_uri_t *uri;
6536 mongoc_client_t *client;
6537 mongoc_collection_t *coll;
6538 mongoc_change_stream_t *stream;
6539 mongoc_write_concern_t *wc = mongoc_write_concern_new ();
6540 bson_t opts = BSON_INITIALIZER;
6541 bool r;
6542
6543 mongoc_init ();
6544
6545 uri_string = "mongodb://"
6546 "localhost:27017,localhost:27018,localhost:"
6547 "27019/db?replicaSet=rs0";
6548
6549 uri = mongoc_uri_new_with_error (uri_string, &error);
6550 if (!uri) {
6551 fprintf (stderr,
6552 "failed to parse URI: %s\n"
6553 "error message: %s\n",
6554 uri_string,
6555 error.message);
6556 return EXIT_FAILURE;
6557 }
6558
6559 client = mongoc_client_new_from_uri (uri);
6560 if (!client) {
6561 return EXIT_FAILURE;
6562 }
6563
6564 coll = mongoc_client_get_collection (client, "db", "coll");
6565 stream = mongoc_collection_watch (coll, &empty, NULL);
6566
6567 mongoc_write_concern_set_wmajority (wc, 10000);
6568 mongoc_write_concern_append (wc, &opts);
6569 r = mongoc_collection_insert_one (coll, to_insert, &opts, NULL, &error);
6570 if (!r) {
6571 fprintf (stderr, "Error: %s\n", error.message);
6572 return EXIT_FAILURE;
6573 }
6574
6575 while (mongoc_change_stream_next (stream, &doc)) {
6576 char *as_json = bson_as_relaxed_extended_json (doc, NULL);
6577 fprintf (stderr, "Got document: %s\n", as_json);
6578 bson_free (as_json);
6579 }
6580
6581 if (mongoc_change_stream_error_document (stream, &error, &err_doc)) {
6582 if (!bson_empty (err_doc)) {
6583 fprintf (stderr,
6584 "Server Error: %s\n",
6585 bson_as_relaxed_extended_json (err_doc, NULL));
6586 } else {
6587 fprintf (stderr, "Client Error: %s\n", error.message);
6588 }
6589 return EXIT_FAILURE;
6590 }
6591
6592 bson_destroy (to_insert);
6593 mongoc_write_concern_destroy (wc);
6594 bson_destroy (&opts);
6595 mongoc_change_stream_destroy (stream);
6596 mongoc_collection_destroy (coll);
6597 mongoc_uri_destroy (uri);
6598 mongoc_client_destroy (client);
6599 mongoc_cleanup ();
6600
6601 return EXIT_SUCCESS;
6602 }
6603
6604
6605 Starting and Resuming
6606 All watch functions accept several options to indicate where a change
6607 stream should start returning changes from: resumeAfter, startAfter,
6608 and startAtOperationTime.
6609
6610 All changes returned by mongoc_change_stream_next include a resume to‐
6611 ken in the _id field. MongoDB 4.2 also includes an additional resume
6612 token in each "aggregate" and "getMore" command response, which points
6613 to the end of that response's batch. The current token is automatically
6614 cached by libmongoc. In the event of an error, libmongoc attempts to
6615 recreate the change stream starting where it left off by passing the
6616 cached resume token. libmongoc only attempts to resume once, but client
6617 applications can access the cached resume token with mon‐
6618 goc_change_stream_get_resume_token and use it for their own resume
6619 logic by passing it as either the resumeAfter or startAfter option.
6620
6621 Additionally, change streams can start returning changes at an opera‐
6622 tion time by using the startAtOperationTime field. This can be the
6623 timestamp returned in the operationTime field of a command reply.
6624
6625 resumeAfter, startAfter, and startAtOperationTime are mutually exclu‐
6626 sive options. Setting more than one will result in a server error.
6627
6628 The following example implements custom resuming logic, persisting the
6629 resume token in a file.
6630
6631 example-resume.c
6632
6633 #include <mongoc/mongoc.h>
6634
6635 /* An example implementation of custom resume logic in a change stream.
6636 * example-resume starts a client-wide change stream and persists the resume
6637 * token in a file "resume-token.json". On restart, if "resume-token.json"
6638 * exists, the change stream starts watching after the persisted resume token.
6639 *
6640 * This behavior allows a user to exit example-resume, and restart it later
6641 * without missing any change events.
6642 */
6643 #include <unistd.h>
6644
6645 static const char *RESUME_TOKEN_PATH = "resume-token.json";
6646
6647 static bool
6648 _save_resume_token (const bson_t *doc)
6649 {
6650 FILE *file_stream;
6651 bson_iter_t iter;
6652 bson_t resume_token_doc;
6653 char *as_json = NULL;
6654 size_t as_json_len;
6655 ssize_t r, n_written;
6656 const bson_value_t *resume_token;
6657
6658 if (!bson_iter_init_find (&iter, doc, "_id")) {
6659 fprintf (stderr, "reply does not contain operationTime.");
6660 return false;
6661 }
6662 resume_token = bson_iter_value (&iter);
6663 /* store the resume token in a document, { resumeAfter: <resume token> }
6664 * which we can later append easily. */
6665 file_stream = fopen (RESUME_TOKEN_PATH, "w+");
6666 if (!file_stream) {
6667 fprintf (stderr, "failed to open %s for writing\n", RESUME_TOKEN_PATH);
6668 return false;
6669 }
6670 bson_init (&resume_token_doc);
6671 BSON_APPEND_VALUE (&resume_token_doc, "resumeAfter", resume_token);
6672 as_json = bson_as_canonical_extended_json (&resume_token_doc, &as_json_len);
6673 bson_destroy (&resume_token_doc);
6674 n_written = 0;
6675 while (n_written < as_json_len) {
6676 r = fwrite ((void *) (as_json + n_written),
6677 sizeof (char),
6678 as_json_len - n_written,
6679 file_stream);
6680 if (r == -1) {
6681 fprintf (stderr, "failed to write to %s\n", RESUME_TOKEN_PATH);
6682 bson_free (as_json);
6683 fclose (file_stream);
6684 return false;
6685 }
6686 n_written += r;
6687 }
6688
6689 bson_free (as_json);
6690 fclose (file_stream);
6691 return true;
6692 }
6693
6694 bool
6695 _load_resume_token (bson_t *opts)
6696 {
6697 bson_error_t error;
6698 bson_json_reader_t *reader;
6699 bson_t doc;
6700
6701 /* if the file does not exist, skip. */
6702 if (-1 == access (RESUME_TOKEN_PATH, R_OK)) {
6703 return true;
6704 }
6705 reader = bson_json_reader_new_from_file (RESUME_TOKEN_PATH, &error);
6706 if (!reader) {
6707 fprintf (stderr,
6708 "failed to open %s for reading: %s\n",
6709 RESUME_TOKEN_PATH,
6710 error.message);
6711 return false;
6712 }
6713
6714 bson_init (&doc);
6715 if (-1 == bson_json_reader_read (reader, &doc, &error)) {
6716 fprintf (stderr, "failed to read doc from %s\n", RESUME_TOKEN_PATH);
6717 bson_destroy (&doc);
6718 bson_json_reader_destroy (reader);
6719 return false;
6720 }
6721
6722 printf ("found cached resume token in %s, resuming change stream.\n",
6723 RESUME_TOKEN_PATH);
6724
6725 bson_concat (opts, &doc);
6726 bson_destroy (&doc);
6727 bson_json_reader_destroy (reader);
6728 return true;
6729 }
6730
6731 int
6732 main ()
6733 {
6734 int exit_code = EXIT_FAILURE;
6735 const char *uri_string;
6736 mongoc_uri_t *uri = NULL;
6737 bson_error_t error;
6738 mongoc_client_t *client = NULL;
6739 bson_t pipeline = BSON_INITIALIZER;
6740 bson_t opts = BSON_INITIALIZER;
6741 mongoc_change_stream_t *stream = NULL;
6742 const bson_t *doc;
6743
6744 const int max_time = 30; /* max amount of time, in seconds, that
6745 mongoc_change_stream_next can block. */
6746
6747 mongoc_init ();
6748 uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
6749 uri = mongoc_uri_new_with_error (uri_string, &error);
6750 if (!uri) {
6751 fprintf (stderr,
6752 "failed to parse URI: %s\n"
6753 "error message: %s\n",
6754 uri_string,
6755 error.message);
6756 goto cleanup;
6757 }
6758
6759 client = mongoc_client_new_from_uri (uri);
6760 if (!client) {
6761 goto cleanup;
6762 }
6763
6764 if (!_load_resume_token (&opts)) {
6765 goto cleanup;
6766 }
6767 BSON_APPEND_INT64 (&opts, "maxAwaitTimeMS", max_time * 1000);
6768
6769 printf ("listening for changes on the client (max %d seconds).\n", max_time);
6770 stream = mongoc_client_watch (client, &pipeline, &opts);
6771
6772 while (mongoc_change_stream_next (stream, &doc)) {
6773 char *as_json;
6774
6775 as_json = bson_as_canonical_extended_json (doc, NULL);
6776 printf ("change received: %s\n", as_json);
6777 bson_free (as_json);
6778 if (!_save_resume_token (doc)) {
6779 goto cleanup;
6780 }
6781 }
6782
6783 exit_code = EXIT_SUCCESS;
6784
6785 cleanup:
6786 mongoc_uri_destroy (uri);
6787 bson_destroy (&pipeline);
6788 bson_destroy (&opts);
6789 mongoc_change_stream_destroy (stream);
6790 mongoc_client_destroy (client);
6791 mongoc_cleanup ();
6792 return exit_code;
6793 }
6794
6795
6796 The following example shows using startAtOperationTime to synchronize a
6797 change stream with another operation.
6798
6799 example-start-at-optime.c
6800
6801 /* An example of starting a change stream with startAtOperationTime. */
6802 #include <mongoc/mongoc.h>
6803
6804 int
6805 main ()
6806 {
6807 int exit_code = EXIT_FAILURE;
6808 const char *uri_string;
6809 mongoc_uri_t *uri = NULL;
6810 bson_error_t error;
6811 mongoc_client_t *client = NULL;
6812 mongoc_collection_t *coll = NULL;
6813 bson_t pipeline = BSON_INITIALIZER;
6814 bson_t opts = BSON_INITIALIZER;
6815 mongoc_change_stream_t *stream = NULL;
6816 bson_iter_t iter;
6817 const bson_t *doc;
6818 bson_value_t cached_operation_time = {0};
6819 int i;
6820 bool r;
6821
6822 mongoc_init ();
6823 uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
6824 uri = mongoc_uri_new_with_error (uri_string, &error);
6825 if (!uri) {
6826 fprintf (stderr,
6827 "failed to parse URI: %s\n"
6828 "error message: %s\n",
6829 uri_string,
6830 error.message);
6831 goto cleanup;
6832 }
6833
6834 client = mongoc_client_new_from_uri (uri);
6835 if (!client) {
6836 goto cleanup;
6837 }
6838
6839 /* insert five documents. */
6840 coll = mongoc_client_get_collection (client, "db", "coll");
6841 for (i = 0; i < 5; i++) {
6842 bson_t reply;
6843 bson_t *insert_cmd = BCON_NEW ("insert",
6844 "coll",
6845 "documents",
6846 "[",
6847 "{",
6848 "x",
6849 BCON_INT64 (i),
6850 "}",
6851 "]");
6852
6853 r = mongoc_collection_write_command_with_opts (
6854 coll, insert_cmd, NULL, &reply, &error);
6855 bson_destroy (insert_cmd);
6856 if (!r) {
6857 bson_destroy (&reply);
6858 fprintf (stderr, "failed to insert: %s\n", error.message);
6859 goto cleanup;
6860 }
6861 if (i == 0) {
6862 /* cache the operation time in the first reply. */
6863 if (bson_iter_init_find (&iter, &reply, "operationTime")) {
6864 bson_value_copy (bson_iter_value (&iter), &cached_operation_time);
6865 } else {
6866 fprintf (stderr, "reply does not contain operationTime.");
6867 bson_destroy (&reply);
6868 goto cleanup;
6869 }
6870 }
6871 bson_destroy (&reply);
6872 }
6873
6874 /* start a change stream at the first returned operationTime. */
6875 BSON_APPEND_VALUE (&opts, "startAtOperationTime", &cached_operation_time);
6876 stream = mongoc_collection_watch (coll, &pipeline, &opts);
6877
6878 /* since the change stream started at the operation time of the first
6879 * insert, the five inserts are returned. */
6880 printf ("listening for changes on db.coll:\n");
6881 while (mongoc_change_stream_next (stream, &doc)) {
6882 char *as_json;
6883
6884 as_json = bson_as_canonical_extended_json (doc, NULL);
6885 printf ("change received: %s\n", as_json);
6886 bson_free (as_json);
6887 }
6888
6889 exit_code = EXIT_SUCCESS;
6890
6891 cleanup:
6892 mongoc_uri_destroy (uri);
6893 bson_destroy (&pipeline);
6894 bson_destroy (&opts);
6895 if (cached_operation_time.value_type) {
6896 bson_value_destroy (&cached_operation_time);
6897 }
6898 mongoc_change_stream_destroy (stream);
6899 mongoc_collection_destroy (coll);
6900 mongoc_client_destroy (client);
6901 mongoc_cleanup ();
6902 return exit_code;
6903 }
6904
6905
6906 mongoc_client_encryption_t
6907 Synopsis
6908 typedef struct _mongoc_client_encryption_t mongoc_client_encryption_t;
6909
6910 mongoc_client_encryption_t provides utility functions for Client-Side
6911 Field Level Encryption. See the guide for Using Client-Side Field Level
6912 Encryption.
6913
6914 Thread Safety
6915 mongoc_client_encryption_t is NOT thread-safe and should only be used
6916 in the same thread as the mongoc_client_t that is configured via mon‐
6917 goc_client_encryption_opts_set_keyvault_client().
6918
6919 Lifecycle
6920 The key vault client, configured via mongoc_client_encryp‐
6921 tion_opts_set_keyvault_client(), must outlive the mongoc_client_encryp‐
6922 tion_t.
6923
6924 See also
6925 • mongoc_client_enable_auto_encryption()
6926
6927 • mongoc_client_pool_enable_auto_encryption()
6928
6929 • The guide for Using Client-Side Field Level Encryption for libmongoc
6930
6931 • The MongoDB Manual for Client-Side Field Level Encryption
6932
6933 mongoc_client_encryption_datakey_opts_t
6934 Synopsis
6935 typedef struct _mongoc_client_encryption_datakey_opts_t mongoc_client_encryption_datakey_opts_t;
6936
6937 Used to set options for mongoc_client_encryption_create_datakey().
6938
6939 See also
6940 • mongoc_client_encryption_create_datakey()
6941
6942 mongoc_client_encryption_encrypt_opts_t
6943 Synopsis
6944 typedef struct _mongoc_client_encryption_encrypt_opts_t mongoc_client_encryption_encrypt_opts_t;
6945
6946 Used to set options for mongoc_client_encryption_encrypt().
6947
6948 See also
6949 • mongoc_client_encryption_encrypt()
6950
6951 mongoc_client_encryption_opts_t
6952 Synopsis
6953 typedef struct _mongoc_client_encryption_opts_t mongoc_client_encryption_opts_t;
6954
6955 Used to set options for mongoc_client_encryption_new().
6956
6957 See also
6958 • mongoc_client_encryption_new()
6959
6960 mongoc_client_pool_t
6961 A connection pool for multi-threaded programs. See connection-pooling.
6962
6963 Synopsis
6964 typedef struct _mongoc_client_pool_t mongoc_client_pool_t
6965
6966 mongoc_client_pool_t is the basis for multi-threading in the MongoDB C
6967 driver. Since mongoc_client_t structures are not thread-safe, this
6968 structure is used to retrieve a new mongoc_client_t for a given thread.
6969 This structure is thread-safe, except for its destructor method, mon‐
6970 goc_client_pool_destroy, which is not thread-safe and must only be
6971 called from one thread.
6972
6973 Example
6974 example-pool.c
6975
6976 /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
6977 * libmongoc-1.0) */
6978
6979 /* ./example-pool [CONNECTION_STRING] */
6980
6981 #include <mongoc/mongoc.h>
6982 #include <pthread.h>
6983 #include <stdio.h>
6984
6985 static pthread_mutex_t mutex;
6986 static bool in_shutdown = false;
6987
6988 static void *
6989 worker (void *data)
6990 {
6991 mongoc_client_pool_t *pool = data;
6992 mongoc_client_t *client;
6993 bson_t ping = BSON_INITIALIZER;
6994 bson_error_t error;
6995 bool r;
6996
6997 BSON_APPEND_INT32 (&ping, "ping", 1);
6998
6999 while (true) {
7000 client = mongoc_client_pool_pop (pool);
7001 /* Do something with client. If you are writing an HTTP server, you
7002 * probably only want to hold onto the client for the portion of the
7003 * request performing database queries.
7004 */
7005 r = mongoc_client_command_simple (
7006 client, "admin", &ping, NULL, NULL, &error);
7007
7008 if (!r) {
7009 fprintf (stderr, "%s\n", error.message);
7010 }
7011
7012 mongoc_client_pool_push (pool, client);
7013
7014 pthread_mutex_lock (&mutex);
7015 if (in_shutdown || !r) {
7016 pthread_mutex_unlock (&mutex);
7017 break;
7018 }
7019
7020 pthread_mutex_unlock (&mutex);
7021 }
7022
7023 bson_destroy (&ping);
7024 return NULL;
7025 }
7026
7027 int
7028 main (int argc, char *argv[])
7029 {
7030 const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
7031 mongoc_uri_t *uri;
7032 bson_error_t error;
7033 mongoc_client_pool_t *pool;
7034 pthread_t threads[10];
7035 unsigned i;
7036 void *ret;
7037
7038 pthread_mutex_init (&mutex, NULL);
7039 mongoc_init ();
7040
7041 if (argc > 1) {
7042 uri_string = argv[1];
7043 }
7044
7045 uri = mongoc_uri_new_with_error (uri_string, &error);
7046 if (!uri) {
7047 fprintf (stderr,
7048 "failed to parse URI: %s\n"
7049 "error message: %s\n",
7050 uri_string,
7051 error.message);
7052 return EXIT_FAILURE;
7053 }
7054
7055 pool = mongoc_client_pool_new (uri);
7056 mongoc_client_pool_set_error_api (pool, 2);
7057
7058 for (i = 0; i < 10; i++) {
7059 pthread_create (&threads[i], NULL, worker, pool);
7060 }
7061
7062 sleep (10);
7063 pthread_mutex_lock (&mutex);
7064 in_shutdown = true;
7065 pthread_mutex_unlock (&mutex);
7066
7067 for (i = 0; i < 10; i++) {
7068 pthread_join (threads[i], &ret);
7069 }
7070
7071 mongoc_client_pool_destroy (pool);
7072 mongoc_uri_destroy (uri);
7073
7074 mongoc_cleanup ();
7075
7076 return EXIT_SUCCESS;
7077 }
7078
7079
7080 mongoc_client_session_t
7081 Use a session for a sequence of operations, optionally with causal con‐
7082 sistency. See the MongoDB Manual Entry for Causal Consistency.
7083
7084 Synopsis
7085 Start a session with mongoc_client_start_session, use the session for a
7086 sequence of operations and multi-document transactions, then free it
7087 with mongoc_client_session_destroy(). Any mongoc_cursor_t or mon‐
7088 goc_change_stream_t using a session must be destroyed before the ses‐
7089 sion, and a session must be destroyed before the mongoc_client_t it
7090 came from.
7091
7092 By default, sessions are causally consistent. To disable causal consis‐
7093 tency, before starting a session create a mongoc_session_opt_t with
7094 mongoc_session_opts_new() and call mongoc_session_opts_set_causal_con‐
7095 sistency(), then free the struct with mongoc_session_opts_destroy.
7096
7097 Unacknowledged writes are prohibited with sessions.
7098
7099 A mongoc_client_session_t must be used by only one thread at a time.
7100 Due to session pooling, mongoc_client_start_session may return a ses‐
7101 sion that has been idle for some time and is about to be closed after
7102 its idle timeout. Use the session within one minute of acquiring it to
7103 refresh the session and avoid a timeout.
7104
7105 Example
7106 example-session.c
7107
7108 /* gcc example-session.c -o example-session \
7109 * $(pkg-config --cflags --libs libmongoc-1.0) */
7110
7111 /* ./example-session [CONNECTION_STRING] */
7112
7113 #include <stdio.h>
7114 #include <mongoc/mongoc.h>
7115
7116
7117 int
7118 main (int argc, char *argv[])
7119 {
7120 int exit_code = EXIT_FAILURE;
7121
7122 mongoc_client_t *client = NULL;
7123 const char *uri_string = "mongodb://127.0.0.1/?appname=session-example";
7124 mongoc_uri_t *uri = NULL;
7125 mongoc_client_session_t *client_session = NULL;
7126 mongoc_collection_t *collection = NULL;
7127 bson_error_t error;
7128 bson_t *selector = NULL;
7129 bson_t *update = NULL;
7130 bson_t *update_opts = NULL;
7131 bson_t *find_opts = NULL;
7132 mongoc_read_prefs_t *secondary = NULL;
7133 mongoc_cursor_t *cursor = NULL;
7134 const bson_t *doc;
7135 char *str;
7136 bool r;
7137
7138 mongoc_init ();
7139
7140 if (argc > 1) {
7141 uri_string = argv[1];
7142 }
7143
7144 uri = mongoc_uri_new_with_error (uri_string, &error);
7145 if (!uri) {
7146 fprintf (stderr,
7147 "failed to parse URI: %s\n"
7148 "error message: %s\n",
7149 uri_string,
7150 error.message);
7151 goto done;
7152 }
7153
7154 client = mongoc_client_new_from_uri (uri);
7155 if (!client) {
7156 goto done;
7157 }
7158
7159 mongoc_client_set_error_api (client, 2);
7160
7161 /* pass NULL for options - by default the session is causally consistent */
7162 client_session = mongoc_client_start_session (client, NULL, &error);
7163 if (!client_session) {
7164 fprintf (stderr, "Failed to start session: %s\n", error.message);
7165 goto done;
7166 }
7167
7168 collection = mongoc_client_get_collection (client, "test", "collection");
7169 selector = BCON_NEW ("_id", BCON_INT32 (1));
7170 update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}");
7171 update_opts = bson_new ();
7172 if (!mongoc_client_session_append (client_session, update_opts, &error)) {
7173 fprintf (stderr, "Could not add session to opts: %s\n", error.message);
7174 goto done;
7175 }
7176
7177 r = mongoc_collection_update_one (
7178 collection, selector, update, update_opts, NULL /* reply */, &error);
7179
7180 if (!r) {
7181 fprintf (stderr, "Update failed: %s\n", error.message);
7182 goto done;
7183 }
7184
7185 bson_destroy (selector);
7186 selector = BCON_NEW ("_id", BCON_INT32 (1));
7187 secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
7188
7189 find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000));
7190 if (!mongoc_client_session_append (client_session, find_opts, &error)) {
7191 fprintf (stderr, "Could not add session to opts: %s\n", error.message);
7192 goto done;
7193 };
7194
7195 /* read from secondary. since we're in a causally consistent session, the
7196 * data is guaranteed to reflect the update we did on the primary. the query
7197 * blocks waiting for the secondary to catch up, if necessary, or times out
7198 * and fails after 2000 ms.
7199 */
7200 cursor = mongoc_collection_find_with_opts (
7201 collection, selector, find_opts, secondary);
7202
7203 while (mongoc_cursor_next (cursor, &doc)) {
7204 str = bson_as_json (doc, NULL);
7205 fprintf (stdout, "%s\n", str);
7206 bson_free (str);
7207 }
7208
7209 if (mongoc_cursor_error (cursor, &error)) {
7210 fprintf (stderr, "Cursor Failure: %s\n", error.message);
7211 goto done;
7212 }
7213
7214 exit_code = EXIT_SUCCESS;
7215
7216 done:
7217 if (find_opts) {
7218 bson_destroy (find_opts);
7219 }
7220 if (update) {
7221 bson_destroy (update);
7222 }
7223 if (selector) {
7224 bson_destroy (selector);
7225 }
7226 if (update_opts) {
7227 bson_destroy (update_opts);
7228 }
7229 if (secondary) {
7230 mongoc_read_prefs_destroy (secondary);
7231 }
7232 /* destroy cursor, collection, session before the client they came from */
7233 if (cursor) {
7234 mongoc_cursor_destroy (cursor);
7235 }
7236 if (collection) {
7237 mongoc_collection_destroy (collection);
7238 }
7239 if (client_session) {
7240 mongoc_client_session_destroy (client_session);
7241 }
7242 if (uri) {
7243 mongoc_uri_destroy (uri);
7244 }
7245 if (client) {
7246 mongoc_client_destroy (client);
7247 }
7248
7249 mongoc_cleanup ();
7250
7251 return exit_code;
7252 }
7253
7254
7255 mongoc_client_session_with_transaction_cb_t
7256 Synopsis
7257 typedef bool (*mongoc_client_session_with_transaction_cb_t) (
7258 mongoc_client_session_t *session,
7259 void *ctx,
7260 bson_t **reply,
7261 bson_error_t *error);
7262
7263 Provide this callback to mongoc_client_session_with_transaction. The
7264 callback should run a sequence of operations meant to be contained
7265 within a transaction. The callback should not attempt to start or com‐
7266 mit transactions.
7267
7268 Parameters
7269 • session: A mongoc_client_session_t.
7270
7271 • ctx: A void* set to the the user-provided ctx passed to mon‐
7272 goc_client_session_with_transaction.
7273
7274 • reply: An optional location for a bson_t or NULL. The callback should
7275 set this if it runs any operations against the server and receives
7276 replies.
7277
7278 • error: A bson_error_t. The callback should set this if it receives
7279 any errors while running operations against the server.
7280
7281 Return
7282 Returns true for success and false on failure. If cb returns false then
7283 it should also set error.
7284
7285 See Also
7286 mongoc_client_session_with_transaction
7287
7288 mongoc_client_t
7289 A single-threaded MongoDB connection. See connection-pooling.
7290
7291 Synopsis
7292 typedef struct _mongoc_client_t mongoc_client_t;
7293
7294 typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
7295 const mongoc_uri_t *uri,
7296 const mongoc_host_list_t *host,
7297 void *user_data,
7298 bson_error_t *error);
7299
7300 mongoc_client_t is an opaque type that provides access to a MongoDB
7301 server, replica set, or sharded cluster. It maintains management of un‐
7302 derlying sockets and routing to individual nodes based on mon‐
7303 goc_read_prefs_t or mongoc_write_concern_t.
7304
7305 Streams
7306 The underlying transport for a given client can be customized, wrapped
7307 or replaced by any implementation that fulfills mongoc_stream_t. A cus‐
7308 tom transport can be set with mongoc_client_set_stream_initiator().
7309
7310 Thread Safety
7311 mongoc_client_t is NOT thread-safe and should only be used from one
7312 thread at a time. When used in multi-threaded scenarios, it is recom‐
7313 mended that you use the thread-safe mongoc_client_pool_t to retrieve a
7314 mongoc_client_t for your thread.
7315
7316 Example
7317 example-client.c
7318
7319 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
7320 * libmongoc-1.0) */
7321
7322 /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
7323
7324 #include <mongoc/mongoc.h>
7325 #include <stdio.h>
7326 #include <stdlib.h>
7327
7328 int
7329 main (int argc, char *argv[])
7330 {
7331 mongoc_client_t *client;
7332 mongoc_collection_t *collection;
7333 mongoc_cursor_t *cursor;
7334 bson_error_t error;
7335 const bson_t *doc;
7336 const char *collection_name = "test";
7337 bson_t query;
7338 char *str;
7339 const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
7340 mongoc_uri_t *uri;
7341
7342 mongoc_init ();
7343 if (argc > 1) {
7344 uri_string = argv[1];
7345 }
7346
7347 if (argc > 2) {
7348 collection_name = argv[2];
7349 }
7350
7351 uri = mongoc_uri_new_with_error (uri_string, &error);
7352 if (!uri) {
7353 fprintf (stderr,
7354 "failed to parse URI: %s\n"
7355 "error message: %s\n",
7356 uri_string,
7357 error.message);
7358 return EXIT_FAILURE;
7359 }
7360
7361 client = mongoc_client_new_from_uri (uri);
7362 if (!client) {
7363 return EXIT_FAILURE;
7364 }
7365
7366 mongoc_client_set_error_api (client, 2);
7367
7368 bson_init (&query);
7369 collection = mongoc_client_get_collection (client, "test", collection_name);
7370 cursor = mongoc_collection_find_with_opts (
7371 collection,
7372 &query,
7373 NULL, /* additional options */
7374 NULL); /* read prefs, NULL for default */
7375
7376 while (mongoc_cursor_next (cursor, &doc)) {
7377 str = bson_as_canonical_extended_json (doc, NULL);
7378 fprintf (stdout, "%s\n", str);
7379 bson_free (str);
7380 }
7381
7382 if (mongoc_cursor_error (cursor, &error)) {
7383 fprintf (stderr, "Cursor Failure: %s\n", error.message);
7384 return EXIT_FAILURE;
7385 }
7386
7387 bson_destroy (&query);
7388 mongoc_cursor_destroy (cursor);
7389 mongoc_collection_destroy (collection);
7390 mongoc_uri_destroy (uri);
7391 mongoc_client_destroy (client);
7392 mongoc_cleanup ();
7393
7394 return EXIT_SUCCESS;
7395 }
7396
7397
7398 mongoc_collection_t
7399 Synopsis
7400 typedef struct _mongoc_collection_t mongoc_collection_t;
7401
7402 mongoc_collection_t provides access to a MongoDB collection. This han‐
7403 dle is useful for actions for most CRUD operations, I.e. insert, up‐
7404 date, delete, find, etc.
7405
7406 Read Preferences and Write Concerns
7407 Read preferences and write concerns are inherited from the parent
7408 client. They can be overridden by set_* commands if so desired.
7409
7410 mongoc_cursor_t
7411 Client-side cursor abstraction
7412
7413 Synopsis
7414 typedef struct _mongoc_cursor_t mongoc_cursor_t;
7415
7416 mongoc_cursor_t provides access to a MongoDB query cursor. It wraps up
7417 the wire protocol negotiation required to initiate a query and retrieve
7418 an unknown number of documents.
7419
7420 Common cursor operations include:
7421
7422 • Determine which host we've connected to with mongoc_cur‐
7423 sor_get_host().
7424
7425 • Retrieve more records with repeated calls to mongoc_cursor_next().
7426
7427 • Clone a query to repeat execution at a later point with mongoc_cur‐
7428 sor_clone().
7429
7430 • Test for errors with mongoc_cursor_error().
7431
7432 Cursors are lazy, meaning that no connection is established and no net‐
7433 work traffic occurs until the first call to mongoc_cursor_next().
7434
7435 Thread Safety
7436 mongoc_cursor_t is NOT thread safe. It may only be used from within the
7437 thread in which it was created.
7438
7439 Example
7440 Query MongoDB and iterate results
7441
7442 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
7443 * libmongoc-1.0) */
7444
7445 /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
7446
7447 #include <mongoc/mongoc.h>
7448 #include <stdio.h>
7449 #include <stdlib.h>
7450
7451 int
7452 main (int argc, char *argv[])
7453 {
7454 mongoc_client_t *client;
7455 mongoc_collection_t *collection;
7456 mongoc_cursor_t *cursor;
7457 bson_error_t error;
7458 const bson_t *doc;
7459 const char *collection_name = "test";
7460 bson_t query;
7461 char *str;
7462 const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
7463 mongoc_uri_t *uri;
7464
7465 mongoc_init ();
7466 if (argc > 1) {
7467 uri_string = argv[1];
7468 }
7469
7470 if (argc > 2) {
7471 collection_name = argv[2];
7472 }
7473
7474 uri = mongoc_uri_new_with_error (uri_string, &error);
7475 if (!uri) {
7476 fprintf (stderr,
7477 "failed to parse URI: %s\n"
7478 "error message: %s\n",
7479 uri_string,
7480 error.message);
7481 return EXIT_FAILURE;
7482 }
7483
7484 client = mongoc_client_new_from_uri (uri);
7485 if (!client) {
7486 return EXIT_FAILURE;
7487 }
7488
7489 mongoc_client_set_error_api (client, 2);
7490
7491 bson_init (&query);
7492 collection = mongoc_client_get_collection (client, "test", collection_name);
7493 cursor = mongoc_collection_find_with_opts (
7494 collection,
7495 &query,
7496 NULL, /* additional options */
7497 NULL); /* read prefs, NULL for default */
7498
7499 while (mongoc_cursor_next (cursor, &doc)) {
7500 str = bson_as_canonical_extended_json (doc, NULL);
7501 fprintf (stdout, "%s\n", str);
7502 bson_free (str);
7503 }
7504
7505 if (mongoc_cursor_error (cursor, &error)) {
7506 fprintf (stderr, "Cursor Failure: %s\n", error.message);
7507 return EXIT_FAILURE;
7508 }
7509
7510 bson_destroy (&query);
7511 mongoc_cursor_destroy (cursor);
7512 mongoc_collection_destroy (collection);
7513 mongoc_uri_destroy (uri);
7514 mongoc_client_destroy (client);
7515 mongoc_cleanup ();
7516
7517 return EXIT_SUCCESS;
7518 }
7519
7520
7521 mongoc_database_t
7522 MongoDB Database Abstraction
7523
7524 Synopsis
7525 typedef struct _mongoc_database_t mongoc_database_t;
7526
7527 mongoc_database_t provides access to a MongoDB database. This handle is
7528 useful for actions a particular database object. It is not a container
7529 for mongoc_collection_t structures.
7530
7531 Read preferences and write concerns are inherited from the parent
7532 client. They can be overridden with mongoc_database_set_read_prefs()
7533 and mongoc_database_set_write_concern().
7534
7535 Examples
7536 #include <mongoc/mongoc.h>
7537
7538 int
7539 main (int argc, char *argv[])
7540 {
7541 mongoc_database_t *database;
7542 mongoc_client_t *client;
7543
7544 mongoc_init ();
7545
7546 client = mongoc_client_new ("mongodb://localhost/");
7547 database = mongoc_client_get_database (client, "test");
7548
7549 mongoc_database_destroy (database);
7550 mongoc_client_destroy (client);
7551
7552 mongoc_cleanup ();
7553
7554 return 0;
7555 }
7556
7557 mongoc_delete_flags_t
7558 Flags for deletion operations
7559
7560 Synopsis
7561 typedef enum {
7562 MONGOC_DELETE_NONE = 0,
7563 MONGOC_DELETE_SINGLE_REMOVE = 1 << 0,
7564 } mongoc_delete_flags_t;
7565
7566 Deprecated
7567 WARNING:
7568 These flags are deprecated and should not be used in new code.
7569
7570 Please use mongoc_collection_delete_one() or mongoc_collec‐
7571 tion_delete_many() instead.
7572
7573 mongoc_find_and_modify_opts_t
7574 find_and_modify abstraction
7575
7576 Synopsis
7577 mongoc_find_and_modify_opts_t is a builder interface to construct a
7578 find_and_modify command.
7579
7580 It was created to be able to accommodate new arguments to the MongoDB
7581 find_and_modify command.
7582
7583 As of MongoDB 3.2, the mongoc_write_concern_t specified on the mon‐
7584 goc_collection_t will be used, if any.
7585
7586 Example
7587 flags.c
7588
7589 void
7590 fam_flags (mongoc_collection_t *collection)
7591 {
7592 mongoc_find_and_modify_opts_t *opts;
7593 bson_t reply;
7594 bson_error_t error;
7595 bson_t query = BSON_INITIALIZER;
7596 bson_t *update;
7597 bool success;
7598
7599
7600 /* Find Zlatan Ibrahimovic, the striker */
7601 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7602 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7603 BSON_APPEND_UTF8 (&query, "profession", "Football player");
7604 BSON_APPEND_INT32 (&query, "age", 34);
7605 BSON_APPEND_INT32 (
7606 &query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62));
7607
7608 /* Add his football position */
7609 update = BCON_NEW ("$set", "{", "position", BCON_UTF8 ("striker"), "}");
7610
7611 opts = mongoc_find_and_modify_opts_new ();
7612
7613 mongoc_find_and_modify_opts_set_update (opts, update);
7614
7615 /* Create the document if it didn't exist, and return the updated document */
7616 mongoc_find_and_modify_opts_set_flags (
7617 opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7618
7619 success = mongoc_collection_find_and_modify_with_opts (
7620 collection, &query, opts, &reply, &error);
7621
7622 if (success) {
7623 char *str;
7624
7625 str = bson_as_canonical_extended_json (&reply, NULL);
7626 printf ("%s\n", str);
7627 bson_free (str);
7628 } else {
7629 fprintf (
7630 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7631 }
7632
7633 bson_destroy (&reply);
7634 bson_destroy (update);
7635 bson_destroy (&query);
7636 mongoc_find_and_modify_opts_destroy (opts);
7637 }
7638
7639
7640 bypass.c
7641
7642 void
7643 fam_bypass (mongoc_collection_t *collection)
7644 {
7645 mongoc_find_and_modify_opts_t *opts;
7646 bson_t reply;
7647 bson_t *update;
7648 bson_error_t error;
7649 bson_t query = BSON_INITIALIZER;
7650 bool success;
7651
7652
7653 /* Find Zlatan Ibrahimovic, the striker */
7654 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7655 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7656 BSON_APPEND_UTF8 (&query, "profession", "Football player");
7657
7658 /* Bump his age */
7659 update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
7660
7661 opts = mongoc_find_and_modify_opts_new ();
7662 mongoc_find_and_modify_opts_set_update (opts, update);
7663 /* He can still play, even though he is pretty old. */
7664 mongoc_find_and_modify_opts_set_bypass_document_validation (opts, true);
7665
7666 success = mongoc_collection_find_and_modify_with_opts (
7667 collection, &query, opts, &reply, &error);
7668
7669 if (success) {
7670 char *str;
7671
7672 str = bson_as_canonical_extended_json (&reply, NULL);
7673 printf ("%s\n", str);
7674 bson_free (str);
7675 } else {
7676 fprintf (
7677 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7678 }
7679
7680 bson_destroy (&reply);
7681 bson_destroy (update);
7682 bson_destroy (&query);
7683 mongoc_find_and_modify_opts_destroy (opts);
7684 }
7685
7686
7687 update.c
7688
7689 void
7690 fam_update (mongoc_collection_t *collection)
7691 {
7692 mongoc_find_and_modify_opts_t *opts;
7693 bson_t *update;
7694 bson_t reply;
7695 bson_error_t error;
7696 bson_t query = BSON_INITIALIZER;
7697 bool success;
7698
7699
7700 /* Find Zlatan Ibrahimovic */
7701 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7702 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7703
7704 /* Make him a book author */
7705 update = BCON_NEW ("$set", "{", "author", BCON_BOOL (true), "}");
7706
7707 opts = mongoc_find_and_modify_opts_new ();
7708 /* Note that the document returned is the _previous_ version of the document
7709 * To fetch the modified new version, use
7710 * mongoc_find_and_modify_opts_set_flags (opts,
7711 * MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7712 */
7713 mongoc_find_and_modify_opts_set_update (opts, update);
7714
7715 success = mongoc_collection_find_and_modify_with_opts (
7716 collection, &query, opts, &reply, &error);
7717
7718 if (success) {
7719 char *str;
7720
7721 str = bson_as_canonical_extended_json (&reply, NULL);
7722 printf ("%s\n", str);
7723 bson_free (str);
7724 } else {
7725 fprintf (
7726 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7727 }
7728
7729 bson_destroy (&reply);
7730 bson_destroy (update);
7731 bson_destroy (&query);
7732 mongoc_find_and_modify_opts_destroy (opts);
7733 }
7734
7735
7736 fields.c
7737
7738 void
7739 fam_fields (mongoc_collection_t *collection)
7740 {
7741 mongoc_find_and_modify_opts_t *opts;
7742 bson_t fields = BSON_INITIALIZER;
7743 bson_t *update;
7744 bson_t reply;
7745 bson_error_t error;
7746 bson_t query = BSON_INITIALIZER;
7747 bool success;
7748
7749
7750 /* Find Zlatan Ibrahimovic */
7751 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7752 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7753
7754 /* Return his goal tally */
7755 BSON_APPEND_INT32 (&fields, "goals", 1);
7756
7757 /* Bump his goal tally */
7758 update = BCON_NEW ("$inc", "{", "goals", BCON_INT32 (1), "}");
7759
7760 opts = mongoc_find_and_modify_opts_new ();
7761 mongoc_find_and_modify_opts_set_update (opts, update);
7762 mongoc_find_and_modify_opts_set_fields (opts, &fields);
7763 /* Return the new tally */
7764 mongoc_find_and_modify_opts_set_flags (opts,
7765 MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7766
7767 success = mongoc_collection_find_and_modify_with_opts (
7768 collection, &query, opts, &reply, &error);
7769
7770 if (success) {
7771 char *str;
7772
7773 str = bson_as_canonical_extended_json (&reply, NULL);
7774 printf ("%s\n", str);
7775 bson_free (str);
7776 } else {
7777 fprintf (
7778 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7779 }
7780
7781 bson_destroy (&reply);
7782 bson_destroy (update);
7783 bson_destroy (&fields);
7784 bson_destroy (&query);
7785 mongoc_find_and_modify_opts_destroy (opts);
7786 }
7787
7788
7789 sort.c
7790
7791 void
7792 fam_sort (mongoc_collection_t *collection)
7793 {
7794 mongoc_find_and_modify_opts_t *opts;
7795 bson_t *update;
7796 bson_t sort = BSON_INITIALIZER;
7797 bson_t reply;
7798 bson_error_t error;
7799 bson_t query = BSON_INITIALIZER;
7800 bool success;
7801
7802
7803 /* Find all users with the lastname Ibrahimovic */
7804 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7805
7806 /* Sort by age (descending) */
7807 BSON_APPEND_INT32 (&sort, "age", -1);
7808
7809 /* Bump his goal tally */
7810 update = BCON_NEW ("$set", "{", "oldest", BCON_BOOL (true), "}");
7811
7812 opts = mongoc_find_and_modify_opts_new ();
7813 mongoc_find_and_modify_opts_set_update (opts, update);
7814 mongoc_find_and_modify_opts_set_sort (opts, &sort);
7815
7816 success = mongoc_collection_find_and_modify_with_opts (
7817 collection, &query, opts, &reply, &error);
7818
7819 if (success) {
7820 char *str;
7821
7822 str = bson_as_canonical_extended_json (&reply, NULL);
7823 printf ("%s\n", str);
7824 bson_free (str);
7825 } else {
7826 fprintf (
7827 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7828 }
7829
7830 bson_destroy (&reply);
7831 bson_destroy (update);
7832 bson_destroy (&sort);
7833 bson_destroy (&query);
7834 mongoc_find_and_modify_opts_destroy (opts);
7835 }
7836
7837
7838 opts.c
7839
7840 void
7841 fam_opts (mongoc_collection_t *collection)
7842 {
7843 mongoc_find_and_modify_opts_t *opts;
7844 bson_t reply;
7845 bson_t *update;
7846 bson_error_t error;
7847 bson_t query = BSON_INITIALIZER;
7848 mongoc_write_concern_t *wc;
7849 bson_t extra = BSON_INITIALIZER;
7850 bool success;
7851
7852
7853 /* Find Zlatan Ibrahimovic, the striker */
7854 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7855 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7856 BSON_APPEND_UTF8 (&query, "profession", "Football player");
7857
7858 /* Bump his age */
7859 update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
7860
7861 opts = mongoc_find_and_modify_opts_new ();
7862 mongoc_find_and_modify_opts_set_update (opts, update);
7863
7864 /* Abort if the operation takes too long. */
7865 mongoc_find_and_modify_opts_set_max_time_ms (opts, 100);
7866
7867 /* Set write concern w: 2 */
7868 wc = mongoc_write_concern_new ();
7869 mongoc_write_concern_set_w (wc, 2);
7870 mongoc_write_concern_append (wc, &extra);
7871
7872 /* Some future findAndModify option the driver doesn't support conveniently
7873 */
7874 BSON_APPEND_INT32 (&extra, "futureOption", 42);
7875 mongoc_find_and_modify_opts_append (opts, &extra);
7876
7877 success = mongoc_collection_find_and_modify_with_opts (
7878 collection, &query, opts, &reply, &error);
7879
7880 if (success) {
7881 char *str;
7882
7883 str = bson_as_canonical_extended_json (&reply, NULL);
7884 printf ("%s\n", str);
7885 bson_free (str);
7886 } else {
7887 fprintf (
7888 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7889 }
7890
7891 bson_destroy (&reply);
7892 bson_destroy (&extra);
7893 bson_destroy (update);
7894 bson_destroy (&query);
7895 mongoc_write_concern_destroy (wc);
7896 mongoc_find_and_modify_opts_destroy (opts);
7897 }
7898
7899
7900 fam.c
7901
7902 int
7903 main (void)
7904 {
7905 mongoc_collection_t *collection;
7906 mongoc_database_t *database;
7907 mongoc_client_t *client;
7908 const char *uri_string =
7909 "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example";
7910 mongoc_uri_t *uri;
7911 bson_error_t error;
7912 bson_t *options;
7913
7914 mongoc_init ();
7915
7916 uri = mongoc_uri_new_with_error (uri_string, &error);
7917 if (!uri) {
7918 fprintf (stderr,
7919 "failed to parse URI: %s\n"
7920 "error message: %s\n",
7921 uri_string,
7922 error.message);
7923 return EXIT_FAILURE;
7924 }
7925
7926 client = mongoc_client_new_from_uri (uri);
7927 if (!client) {
7928 return EXIT_FAILURE;
7929 }
7930
7931 mongoc_client_set_error_api (client, 2);
7932 database = mongoc_client_get_database (client, "databaseName");
7933
7934 options = BCON_NEW ("validator",
7935 "{",
7936 "age",
7937 "{",
7938 "$lte",
7939 BCON_INT32 (34),
7940 "}",
7941 "}",
7942 "validationAction",
7943 BCON_UTF8 ("error"),
7944 "validationLevel",
7945 BCON_UTF8 ("moderate"));
7946
7947 collection = mongoc_database_create_collection (
7948 database, "collectionName", options, &error);
7949 if (!collection) {
7950 fprintf (
7951 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7952 return EXIT_FAILURE;
7953 }
7954
7955 fam_flags (collection);
7956 fam_bypass (collection);
7957 fam_update (collection);
7958 fam_fields (collection);
7959 fam_opts (collection);
7960 fam_sort (collection);
7961
7962 mongoc_collection_drop (collection, NULL);
7963 bson_destroy (options);
7964 mongoc_uri_destroy (uri);
7965 mongoc_database_destroy (database);
7966 mongoc_collection_destroy (collection);
7967 mongoc_client_destroy (client);
7968
7969 mongoc_cleanup ();
7970 return EXIT_SUCCESS;
7971 }
7972
7973
7974 Outputs:
7975
7976 {
7977 "lastErrorObject": {
7978 "updatedExisting": false,
7979 "n": 1,
7980 "upserted": {
7981 "$oid": "56562a99d13e6d86239c7b00"
7982 }
7983 },
7984 "value": {
7985 "_id": {
7986 "$oid": "56562a99d13e6d86239c7b00"
7987 },
7988 "age": 34,
7989 "firstname": "Zlatan",
7990 "goals": 342,
7991 "lastname": "Ibrahimovic",
7992 "profession": "Football player",
7993 "position": "striker"
7994 },
7995 "ok": 1
7996 }
7997 {
7998 "lastErrorObject": {
7999 "updatedExisting": true,
8000 "n": 1
8001 },
8002 "value": {
8003 "_id": {
8004 "$oid": "56562a99d13e6d86239c7b00"
8005 },
8006 "age": 34,
8007 "firstname": "Zlatan",
8008 "goals": 342,
8009 "lastname": "Ibrahimovic",
8010 "profession": "Football player",
8011 "position": "striker"
8012 },
8013 "ok": 1
8014 }
8015 {
8016 "lastErrorObject": {
8017 "updatedExisting": true,
8018 "n": 1
8019 },
8020 "value": {
8021 "_id": {
8022 "$oid": "56562a99d13e6d86239c7b00"
8023 },
8024 "age": 35,
8025 "firstname": "Zlatan",
8026 "goals": 342,
8027 "lastname": "Ibrahimovic",
8028 "profession": "Football player",
8029 "position": "striker"
8030 },
8031 "ok": 1
8032 }
8033 {
8034 "lastErrorObject": {
8035 "updatedExisting": true,
8036 "n": 1
8037 },
8038 "value": {
8039 "_id": {
8040 "$oid": "56562a99d13e6d86239c7b00"
8041 },
8042 "goals": 343
8043 },
8044 "ok": 1
8045 }
8046 {
8047 "lastErrorObject": {
8048 "updatedExisting": true,
8049 "n": 1
8050 },
8051 "value": {
8052 "_id": {
8053 "$oid": "56562a99d13e6d86239c7b00"
8054 },
8055 "age": 35,
8056 "firstname": "Zlatan",
8057 "goals": 343,
8058 "lastname": "Ibrahimovic",
8059 "profession": "Football player",
8060 "position": "striker",
8061 "author": true
8062 },
8063 "ok": 1
8064 }
8065
8066 mongoc_gridfs_file_list_t
8067 Synopsis
8068 #include <mongoc/mongoc.h>
8069
8070 typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t;
8071
8072 Description
8073 mongoc_gridfs_file_list_t provides a gridfs file list abstraction. It
8074 provides iteration and basic marshalling on top of a regular mon‐
8075 goc_collection_find_with_opts() style query. In interface, it's styled
8076 after mongoc_cursor_t.
8077
8078 Example
8079 mongoc_gridfs_file_list_t *list;
8080 mongoc_gridfs_file_t *file;
8081
8082 list = mongoc_gridfs_find (gridfs, query);
8083
8084 while ((file = mongoc_gridfs_file_list_next (list))) {
8085 do_something (file);
8086
8087 mongoc_gridfs_file_destroy (file);
8088 }
8089
8090 mongoc_gridfs_file_list_destroy (list);
8091
8092 mongoc_gridfs_file_opt_t
8093 Synopsis
8094 typedef struct {
8095 const char *md5;
8096 const char *filename;
8097 const char *content_type;
8098 const bson_t *aliases;
8099 const bson_t *metadata;
8100 uint32_t chunk_size;
8101 } mongoc_gridfs_file_opt_t;
8102
8103 Description
8104 This structure contains options that can be set on a mon‐
8105 goc_gridfs_file_t. It can be used by various functions when creating a
8106 new gridfs file.
8107
8108 mongoc_gridfs_file_t
8109 Synopsis
8110 typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t;
8111
8112 Description
8113 This structure provides a MongoDB GridFS file abstraction. It provides
8114 several APIs.
8115
8116 • readv, writev, seek, and tell.
8117
8118 • General file metadata such as filename and length.
8119
8120 • GridFS metadata such as md5, filename, content_type, aliases, meta‐
8121 data, chunk_size, and upload_date.
8122
8123 Thread Safety
8124 This structure is NOT thread-safe and should only be used from one
8125 thread at a time.
8126
8127 Related
8128 • mongoc_client_t
8129
8130 • mongoc_gridfs_t
8131
8132 • mongoc_gridfs_file_list_t
8133
8134 • mongoc_gridfs_file_opt_t
8135
8136 mongoc_gridfs_bucket_t
8137 Synopsis
8138 #include <mongoc/mongoc.h>
8139
8140 typedef struct _mongoc_gridfs_bucket_t mongoc_gridfs_bucket_t;
8141
8142 Description
8143 mongoc_gridfs_bucket_t provides a spec-compliant MongoDB GridFS imple‐
8144 mentation, superseding mongoc_gridfs_t. See the GridFS MongoDB documen‐
8145 tation.
8146
8147 Thread Safety
8148 mongoc_gridfs_bucket_t is NOT thread-safe and should only be used in
8149 the same thread as the owning mongoc_client_t.
8150
8151 Lifecycle
8152 It is an error to free a mongoc_gridfs_bucket_t before freeing all de‐
8153 rived instances of mongoc_stream_t. The owning mongoc_client_t must
8154 outlive the mongoc_gridfs_bucket_t.
8155
8156 Example
8157 example-gridfs-bucket.c
8158
8159 #include <stdio.h>
8160 #include <stdlib.h>
8161
8162 #include <mongoc/mongoc.h>
8163
8164 int
8165 main (int argc, char *argv[])
8166 {
8167 const char *uri_string =
8168 "mongodb://localhost:27017/?appname=new-gridfs-example";
8169 mongoc_client_t *client;
8170 mongoc_database_t *db;
8171 mongoc_stream_t *file_stream;
8172 mongoc_gridfs_bucket_t *bucket;
8173 mongoc_cursor_t *cursor;
8174 bson_t filter;
8175 bool res;
8176 bson_value_t file_id;
8177 bson_error_t error;
8178 const bson_t *doc;
8179 char *str;
8180 mongoc_init ();
8181
8182 if (argc != 3) {
8183 fprintf (stderr, "usage: %s SOURCE_FILE_PATH FILE_COPY_PATH\n", argv[0]);
8184 return EXIT_FAILURE;
8185 }
8186
8187 /* 1. Make a bucket. */
8188 client = mongoc_client_new (uri_string);
8189 db = mongoc_client_get_database (client, "test");
8190 bucket = mongoc_gridfs_bucket_new (db, NULL, NULL, &error);
8191 if (!bucket) {
8192 printf ("Error creating gridfs bucket: %s\n", error.message);
8193 return EXIT_FAILURE;
8194 }
8195
8196 /* 2. Insert a file. */
8197 file_stream = mongoc_stream_file_new_for_path (argv[1], O_RDONLY, 0);
8198 res = mongoc_gridfs_bucket_upload_from_stream (
8199 bucket, "my-file", file_stream, NULL, &file_id, &error);
8200 if (!res) {
8201 printf ("Error uploading file: %s\n", error.message);
8202 return EXIT_FAILURE;
8203 }
8204
8205 mongoc_stream_close (file_stream);
8206 mongoc_stream_destroy (file_stream);
8207
8208 /* 3. Download the file in GridFS to a local file. */
8209 file_stream = mongoc_stream_file_new_for_path (argv[2], O_CREAT | O_RDWR, 0);
8210 if (!file_stream) {
8211 perror ("Error opening file stream");
8212 return EXIT_FAILURE;
8213 }
8214
8215 res = mongoc_gridfs_bucket_download_to_stream (
8216 bucket, &file_id, file_stream, &error);
8217 if (!res) {
8218 printf ("Error downloading file to stream: %s\n", error.message);
8219 return EXIT_FAILURE;
8220 }
8221 mongoc_stream_close (file_stream);
8222 mongoc_stream_destroy (file_stream);
8223
8224 /* 4. List what files are available in GridFS. */
8225 bson_init (&filter);
8226 cursor = mongoc_gridfs_bucket_find (bucket, &filter, NULL);
8227
8228 while (mongoc_cursor_next (cursor, &doc)) {
8229 str = bson_as_canonical_extended_json (doc, NULL);
8230 printf ("%s\n", str);
8231 bson_free (str);
8232 }
8233
8234 /* 5. Delete the file that we added. */
8235 res = mongoc_gridfs_bucket_delete_by_id (bucket, &file_id, &error);
8236 if (!res) {
8237 printf ("Error deleting the file: %s\n", error.message);
8238 return EXIT_FAILURE;
8239 }
8240
8241 /* 6. Cleanup. */
8242 mongoc_stream_close (file_stream);
8243 mongoc_stream_destroy (file_stream);
8244 mongoc_cursor_destroy (cursor);
8245 bson_destroy (&filter);
8246 mongoc_gridfs_bucket_destroy (bucket);
8247 mongoc_database_destroy (db);
8248 mongoc_client_destroy (client);
8249 mongoc_cleanup ();
8250
8251 return EXIT_SUCCESS;
8252 }
8253
8254
8255 See also
8256 • The MongoDB GridFS specification.
8257
8258 • The non spec-compliant mongoc_gridfs_t.
8259
8260 mongoc_gridfs_t
8261 WARNING:
8262 This GridFS implementation does not conform to the MongoDB GridFS
8263 specification. For a spec compliant implementation, use mon‐
8264 goc_gridfs_bucket_t.
8265
8266 Synopsis
8267 #include <mongoc/mongoc.h>
8268
8269 typedef struct _mongoc_gridfs_t mongoc_gridfs_t;
8270
8271 Description
8272 mongoc_gridfs_t provides a MongoDB gridfs implementation. The system as
8273 a whole is made up of gridfs objects, which contain gridfs_files and
8274 gridfs_file_lists. Essentially, a basic file system API.
8275
8276 There are extensive caveats about the kind of use cases gridfs is prac‐
8277 tical for. In particular, any writing after initial file creation is
8278 likely to both break any concurrent readers and be quite expensive.
8279 That said, this implementation does allow for arbitrary writes to ex‐
8280 isting gridfs object, just use them with caution.
8281
8282 mongoc_gridfs also integrates tightly with the mongoc_stream_t abstrac‐
8283 tion, which provides some convenient wrapping for file creation and
8284 reading/writing. It can be used without, but its worth looking to see
8285 if your problem can fit that model.
8286
8287 WARNING:
8288 mongoc_gridfs_t does not support read preferences. In a replica set,
8289 GridFS queries are always routed to the primary.
8290
8291 Thread Safety
8292 mongoc_gridfs_t is NOT thread-safe and should only be used in the same
8293 thread as the owning mongoc_client_t.
8294
8295 Lifecycle
8296 It is an error to free a mongoc_gridfs_t before freeing all related in‐
8297 stances of mongoc_gridfs_file_t and mongoc_gridfs_file_list_t.
8298
8299 Example
8300 example-gridfs.c
8301
8302 #include <assert.h>
8303 #include <mongoc/mongoc.h>
8304 #include <stdio.h>
8305 #include <stdlib.h>
8306 #include <fcntl.h>
8307
8308 int
8309 main (int argc, char *argv[])
8310 {
8311 mongoc_gridfs_t *gridfs;
8312 mongoc_gridfs_file_t *file;
8313 mongoc_gridfs_file_list_t *list;
8314 mongoc_gridfs_file_opt_t opt = {0};
8315 mongoc_client_t *client;
8316 const char *uri_string = "mongodb://127.0.0.1:27017/?appname=gridfs-example";
8317 mongoc_uri_t *uri;
8318 mongoc_stream_t *stream;
8319 bson_t filter;
8320 bson_t opts;
8321 bson_t child;
8322 bson_error_t error;
8323 ssize_t r;
8324 char buf[4096];
8325 mongoc_iovec_t iov;
8326 const char *filename;
8327 const char *command;
8328 bson_value_t id;
8329
8330 if (argc < 2) {
8331 fprintf (stderr, "usage - %s command ...\n", argv[0]);
8332 return EXIT_FAILURE;
8333 }
8334
8335 mongoc_init ();
8336
8337 iov.iov_base = (void *) buf;
8338 iov.iov_len = sizeof buf;
8339
8340 /* connect to localhost client */
8341 uri = mongoc_uri_new_with_error (uri_string, &error);
8342 if (!uri) {
8343 fprintf (stderr,
8344 "failed to parse URI: %s\n"
8345 "error message: %s\n",
8346 uri_string,
8347 error.message);
8348 return EXIT_FAILURE;
8349 }
8350
8351 client = mongoc_client_new_from_uri (uri);
8352 assert (client);
8353 mongoc_client_set_error_api (client, 2);
8354
8355 /* grab a gridfs handle in test prefixed by fs */
8356 gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error);
8357 assert (gridfs);
8358
8359 command = argv[1];
8360 filename = argv[2];
8361
8362 if (strcmp (command, "read") == 0) {
8363 if (argc != 3) {
8364 fprintf (stderr, "usage - %s read filename\n", argv[0]);
8365 return EXIT_FAILURE;
8366 }
8367 file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error);
8368 assert (file);
8369
8370 stream = mongoc_stream_gridfs_new (file);
8371 assert (stream);
8372
8373 for (;;) {
8374 r = mongoc_stream_readv (stream, &iov, 1, -1, 0);
8375
8376 assert (r >= 0);
8377
8378 if (r == 0) {
8379 break;
8380 }
8381
8382 if (fwrite (iov.iov_base, 1, r, stdout) != r) {
8383 MONGOC_ERROR ("Failed to write to stdout. Exiting.\n");
8384 exit (1);
8385 }
8386 }
8387
8388 mongoc_stream_destroy (stream);
8389 mongoc_gridfs_file_destroy (file);
8390 } else if (strcmp (command, "list") == 0) {
8391 bson_init (&filter);
8392
8393 bson_init (&opts);
8394 bson_append_document_begin (&opts, "sort", -1, &child);
8395 BSON_APPEND_INT32 (&child, "filename", 1);
8396 bson_append_document_end (&opts, &child);
8397
8398 list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts);
8399
8400 bson_destroy (&filter);
8401 bson_destroy (&opts);
8402
8403 while ((file = mongoc_gridfs_file_list_next (list))) {
8404 const char *name = mongoc_gridfs_file_get_filename (file);
8405 printf ("%s\n", name ? name : "?");
8406
8407 mongoc_gridfs_file_destroy (file);
8408 }
8409
8410 mongoc_gridfs_file_list_destroy (list);
8411 } else if (strcmp (command, "write") == 0) {
8412 if (argc != 4) {
8413 fprintf (stderr, "usage - %s write filename input_file\n", argv[0]);
8414 return EXIT_FAILURE;
8415 }
8416
8417 stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0);
8418 assert (stream);
8419
8420 opt.filename = filename;
8421
8422 /* the driver generates a file_id for you */
8423 file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt);
8424 assert (file);
8425
8426 id.value_type = BSON_TYPE_INT32;
8427 id.value.v_int32 = 1;
8428
8429 /* optional: the following method specifies a file_id of any
8430 BSON type */
8431 if (!mongoc_gridfs_file_set_id (file, &id, &error)) {
8432 fprintf (stderr, "%s\n", error.message);
8433 return EXIT_FAILURE;
8434 }
8435
8436 if (!mongoc_gridfs_file_save (file)) {
8437 mongoc_gridfs_file_error (file, &error);
8438 fprintf (stderr, "Could not save: %s\n", error.message);
8439 return EXIT_FAILURE;
8440 }
8441
8442 mongoc_gridfs_file_destroy (file);
8443 } else {
8444 fprintf (stderr, "Unknown command");
8445 return EXIT_FAILURE;
8446 }
8447
8448 mongoc_gridfs_destroy (gridfs);
8449 mongoc_uri_destroy (uri);
8450 mongoc_client_destroy (client);
8451
8452 mongoc_cleanup ();
8453
8454 return EXIT_SUCCESS;
8455 }
8456
8457
8458 See also
8459 • The MongoDB GridFS specification.
8460
8461 • The spec-compliant mongoc_gridfs_bucket_t.
8462
8463 mongoc_host_list_t
8464 Synopsis
8465 typedef struct {
8466 mongoc_host_list_t *next;
8467 char host[BSON_HOST_NAME_MAX + 1];
8468 char host_and_port[BSON_HOST_NAME_MAX + 7];
8469 uint16_t port;
8470 int family;
8471 void *padding[4];
8472 } mongoc_host_list_t;
8473
8474 Description
8475 The host and port of a MongoDB server. Can be part of a linked list:
8476 for example the return value of mongoc_uri_get_hosts when multiple
8477 hosts are provided in the MongoDB URI.
8478
8479 See Also
8480 mongoc_uri_get_hosts and mongoc_cursor_get_host.
8481
8482 mongoc_index_opt_geo_t
8483 Synopsis
8484 #include <mongoc/mongoc.h>
8485
8486 typedef struct {
8487 uint8_t twod_sphere_version;
8488 uint8_t twod_bits_precision;
8489 double twod_location_min;
8490 double twod_location_max;
8491 double haystack_bucket_size;
8492 uint8_t *padding[32];
8493 } mongoc_index_opt_geo_t;
8494
8495 Description
8496 This structure contains the options that may be used for tuning a GEO
8497 index.
8498
8499 See Also
8500 mongoc_index_opt_t
8501
8502 mongoc_index_opt_wt_t
8503
8504 mongoc_index_opt_t
8505 Synopsis
8506 #include <mongoc/mongoc.h>
8507
8508 typedef struct {
8509 bool is_initialized;
8510 bool background;
8511 bool unique;
8512 const char *name;
8513 bool drop_dups;
8514 bool sparse;
8515 int32_t expire_after_seconds;
8516 int32_t v;
8517 const bson_t *weights;
8518 const char *default_language;
8519 const char *language_override;
8520 mongoc_index_opt_geo_t *geo_options;
8521 mongoc_index_opt_storage_t *storage_options;
8522 const bson_t *partial_filter_expression;
8523 const bson_t *collation;
8524 void *padding[4];
8525 } mongoc_index_opt_t;
8526
8527 Deprecated
8528 This structure is deprecated and should not be used in new code. See
8529 create-indexes.
8530
8531 Description
8532 This structure contains the options that may be used for tuning a spe‐
8533 cific index.
8534
8535 See the createIndexes documentations in the MongoDB manual for descrip‐
8536 tions of individual options.
8537
8538 NOTE:
8539 dropDups is deprecated as of MongoDB version 3.0.0. This option is
8540 silently ignored by the server and unique index builds using this
8541 option will fail if a duplicate value is detected.
8542
8543 Example
8544 {
8545 bson_t keys;
8546 bson_error_t error;
8547 mongoc_index_opt_t opt;
8548 mongoc_index_opt_geo_t geo_opt;
8549
8550 mongoc_index_opt_init (&opt);
8551 mongoc_index_opt_geo_init (&geo_opt);
8552
8553 bson_init (&keys);
8554 BSON_APPEND_UTF8 (&keys, "location", "2d");
8555
8556 geo_opt.twod_location_min = -123;
8557 geo_opt.twod_location_max = +123;
8558 geo_opt.twod_bits_precision = 30;
8559 opt.geo_options = &geo_opt;
8560
8561 collection = mongoc_client_get_collection (client, "test", "geo_test");
8562 if (mongoc_collection_create_index (collection, &keys, &opt, &error)) {
8563 /* Successfully created the geo index */
8564 }
8565 bson_destroy (&keys);
8566 mongoc_collection_destroy (&collection);
8567 }
8568
8569 See Also
8570 mongoc_index_opt_geo_t
8571
8572 mongoc_index_opt_wt_t
8573
8574 mongoc_index_opt_wt_t
8575 Synopsis
8576 #include <mongoc/mongoc.h>
8577
8578 typedef struct {
8579 mongoc_index_opt_storage_t base;
8580 const char *config_str;
8581 void *padding[8];
8582 } mongoc_index_opt_wt_t;
8583
8584 Description
8585 This structure contains the options that may be used for tuning a
8586 WiredTiger specific index.
8587
8588 See Also
8589 mongoc_index_opt_t
8590
8591 mongoc_index_opt_geo_t
8592
8593 mongoc_insert_flags_t
8594 Flags for insert operations
8595
8596 Synopsis
8597 typedef enum {
8598 MONGOC_INSERT_NONE = 0,
8599 MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0,
8600 } mongoc_insert_flags_t;
8601
8602 #define MONGOC_INSERT_NO_VALIDATE (1U << 31)
8603
8604 Description
8605 These flags correspond to the MongoDB wire protocol. They may be bit‐
8606 wise or'd together. They may modify how an insert happens on the Mon‐
8607 goDB server.
8608
8609 Flag Values
8610 ┌──────────────────────────┬────────────────────────────┐
8611 │MONGOC_INSERT_NONE │ Specify no insert flags. │
8612 ├──────────────────────────┼────────────────────────────┤
8613 │MONGOC_INSERT_CON‐ │ Continue inserting docu‐ │
8614 │TINUE_ON_ERROR │ ments from the insertion │
8615 │ │ set even if one insert │
8616 │ │ fails. │
8617 ├──────────────────────────┼────────────────────────────┤
8618 │MONGOC_INSERT_NO_VALIDATE │ Do not validate insertion │
8619 │ │ documents before perform‐ │
8620 │ │ ing an insert. Validation │
8621 │ │ can be expensive, so this │
8622 │ │ can save some time if you │
8623 │ │ know your documents are │
8624 │ │ already valid. │
8625 └──────────────────────────┴────────────────────────────┘
8626
8627 mongoc_iovec_t
8628 Synopsis
8629 Synopsis
8630 #include <mongoc/mongoc.h>
8631
8632 #ifdef _WIN32
8633 typedef struct {
8634 u_long iov_len;
8635 char *iov_base;
8636 } mongoc_iovec_t;
8637 #else
8638 typedef struct iovec mongoc_iovec_t;
8639 #endif
8640
8641 The mongoc_iovec_t structure is a portability abstraction for consumers
8642 of the mongoc_stream_t interfaces. It allows for scatter/gather I/O
8643 through the socket subsystem.
8644
8645 WARNING:
8646 When writing portable code, beware of the ordering of iov_len and
8647 iov_base as they are different on various platforms. Therefore, you
8648 should not use C initializers for initialization.
8649
8650 mongoc_matcher_t
8651 Client-side document matching abstraction
8652
8653 Synopsis
8654 typedef struct _mongoc_matcher_t mongoc_matcher_t;
8655
8656 mongoc_matcher_t provides a reduced-interface for client-side matching
8657 of BSON documents.
8658
8659 It can perform the basics such as $in, $nin, $eq, $neq, $gt, $gte, $lt,
8660 and $lte.
8661
8662 WARNING:
8663 mongoc_matcher_t does not currently support the full spectrum of
8664 query operations that the MongoDB server supports.
8665
8666 Deprecated
8667 WARNING:
8668 mongoc_matcher_t is deprecated and will be removed in version 2.0.
8669
8670 Example
8671 Filter a sequence of BSON documents from STDIN based on a query
8672
8673 #include <bson/bson.h>
8674 #include <mongoc/mongoc.h>
8675 #include <stdio.h>
8676
8677 int
8678 main (int argc, char *argv[])
8679 {
8680 mongoc_matcher_t *matcher;
8681 bson_reader_t *reader;
8682 const bson_t *bson;
8683 bson_t *spec;
8684 char *str;
8685 int fd;
8686
8687 mongoc_init ();
8688
8689 #ifdef _WIN32
8690 fd = fileno (stdin);
8691 #else
8692 fd = STDIN_FILENO;
8693 #endif
8694
8695 reader = bson_reader_new_from_fd (fd, false);
8696
8697 spec = BCON_NEW ("hello", "world");
8698 matcher = mongoc_matcher_new (spec, NULL);
8699
8700 while ((bson = bson_reader_read (reader, NULL))) {
8701 if (mongoc_matcher_match (matcher, bson)) {
8702 str = bson_as_canonical_extended_json (bson, NULL);
8703 printf ("%s\n", str);
8704 bson_free (str);
8705 }
8706 }
8707
8708 bson_reader_destroy (reader);
8709 bson_destroy (spec);
8710
8711 mongoc_cleanup ();
8712
8713 return 0;
8714 }
8715
8716 mongoc_query_flags_t
8717 Flags for query operations
8718
8719 Synopsis
8720 typedef enum {
8721 MONGOC_QUERY_NONE = 0,
8722 MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1,
8723 MONGOC_QUERY_SLAVE_OK = 1 << 2,
8724 MONGOC_QUERY_OPLOG_REPLAY = 1 << 3,
8725 MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
8726 MONGOC_QUERY_AWAIT_DATA = 1 << 5,
8727 MONGOC_QUERY_EXHAUST = 1 << 6,
8728 MONGOC_QUERY_PARTIAL = 1 << 7,
8729 } mongoc_query_flags_t;
8730
8731 Description
8732 These flags correspond to the MongoDB wire protocol. They may be bit‐
8733 wise or'd together. They may modify how a query is performed in the
8734 MongoDB server.
8735
8736 Flag Values
8737 ┌───────────────────────────┬────────────────────────────┐
8738 │MONGOC_QUERY_NONE │ Specify no query flags. │
8739 ├───────────────────────────┼────────────────────────────┤
8740 │MONGOC_QUERY_TAILABLE_CUR‐ │ Cursor will not be closed │
8741 │SOR │ when the last data is re‐ │
8742 │ │ trieved. You can resume │
8743 │ │ this cursor later. │
8744 ├───────────────────────────┼────────────────────────────┤
8745 │MONGOC_QUERY_SLAVE_OK │ Allow query of replica set │
8746 │ │ secondaries. │
8747 ├───────────────────────────┼────────────────────────────┤
8748 │MONGOC_QUERY_OPLOG_REPLAY │ Used internally by Mon‐ │
8749 │ │ goDB. │
8750 ├───────────────────────────┼────────────────────────────┤
8751 │MONGOC_QUERY_NO_CUR‐ │ The server normally times │
8752 │SOR_TIMEOUT │ out an idle cursor after │
8753 │ │ an inactivity period (10 │
8754 │ │ minutes). This prevents │
8755 │ │ that. │
8756 ├───────────────────────────┼────────────────────────────┤
8757 │MONGOC_QUERY_AWAIT_DATA │ Use with MON‐ │
8758 │ │ GOC_QUERY_TAILABLE_CURSOR. │
8759 │ │ Block rather than return‐ │
8760 │ │ ing no data. After a pe‐ │
8761 │ │ riod, time out. │
8762 ├───────────────────────────┼────────────────────────────┤
8763 │MONGOC_QUERY_EXHAUST │ Stream the data down full │
8764 │ │ blast in multiple "reply" │
8765 │ │ packets. Faster when you │
8766 │ │ are pulling down a lot of │
8767 │ │ data and you know you want │
8768 │ │ to retrieve it all. Only │
8769 │ │ applies to cursors created │
8770 │ │ from a find operation │
8771 │ │ (i.e. mongoc_collec‐ │
8772 │ │ tion_find()). │
8773 ├───────────────────────────┼────────────────────────────┤
8774 │MONGOC_QUERY_PARTIAL │ Get partial results from │
8775 │ │ mongos if some shards are │
8776 │ │ down (instead of throwing │
8777 │ │ an error). │
8778 └───────────────────────────┴────────────────────────────┘
8779
8780 mongoc_rand
8781 MongoDB Random Number Generator
8782
8783 Synopsis
8784 void
8785 mongoc_rand_add (const void *buf, int num, double entropy);
8786
8787 void
8788 mongoc_rand_seed (const void *buf, int num);
8789
8790 int
8791 mongoc_rand_status (void);
8792
8793 Description
8794 The mongoc_rand family of functions provide access to the low level
8795 randomness primitives used by the MongoDB C Driver. In particular,
8796 they control the creation of cryptographically strong pseudo-random
8797 bytes required by some security mechanisms.
8798
8799 While we can usually pull enough entropy from the environment, you may
8800 be required to seed the PRNG manually depending on your OS, hardware
8801 and other entropy consumers running on the same system.
8802
8803 Entropy
8804 mongoc_rand_add and mongoc_rand_seed allow the user to directly provide
8805 entropy. They differ insofar as mongoc_rand_seed requires that each
8806 bit provided is fully random. mongoc_rand_add allows the user to spec‐
8807 ify the degree of randomness in the provided bytes as well.
8808
8809 Status
8810 The mongoc_rand_status function allows the user to check the status of
8811 the mongoc PRNG. This can be used to guarantee sufficient entropy at
8812 program startup, rather than waiting for runtime errors to occur.
8813
8814 mongoc_read_concern_t
8815 Read Concern abstraction
8816
8817 Synopsis
8818 New in MongoDB 3.2.
8819
8820 The mongoc_read_concern_t allows clients to choose a level of isolation
8821 for their reads. The default, MONGOC_READ_CONCERN_LEVEL_LOCAL, is right
8822 for the great majority of applications.
8823
8824 You can specify a read concern on connection objects, database objects,
8825 or collection objects.
8826
8827 See readConcern on the MongoDB website for more information.
8828
8829 Read Concern is only sent to MongoDB when it has explicitly been set by
8830 mongoc_read_concern_set_level to anything other than NULL.
8831
8832 Read Concern Levels
8833 ┌────────────────────┬─────────────────────┬─────────────────────┐
8834 │Macro │ Description │ First MongoDB ver‐ │
8835 │ │ │ sion │
8836 ├────────────────────┼─────────────────────┼─────────────────────┤
8837 │MONGOC_READ_CON‐ │ Level "local", the │ 3.2 │
8838 │CERN_LEVEL_LOCAL │ default. │ │
8839 ├────────────────────┼─────────────────────┼─────────────────────┤
8840 │MONGOC_READ_CON‐ │ Level "majority". │ 3.2 │
8841 │CERN_LEVEL_MAJORITY │ │ │
8842 ├────────────────────┼─────────────────────┼─────────────────────┤
8843 │MONGOC_READ_CON‐ │ Level "lineariz‐ │ 3.4 │
8844 │CERN_LEVEL_LIN‐ │ able". │ │
8845 │EARIZABLE │ │ │
8846 ├────────────────────┼─────────────────────┼─────────────────────┤
8847 │MONGOC_READ_CON‐ │ Level "available". │ 3.6 │
8848 │CERN_LEVEL_AVAIL‐ │ │ │
8849 │ABLE │ │ │
8850 ├────────────────────┼─────────────────────┼─────────────────────┤
8851 │MONGOC_READ_CON‐ │ Level "snapshot". │ 4.0 │
8852 │CERN_LEVEL_SNAPSHOT │ │ │
8853 └────────────────────┴─────────────────────┴─────────────────────┘
8854
8855 For the sake of compatibility with future versions of MongoDB, mon‐
8856 goc_read_concern_set_level allows any string, not just this list of
8857 known read concern levels.
8858
8859 See Read Concern Levels in the MongoDB manual for more information
8860 about the individual read concern levels.
8861
8862 mongoc_read_mode_t
8863 Read Preference Modes
8864
8865 Synopsis
8866 typedef enum {
8867 MONGOC_READ_PRIMARY = (1 << 0),
8868 MONGOC_READ_SECONDARY = (1 << 1),
8869 MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
8870 MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
8871 MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
8872 } mongoc_read_mode_t;
8873
8874 Description
8875 This enum describes how reads should be dispatched. The default is MON‐
8876 GOC_READ_PRIMARY.
8877
8878 Please see the MongoDB website for a description of Read Preferences.
8879
8880 mongoc_read_prefs_t
8881 A read preference abstraction
8882
8883 Synopsis
8884 mongoc_read_prefs_t provides an abstraction on top of the MongoDB con‐
8885 nection read preferences. It allows for hinting to the driver which
8886 nodes in a replica set should be accessed first and how.
8887
8888 You can specify a read preference mode on connection objects, database
8889 objects, collection objects, or per-operation. Generally, it makes the
8890 most sense to stick with the global default mode, MONGOC_READ_PRIMARY.
8891 All of the other modes come with caveats that won't be covered in great
8892 detail here.
8893
8894 Read Modes
8895 ┌───────────────────────────┬────────────────────────────┐
8896 │MONGOC_READ_PRIMARY │ Default mode. All opera‐ │
8897 │ │ tions read from the cur‐ │
8898 │ │ rent replica set primary. │
8899 ├───────────────────────────┼────────────────────────────┤
8900 │MONGOC_READ_SECONDARY │ All operations read from │
8901 │ │ among the nearest sec‐ │
8902 │ │ ondary members of the │
8903 │ │ replica set. │
8904 └───────────────────────────┴────────────────────────────┘
8905
8906 │MONGOC_READ_PRIMARY_PRE‐ │ In most situations, opera‐ │
8907 │FERRED │ tions read from the pri‐ │
8908 │ │ mary but if it is unavail‐ │
8909 │ │ able, operations read from │
8910 │ │ secondary members. │
8911 ├───────────────────────────┼────────────────────────────┤
8912 │MONGOC_READ_SECONDARY_PRE‐ │ In most situations, opera‐ │
8913 │FERRED │ tions read from among the │
8914 │ │ nearest secondary members, │
8915 │ │ but if no secondaries are │
8916 │ │ available, operations read │
8917 │ │ from the primary. │
8918 ├───────────────────────────┼────────────────────────────┤
8919 │MONGOC_READ_NEAREST │ Operations read from among │
8920 │ │ the nearest members of the │
8921 │ │ replica set, irrespective │
8922 │ │ of the member's type. │
8923 └───────────────────────────┴────────────────────────────┘
8924
8925 Tag Sets
8926 Tag sets allow you to specify custom read preferences and write con‐
8927 cerns so that your application can target operations to specific mem‐
8928 bers.
8929
8930 Custom read preferences and write concerns evaluate tags sets in dif‐
8931 ferent ways: read preferences consider the value of a tag when select‐
8932 ing a member to read from, while write concerns ignore the value of a
8933 tag when selecting a member, except to consider whether or not the
8934 value is unique.
8935
8936 You can specify tag sets with the following read preference modes:
8937
8938 • primaryPreferred
8939
8940 • secondary
8941
8942 • secondaryPreferred
8943
8944 • nearest
8945
8946 Tags are not compatible with MONGOC_READ_PRIMARY and, in general, only
8947 apply when selecting a secondary member of a set for a read operation.
8948 However, the nearest read mode, when combined with a tag set, will se‐
8949 lect the nearest member that matches the specified tag set, which may
8950 be a primary or secondary.
8951
8952 Tag sets are represented as a comma-separated list of colon-separated
8953 key-value pairs when provided as a connection string, e.g.
8954 dc:ny,rack:1.
8955
8956 To specify a list of tag sets, using multiple readPreferenceTags, e.g.
8957
8958 readPreferenceTags=dc:ny,rack:1;readPreferenceTags=dc:ny;readPreferenceTags=
8959
8960 Note the empty value for the last one, which means "match any secondary
8961 as a last resort".
8962
8963 Order matters when using multiple readPreferenceTags.
8964
8965 Tag Sets can also be configured using mongoc_read_prefs_set_tags.
8966
8967 All interfaces use the same member selection logic to choose the member
8968 to which to direct read operations, basing the choice on read prefer‐
8969 ence mode and tag sets.
8970
8971 Max Staleness
8972 When connected to replica set running MongoDB 3.4 or later, the driver
8973 estimates the staleness of each secondary based on lastWriteDate values
8974 provided in server isMaster responses.
8975
8976 Max Staleness is the maximum replication lag in seconds (wall clock
8977 time) that a secondary can suffer and still be eligible for reads. The
8978 default is MONGOC_NO_MAX_STALENESS, which disables staleness checks.
8979 Otherwise, it must be a positive integer at least MONGOC_SMALL‐
8980 EST_MAX_STALENESS_SECONDS (90 seconds).
8981
8982 Max Staleness is also supported by sharded clusters of replica sets if
8983 all servers run MongoDB 3.4 or later.
8984
8985 Hedged Reads
8986 When connecting to a sharded cluster running MongoDB 4.4 or later,
8987 reads can be sent in parallel to the two "best" hosts. Once one result
8988 returns, any other outstanding operations that were part of the hedged
8989 read are cancelled.
8990
8991 When the read preference mode is MONGOC_READ_NEAREST and the sharded
8992 cluster is running MongoDB 4.4 or later, hedged reads are enabled by
8993 default. Additionally, hedged reads may be explicitly enabled or dis‐
8994 abled by calling mongoc_read_prefs_set_hedge with a BSON document, e.g.
8995
8996 {
8997 enabled: true
8998 }
8999
9000 Appropriate values for the enabled key are true or false.
9001
9002 mongoc_remove_flags_t
9003 Flags for deletion operations
9004
9005 Synopsis
9006 typedef enum {
9007 MONGOC_REMOVE_NONE = 0,
9008 MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0,
9009 } mongoc_remove_flags_t;
9010
9011 Description
9012 These flags correspond to the MongoDB wire protocol. They may be bit‐
9013 wise or'd together. They may change the number of documents that are
9014 removed during a remove command.
9015
9016 Flag Values
9017 ┌─────────────────────────┬────────────────────────────┐
9018 │MONGOC_REMOVE_NONE │ Specify no removal flags. │
9019 │ │ All matching documents │
9020 │ │ will be removed. │
9021 ├─────────────────────────┼────────────────────────────┤
9022 │MONGOC_REMOVE_SINGLE_RE‐ │ Only remove the first │
9023 │MOVE │ matching document from the │
9024 │ │ selector. │
9025 └─────────────────────────┴────────────────────────────┘
9026
9027 mongoc_reply_flags_t
9028 Flags from server replies
9029
9030 Synopsis
9031 typedef enum {
9032 MONGOC_REPLY_NONE = 0,
9033 MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0,
9034 MONGOC_REPLY_QUERY_FAILURE = 1 << 1,
9035 MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2,
9036 MONGOC_REPLY_AWAIT_CAPABLE = 1 << 3,
9037 } mongoc_reply_flags_t;
9038
9039 Description
9040 These flags correspond to the wire protocol. They may be bitwise or'd
9041 together.
9042
9043 Flag Values
9044 ┌───────────────────────────┬────────────────────────────┐
9045 │MONGOC_REPLY_NONE │ No flags set. │
9046 ├───────────────────────────┼────────────────────────────┤
9047 │MONGOC_REPLY_CUR‐ │ No matching cursor was │
9048 │SOR_NOT_FOUND │ found on the server. │
9049 ├───────────────────────────┼────────────────────────────┤
9050 │MONGOC_REPLY_QUERY_FAILURE │ The query failed or was │
9051 │ │ invalid. Error document │
9052 │ │ has been provided. │
9053 ├───────────────────────────┼────────────────────────────┤
9054 │MONGOC_REPLY_SHARD_CON‐ │ Shard config is stale. │
9055 │FIG_STALE │ │
9056 ├───────────────────────────┼────────────────────────────┤
9057 │MONGOC_REPLY_AWAIT_CAPABLE │ If the returned cursor is │
9058 │ │ capable of MON‐ │
9059 │ │ GOC_QUERY_AWAIT_DATA. │
9060 └───────────────────────────┴────────────────────────────┘
9061
9062 mongoc_server_description_t
9063 Server description
9064
9065 Synopsis
9066 #include <mongoc/mongoc.h>
9067 typedef struct _mongoc_server_description_t mongoc_server_description_t
9068
9069 mongoc_server_description_t holds information about a mongod or mongos
9070 the driver is connected to.
9071
9072 See also mongoc_client_get_server_descriptions().
9073
9074 Lifecycle
9075 Clean up with mongoc_server_description_destroy().
9076
9077 mongoc_session_opt_t
9078 #include <mongoc/mongoc.h>
9079
9080 typedef struct _mongoc_session_opt_t mongoc_session_opt_t;
9081
9082 Synopsis
9083 Start a session with mongoc_client_start_session, use the session for a
9084 sequence of operations and multi-document transactions, then free it
9085 with mongoc_client_session_destroy(). Any mongoc_cursor_t or mon‐
9086 goc_change_stream_t using a session must be destroyed before the ses‐
9087 sion, and a session must be destroyed before the mongoc_client_t it
9088 came from.
9089
9090 By default, sessions are causally consistent. To disable causal consis‐
9091 tency, before starting a session create a mongoc_session_opt_t with
9092 mongoc_session_opts_new() and call mongoc_session_opts_set_causal_con‐
9093 sistency(), then free the struct with mongoc_session_opts_destroy.
9094
9095 Unacknowledged writes are prohibited with sessions.
9096
9097 A mongoc_client_session_t must be used by only one thread at a time.
9098 Due to session pooling, mongoc_client_start_session may return a ses‐
9099 sion that has been idle for some time and is about to be closed after
9100 its idle timeout. Use the session within one minute of acquiring it to
9101 refresh the session and avoid a timeout.
9102
9103 See the example code for mongoc_session_opts_set_causal_consistency.
9104
9105 mongoc_socket_t
9106 Portable socket abstraction
9107
9108 Synopsis
9109 #include <mongoc/mongoc.h>
9110
9111 typedef struct _mongoc_socket_t mongoc_socket_t
9112
9113 Synopsis
9114 This structure provides a socket abstraction that is friendlier for
9115 portability than BSD sockets directly. Inconsistencies between Linux,
9116 various BSDs, Solaris, and Windows are handled here.
9117
9118 mongoc_ssl_opt_t
9119 Synopsis
9120 typedef struct {
9121 const char *pem_file;
9122 const char *pem_pwd;
9123 const char *ca_file;
9124 const char *ca_dir;
9125 const char *crl_file;
9126 bool weak_cert_validation;
9127 bool allow_invalid_hostname;
9128 void *internal;
9129 void *padding[6];
9130 } mongoc_ssl_opt_t;
9131
9132 Description
9133 This structure is used to set the TLS options for a mongoc_client_t or
9134 mongoc_client_pool_t.
9135
9136 Beginning in version 1.2.0, once a pool or client has any TLS options
9137 set, all connections use TLS, even if ssl=true is omitted from the Mon‐
9138 goDB URI. Before, TLS options were ignored unless tls=true was included
9139 in the URI.
9140
9141 As of 1.4.0, the mongoc_client_pool_set_ssl_opts and mon‐
9142 goc_client_set_ssl_opts will not only shallow copy the struct, but will
9143 also copy the const char*. It is therefore no longer needed to make
9144 sure the values remain valid after setting them.
9145
9146 See Also
9147 • configuring_tls
9148
9149 • mongoc_client_set_ssl_opts
9150
9151 • mongoc_client_pool_set_ssl_opts
9152
9153 mongoc_stream_buffered_t
9154 Synopsis
9155 typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t;
9156
9157 Description
9158 mongoc_stream_buffered_t should be considered a subclass of mon‐
9159 goc_stream_t. It performs buffering on an underlying stream.
9160
9161 See Also
9162 mongoc_stream_buffered_new()
9163
9164 mongoc_stream_destroy()
9165
9166 mongoc_stream_file_t
9167 Synopsis
9168 typedef struct _mongoc_stream_file_t mongoc_stream_file_t
9169
9170 mongoc_stream_file_t is a mongoc_stream_t subclass for working with
9171 standard UNIX style file-descriptors.
9172
9173 mongoc_stream_socket_t
9174 Synopsis
9175 typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t
9176
9177 mongoc_stream_socket_t should be considered a subclass of mon‐
9178 goc_stream_t that works upon socket streams.
9179
9180 mongoc_stream_t
9181 Synopsis
9182 typedef struct _mongoc_stream_t mongoc_stream_t
9183
9184 mongoc_stream_t provides a generic streaming IO abstraction based on a
9185 struct of pointers interface. The idea is to allow wrappers, perhaps
9186 other language drivers, to easily shim their IO system on top of mon‐
9187 goc_stream_t.
9188
9189 The API for the stream abstraction is currently private and non-exten‐
9190 sible.
9191
9192 Stream Types
9193 There are a number of built in stream types that come with mongoc. The
9194 default configuration is a buffered unix stream. If TLS is in use, that
9195 in turn is wrapped in a tls stream.
9196
9197 See Also
9198 mongoc_stream_buffered_t
9199
9200 mongoc_stream_file_t
9201
9202 mongoc_stream_socket_t
9203
9204 mongoc_stream_tls_t
9205
9206 mongoc_stream_tls_t
9207 Synopsis
9208 typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t
9209
9210 mongoc_stream_tls_t is a mongoc_stream_t subclass for working with TLS
9211 streams.
9212
9213 mongoc_topology_description_t
9214 Status of MongoDB Servers
9215
9216 Synopsis
9217 typedef struct _mongoc_topology_description_t mongoc_topology_description_t;
9218
9219 mongoc_topology_description_t is an opaque type representing the
9220 driver's knowledge of the MongoDB server or servers it is connected to.
9221 Its API conforms to the SDAM Monitoring Specification.
9222
9223 Applications receive a temporary reference to a mongoc_topology_de‐
9224 scription_t as a parameter to an SDAM Monitoring callback. See Intro‐
9225 duction to Application Performance Monitoring.
9226
9227 mongoc_transaction_opt_t
9228 #include <mongoc/mongoc.h>
9229
9230 typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;
9231
9232 Synopsis
9233 Options for starting a multi-document transaction.
9234
9235 When a session is first created with mongoc_client_start_session, it
9236 inherits from the client the read concern, write concern, and read
9237 preference with which to start transactions. Each of these fields can
9238 be overridden independently. Create a mongoc_transaction_opt_t with
9239 mongoc_transaction_opts_new, and pass a non-NULL option to any of the
9240 mongoc_transaction_opt_t setter functions:
9241
9242 • mongoc_transaction_opts_set_read_concern
9243
9244 • mongoc_transaction_opts_set_write_concern
9245
9246 • mongoc_transaction_opts_set_read_prefs
9247
9248 Pass the resulting transaction options to mongoc_client_ses‐
9249 sion_start_transaction. Each field set in the transaction options over‐
9250 rides the inherited client configuration.
9251
9252 Example
9253 example-transaction.c
9254
9255 /* gcc example-transaction.c -o example-transaction \
9256 * $(pkg-config --cflags --libs libmongoc-1.0) */
9257
9258 /* ./example-transaction [CONNECTION_STRING] */
9259
9260 #include <stdio.h>
9261 #include <mongoc/mongoc.h>
9262
9263
9264 int
9265 main (int argc, char *argv[])
9266 {
9267 int exit_code = EXIT_FAILURE;
9268
9269 mongoc_client_t *client = NULL;
9270 mongoc_database_t *database = NULL;
9271 mongoc_collection_t *collection = NULL;
9272 mongoc_client_session_t *session = NULL;
9273 mongoc_session_opt_t *session_opts = NULL;
9274 mongoc_transaction_opt_t *default_txn_opts = NULL;
9275 mongoc_transaction_opt_t *txn_opts = NULL;
9276 mongoc_read_concern_t *read_concern = NULL;
9277 mongoc_write_concern_t *write_concern = NULL;
9278 const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
9279 mongoc_uri_t *uri;
9280 bson_error_t error;
9281 bson_t *doc = NULL;
9282 bson_t *insert_opts = NULL;
9283 int32_t i;
9284 int64_t start;
9285 bson_t reply = BSON_INITIALIZER;
9286 char *reply_json;
9287 bool r;
9288
9289 mongoc_init ();
9290
9291 if (argc > 1) {
9292 uri_string = argv[1];
9293 }
9294
9295 uri = mongoc_uri_new_with_error (uri_string, &error);
9296 if (!uri) {
9297 MONGOC_ERROR ("failed to parse URI: %s\n"
9298 "error message: %s\n",
9299 uri_string,
9300 error.message);
9301 goto done;
9302 }
9303
9304 client = mongoc_client_new_from_uri (uri);
9305 if (!client) {
9306 goto done;
9307 }
9308
9309 mongoc_client_set_error_api (client, 2);
9310 database = mongoc_client_get_database (client, "example-transaction");
9311
9312 /* inserting into a nonexistent collection normally creates it, but a
9313 * collection can't be created in a transaction; create it now */
9314 collection =
9315 mongoc_database_create_collection (database, "collection", NULL, &error);
9316
9317 if (!collection) {
9318 /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
9319 if (error.code == 48) {
9320 collection = mongoc_database_get_collection (database, "collection");
9321 } else {
9322 MONGOC_ERROR ("Failed to create collection: %s", error.message);
9323 goto done;
9324 }
9325 }
9326
9327 /* a transaction's read preferences, read concern, and write concern can be
9328 * set on the client, on the default transaction options, or when starting
9329 * the transaction. for the sake of this example, set read concern on the
9330 * default transaction options. */
9331 default_txn_opts = mongoc_transaction_opts_new ();
9332 read_concern = mongoc_read_concern_new ();
9333 mongoc_read_concern_set_level (read_concern, "snapshot");
9334 mongoc_transaction_opts_set_read_concern (default_txn_opts, read_concern);
9335 session_opts = mongoc_session_opts_new ();
9336 mongoc_session_opts_set_default_transaction_opts (session_opts,
9337 default_txn_opts);
9338
9339 session = mongoc_client_start_session (client, session_opts, &error);
9340 if (!session) {
9341 MONGOC_ERROR ("Failed to start session: %s", error.message);
9342 goto done;
9343 }
9344
9345 /* in this example, set write concern when starting the transaction */
9346 txn_opts = mongoc_transaction_opts_new ();
9347 write_concern = mongoc_write_concern_new ();
9348 mongoc_write_concern_set_wmajority (write_concern, 1000 /* wtimeout */);
9349 mongoc_transaction_opts_set_write_concern (txn_opts, write_concern);
9350
9351 insert_opts = bson_new ();
9352 if (!mongoc_client_session_append (session, insert_opts, &error)) {
9353 MONGOC_ERROR ("Could not add session to opts: %s", error.message);
9354 goto done;
9355 }
9356
9357 retry_transaction:
9358 r = mongoc_client_session_start_transaction (session, txn_opts, &error);
9359 if (!r) {
9360 MONGOC_ERROR ("Failed to start transaction: %s", error.message);
9361 goto done;
9362 }
9363
9364 /* insert two documents - on error, retry the whole transaction */
9365 for (i = 0; i < 2; i++) {
9366 doc = BCON_NEW ("_id", BCON_INT32 (i));
9367 bson_destroy (&reply);
9368 r = mongoc_collection_insert_one (
9369 collection, doc, insert_opts, &reply, &error);
9370
9371 bson_destroy (doc);
9372
9373 if (!r) {
9374 MONGOC_ERROR ("Insert failed: %s", error.message);
9375 mongoc_client_session_abort_transaction (session, NULL);
9376
9377 /* a network error, primary failover, or other temporary error in a
9378 * transaction includes {"errorLabels": ["TransientTransactionError"]},
9379 * meaning that trying the entire transaction again may succeed
9380 */
9381 if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
9382 goto retry_transaction;
9383 }
9384
9385 goto done;
9386 }
9387
9388 reply_json = bson_as_json (&reply, NULL);
9389 printf ("%s\n", reply_json);
9390 bson_free (reply_json);
9391 }
9392
9393 /* in case of transient errors, retry for 5 seconds to commit transaction */
9394 start = bson_get_monotonic_time ();
9395 while (bson_get_monotonic_time () - start < 5 * 1000 * 1000) {
9396 bson_destroy (&reply);
9397 r = mongoc_client_session_commit_transaction (session, &reply, &error);
9398 if (r) {
9399 /* success */
9400 break;
9401 } else {
9402 MONGOC_ERROR ("Warning: commit failed: %s", error.message);
9403 if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
9404 goto retry_transaction;
9405 } else if (mongoc_error_has_label (&reply,
9406 "UnknownTransactionCommitResult")) {
9407 /* try again to commit */
9408 continue;
9409 }
9410
9411 /* unrecoverable error trying to commit */
9412 break;
9413 }
9414 }
9415
9416 exit_code = EXIT_SUCCESS;
9417
9418 done:
9419 bson_destroy (&reply);
9420 bson_destroy (insert_opts);
9421 mongoc_write_concern_destroy (write_concern);
9422 mongoc_read_concern_destroy (read_concern);
9423 mongoc_transaction_opts_destroy (txn_opts);
9424 mongoc_transaction_opts_destroy (default_txn_opts);
9425 mongoc_client_session_destroy (session);
9426 mongoc_collection_destroy (collection);
9427 mongoc_database_destroy (database);
9428 mongoc_uri_destroy (uri);
9429 mongoc_client_destroy (client);
9430
9431 mongoc_cleanup ();
9432
9433 return exit_code;
9434 }
9435
9436
9437 mongoc_transaction_state_t
9438 Constants for transaction states
9439
9440 Synopsis
9441 typedef enum {
9442 MONGOC_TRANSACTION_NONE = 0,
9443 MONGOC_TRANSACTION_STARTING = 1,
9444 MONGOC_TRANSACTION_IN_PROGRESS = 2,
9445 MONGOC_TRANSACTION_COMMITTED = 3,
9446 MONGOC_TRANSACTION_ABORTED = 4,
9447 } mongoc_transaction_state_t;
9448
9449 Description
9450 These constants describe the current transaction state of a session.
9451
9452 Flag Values
9453 ┌───────────────────────────┬────────────────────────────┐
9454 │MONGOC_TRANSACTION_NONE │ There is no transaction in │
9455 │ │ progress. │
9456 ├───────────────────────────┼────────────────────────────┤
9457 │MONGOC_TRANSACTION_START‐ │ A transaction has been │
9458 │ING │ started, but no operation │
9459 │ │ has been sent to the │
9460 │ │ server. │
9461 ├───────────────────────────┼────────────────────────────┤
9462 │MONGOC_TRANSAC‐ │ A transaction is in │
9463 │TION_IN_PROGRESS │ progress. │
9464 ├───────────────────────────┼────────────────────────────┤
9465 │MONGOC_TRANSACTION_COMMIT‐ │ The transaction was com‐ │
9466 │TED │ mitted. │
9467 ├───────────────────────────┼────────────────────────────┤
9468 │MONGOC_TRANSACTION_ABORTED │ The transaction was │
9469 │ │ aborted. │
9470 └───────────────────────────┴────────────────────────────┘
9471
9472 mongoc_update_flags_t
9473 Flags for update operations
9474
9475 Synopsis
9476 typedef enum {
9477 MONGOC_UPDATE_NONE = 0,
9478 MONGOC_UPDATE_UPSERT = 1 << 0,
9479 MONGOC_UPDATE_MULTI_UPDATE = 1 << 1,
9480 } mongoc_update_flags_t;
9481
9482 #define MONGOC_UPDATE_NO_VALIDATE (1U << 31)
9483
9484 Description
9485 These flags correspond to the MongoDB wire protocol. They may be bit‐
9486 wise or'd together. The allow for modifying the way an update is per‐
9487 formed in the MongoDB server.
9488
9489 Flag Values
9490 ┌───────────────────────────┬────────────────────────────┐
9491 │MONGOC_UPDATE_NONE │ No update flags set. │
9492 ├───────────────────────────┼────────────────────────────┤
9493 │MONGOC_UPDATE_UPSERT │ If an upsert should be │
9494 │ │ performed. │
9495 ├───────────────────────────┼────────────────────────────┤
9496 │MONGOC_UPDATE_MULTI_UPDATE │ If more than a single │
9497 │ │ matching document should │
9498 │ │ be updated. By default │
9499 │ │ only the first document is │
9500 │ │ updated. │
9501 ├───────────────────────────┼────────────────────────────┤
9502 │MONGOC_UPDATE_NO_VALIDATE │ Do not perform client side │
9503 │ │ BSON validations when per‐ │
9504 │ │ forming an update. This is │
9505 │ │ useful if you already know │
9506 │ │ your BSON documents are │
9507 │ │ valid. │
9508 └───────────────────────────┴────────────────────────────┘
9509
9510 mongoc_uri_t
9511 Synopsis
9512 typedef struct _mongoc_uri_t mongoc_uri_t;
9513
9514 Description
9515 mongoc_uri_t provides an abstraction on top of the MongoDB connection
9516 URI format. It provides standardized parsing as well as convenience
9517 methods for extracting useful information such as replica hosts or au‐
9518 thorization information.
9519
9520 See Connection String URI Reference on the MongoDB website for more in‐
9521 formation.
9522
9523 Format
9524 mongodb[+srv]:// <1>
9525 [username:password@] <2>
9526 host1 <3>
9527 [:port1] <4>
9528 [,host2[:port2],...[,hostN[:portN]]] <5>
9529 [/[database] <6>
9530 [?options]] <7>
9531
9532 1. "mongodb" is the specifier of the MongoDB protocol. Use "mon‐
9533 godb+srv" with a single service name in place of "host1" to specify
9534 the initial list of servers with an SRV record.
9535
9536 2. An optional username and password.
9537
9538 3. The only required part of the uri. This specifies either a host‐
9539 name, IPv4 address, IPv6 address enclosed in "[" and "]", or UNIX
9540 domain socket.
9541
9542 4. An optional port number. Defaults to :27017.
9543
9544 5. Extra optional hosts and ports. You would specify multiple hosts,
9545 for example, for connections to replica sets.
9546
9547 6. The name of the database to authenticate if the connection string
9548 includes authentication credentials. If /database is not specified
9549 and the connection string includes credentials, defaults to the 'ad‐
9550 min' database.
9551
9552 7. Connection specific options.
9553
9554 NOTE:
9555 Option names are case-insensitive. Do not repeat the same option
9556 (e.g. "mongodb://localhost/db?opt=value1&OPT=value2") since this may
9557 have unexpected results.
9558
9559 The MongoDB C Driver exposes constants for each supported connection
9560 option. These constants make it easier to discover connection options,
9561 but their string values can be used as well.
9562
9563 For example, the following calls are equal.
9564
9565 uri = mongoc_uri_new ("mongodb://localhost/?" MONGOC_URI_APPNAME "=applicationName");
9566 uri = mongoc_uri_new ("mongodb://localhost/?appname=applicationName");
9567 uri = mongoc_uri_new ("mongodb://localhost/?appName=applicationName");
9568
9569 Replica Set Example
9570 To describe a connection to a replica set named 'test' with the follow‐
9571 ing mongod hosts:
9572
9573 • db1.example.com on port 27017
9574
9575 • db2.example.com on port 2500
9576
9577 You would use a connection string that resembles the following.
9578
9579 mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test
9580
9581 SRV Example
9582 If you have configured an SRV record with a name like "_mon‐
9583 godb._tcp.server.example.com" whose records are a list of one or more
9584 MongoDB server hostnames, use a connection string like this:
9585
9586 uri = mongoc_uri_new ("mongodb+srv://server.example.com/?replicaSet=rs&appName=applicationName");
9587
9588 The driver prefixes the service name with "_mongodb._tcp.", then per‐
9589 forms a DNS SRV query to resolve the service name to one or more host‐
9590 names. If this query succeeds, the driver performs a DNS TXT query on
9591 the service name (without the "_mongodb._tcp" prefix) for additional
9592 URI options configured as TXT records.
9593
9594 On Unix, the MongoDB C Driver relies on libresolv to look up SRV and
9595 TXT records. If libresolv is unavailable, then using a "mongodb+srv"
9596 URI will cause an error. If your libresolv lacks res_nsearch then the
9597 driver will fall back to res_search, which is not thread-safe.
9598
9599 IPv4 and IPv6
9600 If connecting to a hostname that has both IPv4 and IPv6 DNS records,
9601 the behavior follows RFC-6555. A connection to the IPv6 address is at‐
9602 tempted first. If IPv6 fails, then a connection is attempted to the
9603 IPv4 address. If the connection attempt to IPv6 does not complete
9604 within 250ms, then IPv4 is tried in parallel. Whichever succeeds con‐
9605 nection first cancels the other. The successful DNS result is cached
9606 for 10 minutes.
9607
9608 As a consequence, attempts to connect to a mongod only listening on
9609 IPv4 may be delayed if there are both A (IPv4) and AAAA (IPv6) DNS
9610 records associated with the host.
9611
9612 To avoid a delay, configure hostnames to match the MongoDB configura‐
9613 tion. That is, only create an A record if the mongod is only listening
9614 on IPv4.
9615
9616 Connection Options
9617 ──────────────────────────────────────────────────────────────────────────
9618 Constant Key Description
9619 ──────────────────────────────────────────────────────────────────────────
9620 MON‐ retryreads If "true" and the
9621 GOC_URI_RETRYREADS server is a MongoDB
9622 3.6+ standalone,
9623 replica set, or
9624 sharded cluster,
9625 the driver safely
9626 retries a read that
9627 failed due to a
9628 network error or
9629 replica set
9630 failover.
9631 ──────────────────────────────────────────────────────────────────────────
9632 MONGOC_URI_RETRY‐ retrywrites If "true" and the
9633 WRITES server is a MongoDB
9634 3.6+ replica set or
9635 sharded cluster,
9636 the driver safely
9637 retries a write
9638 that failed due to
9639 a network error or
9640 replica set
9641 failover. Only in‐
9642 serts, updates of
9643 single documents,
9644 or deletes of sin‐
9645 gle documents are
9646 retried.
9647 ──────────────────────────────────────────────────────────────────────────
9648 MONGOC_URI_APPNAME appname The client applica‐
9649 tion name. This
9650 value is used by
9651 MongoDB when it
9652 logs connection in‐
9653 formation and pro‐
9654 file information,
9655 such as slow
9656 queries.
9657 ──────────────────────────────────────────────────────────────────────────
9658 MONGOC_URI_TLS tls {true|false}, indi‐
9659 cating if TLS must
9660 be used. (See also
9661 mon‐
9662 goc_client_set_ssl_opts
9663 and mon‐
9664 goc_client_pool_set_ssl_opts.)
9665 ──────────────────────────────────────────────────────────────────────────
9666 MONGOC_URI_COMPRES‐ compressors Comma separated list of com‐
9667 SORS pressors, if any, to use to
9668 compress the wire protocol
9669 messages. Snappy, zlib, and
9670 zstd are optional build time
9671 dependencies, and enable the
9672 "snappy", "zlib", and "zstd"
9673 values respectively. Defaults
9674 to empty (no compressors).
9675 ──────────────────────────────────────────────────────────────────────────
9676 MONGOC_URI_CONNECT‐ connecttimeoutms This setting applies to new
9677 TIMEOUTMS server connections. It is also
9678 used as the socket timeout for
9679 server discovery and monitor‐
9680 ing operations. The default is
9681 10,000 ms (10 seconds).
9682 ──────────────────────────────────────────────────────────────────────────
9683 MONGOC_URI_SOCKET‐ sockettimeoutms The time in milliseconds to
9684 TIMEOUTMS attempt to send or receive on
9685 a socket before the attempt
9686 times out. The default is
9687 300,000 (5 minutes).
9688 ──────────────────────────────────────────────────────────────────────────
9689 MONGOC_URI_REPLI‐ replicaset The name of the Replica Set
9690 CASET that the driver should connect
9691 to.
9692 ──────────────────────────────────────────────────────────────────────────
9693 MONGOC_URI_ZLIBCOM‐ zlibcompression‐ When the MONGOC_URI_COMPRES‐
9694 PRESSIONLEVEL level SORS includes "zlib" this op‐
9695 tions configures the zlib com‐
9696 pression level, when the zlib
9697 compressor is used to compress
9698 client data.
9699 ┌────────────────────┬──────────────────┬────────────────────────────────┐
9700 │ │ │ │
9701 │Setting any of the *│timeoutMS options a│bove to 0 will be interpreted as │
9702 │"use the default val│ue". │ │
9703 │ │ │ │
9704 Aut│hentication Options │ │ │
9705 │ ┌────────────────┼───┬──────────────┼─────┬─────────────────────┐ │
9706 │ │Constant │ │ Key │ │ Description │ │
9707 │ └────────────────┴───┴──────────────┴─────┴─────────────────────┘ │
9708
9709
9710 │MONGOC_URI_AUTH‐ │ authmechanism │ Specifies the mech‐ │
9711 │MECHANISM │ │ anism to use when │
9712 │ │ │ authenticating as │
9713 │ │ │ the provided user. │
9714 │ │ │ See Authentication │
9715 │ │ │ for supported val‐ │
9716 │ │ │ ues. │
9717 ├────────────────────┼────────────────────┼─────────────────────┤
9718 │MONGOC_URI_AUTH‐ │ authmechanismprop‐ │ Certain authentica‐ │
9719 │MECHANISMPROPERTIES │ erties │ tion mechanisms │
9720 │ │ │ have additional op‐ │
9721 │ │ │ tions that can be │
9722 │ │ │ configured. These │
9723 │ │ │ options should be │
9724 │ │ │ provided as comma │
9725 │ │ │ separated op‐ │
9726 │ │ │ tion_key:op‐ │
9727 │ │ │ tion_value pair and │
9728 │ │ │ provided as auth‐ │
9729 │ │ │ MechanismProper‐ │
9730 │ │ │ ties. │
9731 ├────────────────────┼────────────────────┼─────────────────────┤
9732 │MONGOC_URI_AUTH‐ │ authsource │ The authSource de‐ │
9733 │SOURCE │ │ fines the database │
9734 │ │ │ that should be used │
9735 │ │ │ to authenticate to. │
9736 │ │ │ It is unnecessary │
9737 │ │ │ to provide this op‐ │
9738 │ │ │ tion the database │
9739 │ │ │ name is the same as │
9740 │ │ │ the database used │
9741 │ │ │ in the URI. │
9742 └────────────────────┴────────────────────┴─────────────────────┘
9743
9744 Mechanism Properties
9745 ┌────────────────────┬───────────────────┬─────────────────────┐
9746 │Constant │ Key │ Description │
9747 ├────────────────────┼───────────────────┼─────────────────────┤
9748 │MONGOC_URI_CANONI‐ │ canonicalizehost‐ │ Use the canonical │
9749 │CALIZEHOSTNAME │ name │ hostname of the │
9750 │ │ │ service, rather │
9751 │ │ │ than its configured │
9752 │ │ │ alias, when authen‐ │
9753 │ │ │ ticating with │
9754 │ │ │ Cyrus-SASL Ker‐ │
9755 │ │ │ beros. │
9756 ├────────────────────┼───────────────────┼─────────────────────┤
9757 │MONGOC_URI_GSSAPIS‐ │ gssapiservicename │ Use alternative │
9758 │ERVICENAME │ │ service name. The │
9759 │ │ │ default is mongodb. │
9760 └────────────────────┴───────────────────┴─────────────────────┘
9761
9762 TLS Options
9763 ┌────────────────────┬─────────────────────┬─────────────────────┐
9764 │Constant │ Key │ Description │
9765 ├────────────────────┼─────────────────────┼─────────────────────┤
9766 │MONGOC_URI_TLS │ tls │ {true|false}, indi‐ │
9767 │ │ │ cating if TLS must │
9768 │ │ │ be used. │
9769 ├────────────────────┼─────────────────────┼─────────────────────┤
9770 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ Path to PEM format‐ │
9771 │TIFICATEKEYFILE │ file │ ted Private Key, │
9772 │ │ │ with its Public │
9773 │ │ │ Certificate con‐ │
9774 │ │ │ catenated at the │
9775 │ │ │ end. │
9776 ├────────────────────┼─────────────────────┼─────────────────────┤
9777 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ The password, if │
9778 │TIFICATEKEYPASSWORD │ password │ any, to use to un‐ │
9779 │ │ │ lock encrypted Pri‐ │
9780 │ │ │ vate Key. │
9781 ├────────────────────┼─────────────────────┼─────────────────────┤
9782 │MON‐ │ tlscafile │ One, or a bundle │
9783 │GOC_URI_TLSCAFILE │ │ of, Certificate Au‐ │
9784 │ │ │ thorities whom │
9785 │ │ │ should be consid‐ │
9786 │ │ │ ered to be trusted. │
9787 ├────────────────────┼─────────────────────┼─────────────────────┤
9788 │MONGOC_URI_TLSAL‐ │ tlsallowinvalidcer‐ │ Accept and ignore │
9789 │LOWINVALIDCERTIFI‐ │ tificates │ certificate verifi‐ │
9790 │CATES │ │ cation errors (e.g. │
9791 │ │ │ untrusted issuer, │
9792 │ │ │ expired, etc.) │
9793 └────────────────────┴─────────────────────┴─────────────────────┘
9794
9795
9796
9797
9798
9799
9800 │MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │ Ignore hostname │
9801 │LOWINVALIDHOSTNAMES │ hostnames │ verification of the │
9802 │ │ │ certificate (e.g. │
9803 │ │ │ Man In The Middle, │
9804 │ │ │ using valid cer‐ │
9805 │ │ │ tificate, but is‐ │
9806 │ │ │ sued for another │
9807 │ │ │ hostname) │
9808 ├────────────────────┼─────────────────────┼─────────────────────┤
9809 │MONGOC_URI_TLSINSE‐ │ tlsinsecure │ {true|false}, indi‐ │
9810 │CURE │ │ cating if insecure │
9811 │ │ │ TLS options should │
9812 │ │ │ be used. Currently │
9813 │ │ │ this implies MON‐ │
9814 │ │ │ GOC_URI_TLSALLOWIN‐ │
9815 │ │ │ VALIDCERTIFICATES │
9816 │ │ │ and MONGOC_URI_TL‐ │
9817 │ │ │ SALLOWINVALIDHOST‐ │
9818 │ │ │ NAMES. │
9819 ├────────────────────┼─────────────────────┼─────────────────────┤
9820 │MONGOC_URI_TLSDIS‐ │ tlsdisablecertifi‐ │ {true|false}, indi‐ │
9821 │ABLECERTIFICATERE‐ │ caterevocationcheck │ cates if revocation │
9822 │VOCATIONCHECK │ │ checking (CRL / │
9823 │ │ │ OCSP) should be │
9824 │ │ │ disabled. │
9825 ├────────────────────┼─────────────────────┼─────────────────────┤
9826 │MONGOC_URI_TLSDIS‐ │ tlsdisableocspend‐ │ {true|false}, indi‐ │
9827 │ABLEOCSPEND‐ │ pointcheck │ cates if OCSP re‐ │
9828 │POINTCHECK │ │ sponder endpoints │
9829 │ │ │ should not be re‐ │
9830 │ │ │ quested when an │
9831 │ │ │ OCSP response is │
9832 │ │ │ not stapled. │
9833 └────────────────────┴─────────────────────┴─────────────────────┘
9834
9835 See configuring_tls for details about these options and about building
9836 libmongoc with TLS support.
9837
9838 Deprecated SSL Options
9839 The following options have been deprecated and may be removed from fu‐
9840 ture releases of libmongoc.
9841
9842 ┌──────────────────────┬──────────────────┬───────────────────┬──────────────────┐
9843 │Constant │ Key │ Deprecated For │ Key │
9844 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9845 │MONGOC_URI_SSL │ ssl │ MONGOC_URI_TLS │ tls │
9846 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9847 │MON‐ │ sslclientcer‐ │ MON‐ │ tlscertifi‐ │
9848 │GOC_URI_SSLCLIENTCER‐ │ tificatekeyfile │ GOC_URI_TLSCER‐ │ catekeyfile │
9849 │TIFICATEKEYFILE │ │ TIFICATEKEYFILE │ │
9850 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9851 │MON‐ │ sslclientcer‐ │ MON‐ │ tlscertifi‐ │
9852 │GOC_URI_SSLCLIENTCER‐ │ tificatekeypass‐ │ GOC_URI_TLSCER‐ │ catekeypassword │
9853 │TIFICATEKEYPASSWORD │ word │ TIFICATEKEYPASS‐ │ │
9854 │ │ │ WORD │ │
9855 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9856 │MONGOC_URI_SSLCER‐ │ sslcertifi‐ │ MON‐ │ tlscafile │
9857 │TIFICATEAUTHORITYFILE │ cateauthority‐ │ GOC_URI_TLSCAFILE │ │
9858 │ │ file │ │ │
9859 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9860 │MONGOC_URI_SSLALLOW‐ │ sslallowinvalid‐ │ MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │
9861 │INVALIDCERTIFICATES │ certificates │ LOWINVALIDCER‐ │ certificates │
9862 │ │ │ TIFICATES │ │
9863 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
9864 │MONGOC_URI_SSLALLOW‐ │ sslallowinvalid‐ │ MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │
9865 │INVALIDHOSTNAMES │ hostnames │ LOWINVALIDHOST‐ │ hostnames │
9866 │ │ │ NAMES │ │
9867 └──────────────────────┴──────────────────┴───────────────────┴──────────────────┘
9868
9869 Server Discovery, Monitoring, and Selection Options
9870 Clients in a mongoc_client_pool_t share a topology scanner that runs on
9871 a background thread. The thread wakes every heartbeatFrequencyMS (de‐
9872 fault 10 seconds) to scan all MongoDB servers in parallel. Whenever an
9873 application operation requires a server that is not known--for example,
9874 if there is no known primary and your application attempts an in‐
9875 sert--the thread rescans all servers every half-second. In this situa‐
9876 tion the pooled client waits up to serverSelectionTimeoutMS (default 30
9877 seconds) for the thread to find a server suitable for the operation,
9878 then returns an error with domain MONGOC_ERROR_SERVER_SELECTION.
9879
9880 Technically, the total time an operation may wait while a pooled client
9881 scans the topology is controlled both by serverSelectionTimeoutMS and
9882 connectTimeoutMS. The longest wait occurs if the last scan begins just
9883 at the end of the selection timeout, and a slow or down server requires
9884 the full connection timeout before the client gives up.
9885
9886 A non-pooled client is single-threaded. Every heartbeatFrequencyMS, it
9887 blocks the next application operation while it does a parallel scan.
9888 This scan takes as long as needed to check the slowest server: roughly
9889 connectTimeoutMS. Therefore the default heartbeatFrequencyMS for sin‐
9890 gle-threaded clients is greater than for pooled clients: 60 seconds.
9891
9892 By default, single-threaded (non-pooled) clients scan only once when an
9893 operation requires a server that is not known. If you attempt an insert
9894 and there is no known primary, the client checks all servers once try‐
9895 ing to find it, then succeeds or returns an error with domain MON‐
9896 GOC_ERROR_SERVER_SELECTION. But if you set serverSelectionTryOnce to
9897 "false", the single-threaded client loops, checking all servers every
9898 half-second, until serverSelectionTimeoutMS.
9899
9900 The total time an operation may wait for a single-threaded client to
9901 scan the topology is determined by connectTimeoutMS in the try-once
9902 case, or serverSelectionTimeoutMS and connectTimeoutMS if serverSelec‐
9903 tionTryOnce is set "false".
9904
9905 ┌────────────────────┬─────────────────────┬─────────────────────┐
9906 │Constant │ Key │ Description │
9907 ├────────────────────┼─────────────────────┼─────────────────────┤
9908 │MONGOC_URI_HEART‐ │ heartbeatfrequen‐ │ The interval be‐ │
9909 │BEATFREQUENCYMS │ cyms │ tween server moni‐ │
9910 │ │ │ toring checks. De‐ │
9911 │ │ │ faults to 10,000ms │
9912 │ │ │ (10 seconds) in │
9913 │ │ │ pooled │
9914 │ │ │ (multi-threaded) │
9915 │ │ │ mode, 60,000ms (60 │
9916 │ │ │ seconds) in │
9917 │ │ │ non-pooled mode │
9918 │ │ │ (single-threaded). │
9919 ├────────────────────┼─────────────────────┼─────────────────────┤
9920 │MONGOC_URI_SERVERS‐ │ serverselection‐ │ A timeout in mil‐ │
9921 │ELECTIONTIMEOUTMS │ timeoutms │ liseconds to block │
9922 │ │ │ for server selec‐ │
9923 │ │ │ tion before throw‐ │
9924 │ │ │ ing an exception. │
9925 │ │ │ The default is │
9926 │ │ │ 30,0000ms (30 sec‐ │
9927 │ │ │ onds). │
9928 ├────────────────────┼─────────────────────┼─────────────────────┤
9929 │MONGOC_URI_SERVERS‐ │ serverselectiontry‐ │ If "true", the │
9930 │ELECTIONTRYONCE │ once │ driver scans the │
9931 │ │ │ topology exactly │
9932 │ │ │ once after server │
9933 │ │ │ selection fails, │
9934 │ │ │ then either selects │
9935 │ │ │ a server or returns │
9936 │ │ │ an error. If it is │
9937 │ │ │ false, then the │
9938 │ │ │ driver repeatedly │
9939 │ │ │ searches for a │
9940 │ │ │ suitable server for │
9941 │ │ │ up to serverSelec‐ │
9942 │ │ │ tionTimeoutMS mil‐ │
9943 │ │ │ liseconds (pausing │
9944 │ │ │ a half second be‐ │
9945 │ │ │ tween attempts). │
9946 │ │ │ The default for │
9947 │ │ │ serverSelectionTry‐ │
9948 │ │ │ Once is "false" for │
9949 │ │ │ pooled clients, │
9950 │ │ │ otherwise "true". │
9951 │ │ │ Pooled clients ig‐ │
9952 │ │ │ nore serverSelec‐ │
9953 │ │ │ tionTryOnce; they │
9954 │ │ │ signal the thread │
9955 │ │ │ to rescan the │
9956 │ │ │ topology every │
9957 │ │ │ half-second until │
9958 │ │ │ serverSelection‐ │
9959 │ │ │ TimeoutMS expires. │
9960 ├────────────────────┼─────────────────────┼─────────────────────┤
9961 │MONGOC_URI_SOCK‐ │ socketcheckinter‐ │ Only applies to │
9962 │ETCHECKINTERVALMS │ valms │ single threaded │
9963 │ │ │ clients. If a │
9964 │ │ │ socket has not been │
9965 │ │ │ used within this │
9966 │ │ │ time, its connec‐ │
9967 │ │ │ tion is checked │
9968 │ │ │ with a quick "is‐ │
9969 │ │ │ Master" call before │
9970 │ │ │ it is used again. │
9971 │ │ │ Defaults to 5,000ms │
9972 │ │ │ (5 seconds). │
9973 └────────────────────┴─────────────────────┴─────────────────────┘
9974
9975
9976
9977
9978
9979
9980 │MONGOC_URI_DIRECT‐ │ directconnection │ If "true", the │
9981 │CONNECTION │ │ driver connects to │
9982 │ │ │ a single server di‐ │
9983 │ │ │ rectly and will not │
9984 │ │ │ monitor additional │
9985 │ │ │ servers. If │
9986 │ │ │ "false", the driver │
9987 │ │ │ connects based on │
9988 │ │ │ the presence and │
9989 │ │ │ value of the repli‐ │
9990 │ │ │ caSet option. │
9991 └────────────────────┴─────────────────────┴─────────────────────┘
9992
9993 Setting any of the *TimeoutMS options above to 0 will be interpreted as
9994 "use the default value".
9995
9996 Connection Pool Options
9997 These options govern the behavior of a mongoc_client_pool_t. They are
9998 ignored by a non-pooled mongoc_client_t.
9999
10000 ┌────────────────────┬────────────────────┬─────────────────────┐
10001 │Constant │ Key │ Description │
10002 ├────────────────────┼────────────────────┼─────────────────────┤
10003 │MONGOC_URI_MAXPOOL‐ │ maxpoolsize │ The maximum number │
10004 │SIZE │ │ of clients created │
10005 │ │ │ by a mon‐ │
10006 │ │ │ goc_client_pool_t │
10007 │ │ │ total (both in the │
10008 │ │ │ pool and checked │
10009 │ │ │ out). The default │
10010 │ │ │ value is 100. Once │
10011 │ │ │ it is reached, mon‐ │
10012 │ │ │ goc_client_pool_pop │
10013 │ │ │ blocks until an‐ │
10014 │ │ │ other thread pushes │
10015 │ │ │ a client. │
10016 ├────────────────────┼────────────────────┼─────────────────────┤
10017 │MONGOC_URI_MINPOOL‐ │ minpoolsize │ Deprecated. This │
10018 │SIZE │ │ option's behavior │
10019 │ │ │ does not match its │
10020 │ │ │ name, and its ac‐ │
10021 │ │ │ tual behavior will │
10022 │ │ │ likely hurt perfor‐ │
10023 │ │ │ mance. │
10024 ├────────────────────┼────────────────────┼─────────────────────┤
10025 │MONGOC_URI_MAXIDLE‐ │ maxidletimems │ Not implemented. │
10026 │TIMEMS │ │ │
10027 ├────────────────────┼────────────────────┼─────────────────────┤
10028 │MONGOC_URI_WAIT‐ │ waitqueuemultiple │ Not implemented. │
10029 │QUEUEMULTIPLE │ │ │
10030 ├────────────────────┼────────────────────┼─────────────────────┤
10031 │MONGOC_URI_WAIT‐ │ waitqueuetimeoutms │ The maximum time to │
10032 │QUEUETIMEOUTMS │ │ wait for a client │
10033 │ │ │ to become available │
10034 │ │ │ from the pool. │
10035 └────────────────────┴────────────────────┴─────────────────────┘
10036
10037 Write Concern Options
10038 ┌───────────────────┬────────────┬─────────────────────┐
10039 │Constant │ Key │ Description │
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 MONGOC_URI_W w Determines the
10071 write concern
10072 (guarantee). Valid
10073 values:
10074
10075 • 0 = The
10076 driver
10077 will not
10078 acknowl‐
10079 edge write
10080 operations
10081 but will
10082 pass or
10083 handle any
10084 network
10085 and socket
10086 errors
10087 that it
10088 receives
10089 to the
10090 client. If
10091 you dis‐
10092 able write
10093 concern
10094 but enable
10095 the get‐
10096 LastError
10097 command’s
10098 w option,
10099 w over‐
10100 rides the
10101 w option.
10102
10103 • 1 = Pro‐
10104 vides ba‐
10105 sic ac‐
10106 knowledge‐
10107 ment of
10108 write op‐
10109 erations.
10110 By speci‐
10111 fying 1,
10112 you re‐
10113 quire that
10114 a stand‐
10115 alone mon‐
10116 god in‐
10117 stance, or
10118 the pri‐
10119 mary for
10120 replica
10121 sets, ac‐
10122 knowledge
10123 all write
10124 opera‐
10125 tions. For
10126 drivers
10127 released
10128 after the
10129 default
10130 write con‐
10131 cern
10132 change,
10133 this is
10134 the de‐
10135 fault
10136 write con‐
10137 cern set‐
10138 ting.
10139
10140 • majority =
10141 For
10142 replica
10143 sets, if
10144 you spec‐
10145 ify the
10146 special
10147 majority
10148 value to w
10149 option,
10150 write op‐
10151 erations
10152 will only
10153 return
10154 success‐
10155 fully af‐
10156 ter a ma‐
10157 jority of
10158 the con‐
10159 figured
10160 replica
10161 set mem‐
10162 bers have
10163 acknowl‐
10164 edged the
10165 write op‐
10166 eration.
10167
10168 • n = For
10169 replica
10170 sets, if
10171 you spec‐
10172 ify a num‐
10173 ber n
10174 greater
10175 than 1,
10176 operations
10177 with this
10178 write con‐
10179 cern re‐
10180 turn only
10181 after n
10182 members of
10183 the set
10184 have ac‐
10185 knowledged
10186 the write.
10187 If you set
10188 n to a
10189 number
10190 that is
10191 greater
10192 than the
10193 number of
10194 available
10195 set mem‐
10196 bers or
10197 members
10198 that hold
10199 data, Mon‐
10200 goDB will
10201 wait, po‐
10202 tentially
10203 indefi‐
10204 nitely,
10205 for these
10206 members to
10207 become
10208 available.
10209
10210 • tags = For
10211 replica
10212 sets, you
10213 can spec‐
10214 ify a tag
10215 set to re‐
10216 quire that
10217 all mem‐
10218 bers of
10219 the set
10220 that have
10221 these tags
10222 configured
10223 return
10224 confirma‐
10225 tion of
10226 the write
10227 operation.
10228 ├───────────────────┼────────────┼─────────────────────┤
10229 │MONGOC_URI_WTIME‐ │ wtimeoutms │ The time in mil‐ │
10230 │OUTMS │ │ liseconds to wait │
10231 │ │ │ for replication to │
10232 │ │ │ succeed, as speci‐ │
10233 │ │ │ fied in the w op‐ │
10234 │ │ │ tion, before timing │
10235 │ │ │ out. When wtime‐ │
10236 │ │ │ outMS is 0, write │
10237 │ │ │ operations will │
10238 │ │ │ never time out. │
10239 ├───────────────────┼────────────┼─────────────────────┤
10240 │MONGOC_URI_JOURNAL │ journal │ Controls whether │
10241 │ │ │ write operations │
10242 │ │ │ will wait until the │
10243 │ │ │ mongod acknowledges │
10244 │ │ │ the write opera‐ │
10245 │ │ │ tions and commits │
10246 │ │ │ the data to the on │
10247 │ │ │ disk journal. │
10248 │ │ │ │
10249 │ │ │ • true = │
10250 │ │ │ Enables │
10251 │ │ │ journal │
10252 │ │ │ commit ac‐ │
10253 │ │ │ knowledge‐ │
10254 │ │ │ ment write │
10255 │ │ │ concern. │
10256 │ │ │ Equivalent │
10257 │ │ │ to speci‐ │
10258 │ │ │ fying the │
10259 │ │ │ getLastEr‐ │
10260 │ │ │ ror com‐ │
10261 │ │ │ mand with │
10262 │ │ │ the j op‐ │
10263 │ │ │ tion en‐ │
10264 │ │ │ abled. │
10265 │ │ │ │
10266 │ │ │ • false = │
10267 │ │ │ Does not │
10268 │ │ │ require │
10269 │ │ │ that mon‐ │
10270 │ │ │ god commit │
10271 │ │ │ write op‐ │
10272 │ │ │ erations │
10273 │ │ │ to the │
10274 │ │ │ journal │
10275 │ │ │ before ac‐ │
10276 │ │ │ knowledg‐ │
10277 │ │ │ ing the │
10278 │ │ │ write op‐ │
10279 │ │ │ eration. │
10280 │ │ │ This is │
10281 │ │ │ the de‐ │
10282 │ │ │ fault op‐ │
10283 │ │ │ tion for │
10284 │ │ │ the jour‐ │
10285 │ │ │ nal param‐ │
10286 │ │ │ eter. │
10287 └───────────────────┴────────────┴─────────────────────┘
10288
10289 Read Concern Options
10290 ┌────────────────────┬──────────────────┬─────────────────────┐
10291 │Constant │ Key │ Description │
10292 ├────────────────────┼──────────────────┼─────────────────────┤
10293 │MONGOC_URI_READCON‐ │ readconcernlevel │ The level of isola‐ │
10294 │CERNLEVEL │ │ tion for read oper‐ │
10295 │ │ │ ations. If the │
10296 │ │ │ level is left un‐ │
10297 │ │ │ specified, the │
10298 │ │ │ server default will │
10299 │ │ │ be used. See │
10300 │ │ │ readConcern in the │
10301 │ │ │ MongoDB Manual for │
10302 │ │ │ details. │
10303 └────────────────────┴──────────────────┴─────────────────────┘
10304
10305 Read Preference Options
10306 When connected to a replica set, the driver chooses which member to
10307 query using the read preference:
10308
10309 1. Choose members whose type matches "readPreference".
10310
10311 2. From these, if there are any tags sets configured, choose members
10312 matching the first tag set. If there are none, fall back to the next
10313 tag set and so on, until some members are chosen or the tag sets are
10314 exhausted.
10315
10316 3. From the chosen servers, distribute queries randomly among the
10317 server with the fastest round-trip times. These include the server
10318 with the fastest time and any whose round-trip time is no more than
10319 "localThresholdMS" slower.
10320
10321 ┌────────────────────┬─────────────────────┬──────────────────────────┐
10322 │Constant │ Key │ Description │
10323 ├────────────────────┼─────────────────────┼──────────────────────────┤
10324 │MONGOC_URI_READ‐ │ readpreference │ Specifies the │
10325 │PREFERENCE │ │ replica set read │
10326 │ │ │ preference for this │
10327 │ │ │ connection. This │
10328 │ │ │ setting overrides │
10329 │ │ │ any slaveOk value. │
10330 │ │ │ The read preference │
10331 │ │ │ values are the fol‐ │
10332 │ │ │ lowing: │
10333 │ │ │ │
10334 │ │ │ • primary │
10335 │ │ │ (default) │
10336 │ │ │ │
10337 │ │ │ • prima‐ │
10338 │ │ │ ryPre‐ │
10339 │ │ │ ferred │
10340 │ │ │ │
10341 │ │ │ • secondary │
10342 │ │ │ │
10343 │ │ │ • sec‐ │
10344 │ │ │ ondaryPre‐ │
10345 │ │ │ ferred │
10346 │ │ │ │
10347 │ │ │ • nearest │
10348 ├────────────────────┼─────────────────────┼──────────────────────────┤
10349 │MONGOC_URI_READ‐ │ readpreferencetags │ A representation of │
10350 │PREFERENCETAGS │ │ a tag set. See also │
10351 │ │ │ mon‐ │
10352 │ │ │ goc-read-prefs-tag-sets. │
10353 ├────────────────────┼─────────────────────┼──────────────────────────┤
10354 │MONGOC_URI_LO‐ │ localthresholdms │ How far to distribute │
10355 │CALTHRESHOLDMS │ │ queries, beyond the │
10356 │ │ │ server with the fastest │
10357 │ │ │ round-trip time. By de‐ │
10358 │ │ │ fault, only servers │
10359 │ │ │ within 15ms of the │
10360 │ │ │ fastest round-trip time │
10361 │ │ │ receive queries. │
10362 ├────────────────────┼─────────────────────┼──────────────────────────┤
10363 │MONGOC_URI_MAXSTAL‐ │ maxstalenessseconds │ The maximum replication │
10364 │ENESSSECONDS │ │ lag, in wall clock time, │
10365 │ │ │ that a secondary can │
10366 │ │ │ suffer and still be eli‐ │
10367 │ │ │ gible. The smallest al‐ │
10368 │ │ │ lowed value for maxStal‐ │
10369 │ │ │ enessSeconds is 90 sec‐ │
10370 │ │ │ onds. │
10371 └────────────────────┴─────────────────────┴──────────────────────────┘
10372
10373 NOTE:
10374 When connecting to more than one mongos, libmongoc's localThresh‐
10375 oldMS applies only to the selection of mongos servers. The threshold
10376 for selecting among replica set members in shards is controlled by
10377 the mongos's localThreshold command line option.
10378
10379 Legacy Options
10380 For historical reasons, the following options are available. They
10381 should however not be used.
10382
10383 ┌───────────────────┬─────────┬─────────────────────┐
10384 │Constant │ Key │ Description │
10385 ├───────────────────┼─────────┼─────────────────────┤
10386 │MONGOC_URI_SAFE │ safe │ {true|false} Same │
10387 │ │ │ as w={1|0} │
10388 ├───────────────────┼─────────┼─────────────────────┤
10389 │MONGOC_URI_SLAVEOK │ slaveok │ When set, same as │
10390 │ │ │ readPreference=sec‐ │
10391 │ │ │ ondaryPreferred │
10392 └───────────────────┴─────────┴─────────────────────┘
10393
10394 Version Checks
10395 Conditional compilation based on mongoc version
10396
10397 Description
10398 The following preprocessor macros can be used to perform various checks
10399 based on the version of the library you are compiling against. This
10400 may be useful if you only want to enable a feature on a certain version
10401 of the library.
10402
10403 #include <mongoc/mongoc.h>
10404
10405 #define MONGOC_MAJOR_VERSION (x)
10406 #define MONGOC_MINOR_VERSION (y)
10407 #define MONGOC_MICRO_VERSION (z)
10408 #define MONGOC_VERSION_S "x.y.z"
10409 #define MONGOC_VERSION_HEX ((1 << 24) | (0 << 16) | (0 << 8) | 0)
10410 #define MONGOC_CHECK_VERSION(major, minor, micro)
10411
10412 Only compile a block on MongoDB C Driver 1.1.0 and newer.
10413
10414 #if MONGOC_CHECK_VERSION(1, 1, 0)
10415 static void
10416 do_something (void)
10417 {
10418 }
10419 #endif
10420
10421 mongoc_write_concern_t
10422 Write Concern abstraction
10423
10424 Synopsis
10425 mongoc_write_concern_t tells the driver what level of acknowledgement
10426 to await from the server. The default, MONGOC_WRITE_CONCERN_W_DEFAULT,
10427 is right for the great majority of applications.
10428
10429 You can specify a write concern on connection objects, database ob‐
10430 jects, collection objects, or per-operation. Data-modifying operations
10431 typically use the write concern of the object they operate on, and
10432 check the server response for a write concern error or write concern
10433 timeout. For example, mongoc_collection_drop_index uses the collec‐
10434 tion's write concern, and a write concern error or timeout in the re‐
10435 sponse is considered a failure.
10436
10437 Exceptions to this principle are the generic command functions:
10438
10439 • mongoc_client_command
10440
10441 • mongoc_client_command_simple
10442
10443 • mongoc_database_command
10444
10445 • mongoc_database_command_simple
10446
10447 • mongoc_collection_command
10448
10449 • mongoc_collection_command_simple
10450
10451 These generic command functions do not automatically apply a write con‐
10452 cern, and they do not check the server response for a write concern er‐
10453 ror or write concern timeout.
10454
10455 See Write Concern on the MongoDB website for more information.
10456
10457 Write Concern Levels
10458 Set the write concern level with mongoc_write_concern_set_w.
10459
10460 ┌───────────────────────────┬────────────────────────────┐
10461 │MONGOC_WRITE_CONCERN_W_DE‐ │ By default, writes block │
10462 │FAULT (1) │ awaiting acknowledgement │
10463 │ │ from MongoDB. Acknowledged │
10464 │ │ write concern allows │
10465 │ │ clients to catch network, │
10466 │ │ duplicate key, and other │
10467 │ │ errors. │
10468 ├───────────────────────────┼────────────────────────────┤
10469 │MONGOC_WRITE_CONCERN_W_UN‐ │ With this write concern, │
10470 │ACKNOWLEDGED (0) │ MongoDB does not acknowl‐ │
10471 │ │ edge the receipt of write │
10472 │ │ operation. Unacknowledged │
10473 │ │ is similar to errors ig‐ │
10474 │ │ nored; however, mongoc at‐ │
10475 │ │ tempts to receive and han‐ │
10476 │ │ dle network errors when │
10477 │ │ possible. │
10478 ├───────────────────────────┼────────────────────────────┤
10479 │MONGOC_WRITE_CONCERN_W_MA‐ │ Block until a write has │
10480 │JORITY (majority) │ been propagated to a ma‐ │
10481 │ │ jority of the nodes in the │
10482 │ │ replica set. │
10483 ├───────────────────────────┼────────────────────────────┤
10484 │n │ Block until a write has │
10485 │ │ been propagated to at │
10486 │ │ least n nodes in the │
10487 │ │ replica set. │
10488 └───────────────────────────┴────────────────────────────┘
10489
10490 Deprecations
10491 The write concern MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED (value -1) is a
10492 deprecated synonym for MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (value 0),
10493 and will be removed in the next major release.
10494
10495 mongoc_write_concern_set_fsync is deprecated.
10496
10497 Application Performance Monitoring (APM)
10498 The MongoDB C Driver allows you to monitor all the MongoDB operations
10499 the driver executes. This event-notification system conforms to two
10500 MongoDB driver specs:
10501
10502 • Command Monitoring: events related to all application operations.
10503
10504 • SDAM Monitoring: events related to the driver's Server Discovery And
10505 Monitoring logic.
10506
10507 To receive notifications, create a mongoc_apm_callbacks_t with mon‐
10508 goc_apm_callbacks_new, set callbacks on it, then pass it to mon‐
10509 goc_client_set_apm_callbacks or mongoc_client_pool_set_apm_callbacks.
10510
10511 Command-Monitoring Example
10512 example-command-monitoring.c
10513
10514 /* gcc example-command-monitoring.c -o example-command-monitoring \
10515 * $(pkg-config --cflags --libs libmongoc-1.0) */
10516
10517 /* ./example-command-monitoring [CONNECTION_STRING] */
10518
10519 #include <mongoc/mongoc.h>
10520 #include <stdio.h>
10521
10522
10523 typedef struct {
10524 int started;
10525 int succeeded;
10526 int failed;
10527 } stats_t;
10528
10529
10530 void
10531 command_started (const mongoc_apm_command_started_t *event)
10532 {
10533 char *s;
10534
10535 s = bson_as_relaxed_extended_json (
10536 mongoc_apm_command_started_get_command (event), NULL);
10537 printf ("Command %s started on %s:\n%s\n\n",
10538 mongoc_apm_command_started_get_command_name (event),
10539 mongoc_apm_command_started_get_host (event)->host,
10540 s);
10541
10542 ((stats_t *) mongoc_apm_command_started_get_context (event))->started++;
10543
10544 bson_free (s);
10545 }
10546
10547
10548 void
10549 command_succeeded (const mongoc_apm_command_succeeded_t *event)
10550 {
10551 char *s;
10552
10553 s = bson_as_relaxed_extended_json (
10554 mongoc_apm_command_succeeded_get_reply (event), NULL);
10555 printf ("Command %s succeeded:\n%s\n\n",
10556 mongoc_apm_command_succeeded_get_command_name (event),
10557 s);
10558
10559 ((stats_t *) mongoc_apm_command_succeeded_get_context (event))->succeeded++;
10560
10561 bson_free (s);
10562 }
10563
10564
10565 void
10566 command_failed (const mongoc_apm_command_failed_t *event)
10567 {
10568 bson_error_t error;
10569
10570 mongoc_apm_command_failed_get_error (event, &error);
10571 printf ("Command %s failed:\n\"%s\"\n\n",
10572 mongoc_apm_command_failed_get_command_name (event),
10573 error.message);
10574
10575 ((stats_t *) mongoc_apm_command_failed_get_context (event))->failed++;
10576 }
10577
10578
10579 int
10580 main (int argc, char *argv[])
10581 {
10582 mongoc_client_t *client;
10583 mongoc_apm_callbacks_t *callbacks;
10584 stats_t stats = {0};
10585 mongoc_collection_t *collection;
10586 bson_error_t error;
10587 const char *uri_string =
10588 "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
10589 mongoc_uri_t *uri;
10590 const char *collection_name = "test";
10591 bson_t *docs[2];
10592
10593 mongoc_init ();
10594
10595 if (argc > 1) {
10596 uri_string = argv[1];
10597 }
10598
10599 uri = mongoc_uri_new_with_error (uri_string, &error);
10600 if (!uri) {
10601 fprintf (stderr,
10602 "failed to parse URI: %s\n"
10603 "error message: %s\n",
10604 uri_string,
10605 error.message);
10606 return EXIT_FAILURE;
10607 }
10608
10609 client = mongoc_client_new_from_uri (uri);
10610 if (!client) {
10611 return EXIT_FAILURE;
10612 }
10613
10614 mongoc_client_set_error_api (client, 2);
10615 callbacks = mongoc_apm_callbacks_new ();
10616 mongoc_apm_set_command_started_cb (callbacks, command_started);
10617 mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
10618 mongoc_apm_set_command_failed_cb (callbacks, command_failed);
10619 mongoc_client_set_apm_callbacks (
10620 client, callbacks, (void *) &stats /* context pointer */);
10621
10622 collection = mongoc_client_get_collection (client, "test", collection_name);
10623 mongoc_collection_drop (collection, NULL);
10624
10625 docs[0] = BCON_NEW ("_id", BCON_INT32 (0));
10626 docs[1] = BCON_NEW ("_id", BCON_INT32 (1));
10627 mongoc_collection_insert_many (
10628 collection, (const bson_t **) docs, 2, NULL, NULL, NULL);
10629
10630 /* duplicate key error on the second insert */
10631 mongoc_collection_insert_one (collection, docs[0], NULL, NULL, NULL);
10632
10633 mongoc_collection_destroy (collection);
10634 mongoc_apm_callbacks_destroy (callbacks);
10635 mongoc_uri_destroy (uri);
10636 mongoc_client_destroy (client);
10637
10638 printf ("started: %d\nsucceeded: %d\nfailed: %d\n",
10639 stats.started,
10640 stats.succeeded,
10641 stats.failed);
10642
10643 bson_destroy (docs[0]);
10644 bson_destroy (docs[1]);
10645
10646 mongoc_cleanup ();
10647
10648 return EXIT_SUCCESS;
10649 }
10650
10651
10652 This example program prints:
10653
10654 Command drop started on 127.0.0.1:
10655 { "drop" : "test" }
10656
10657 Command drop succeeded:
10658 { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }
10659
10660 Command insert started on 127.0.0.1:
10661 {
10662 "insert" : "test",
10663 "ordered" : true,
10664 "documents" : [
10665 { "_id" : 0 }, { "_id" : 1 }
10666 ]
10667 }
10668
10669 Command insert succeeded:
10670 { "n" : 2, "ok" : 1.0 }
10671
10672 Command insert started on 127.0.0.1:
10673 {
10674 "insert" : "test",
10675 "ordered" : true,
10676 "documents" : [
10677 { "_id" : 0 }
10678 ]
10679 }
10680
10681 Command insert succeeded:
10682 {
10683 "n" : 0,
10684 "writeErrors" : [
10685 { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
10686 ],
10687 "ok" : 1.0
10688 }
10689
10690 started: 3
10691 succeeded: 3
10692 failed: 0
10693
10694 The output has been edited and formatted for clarity. Depending on your
10695 server configuration, messages may include metadata like database name,
10696 logical session ids, or cluster times that are not shown here.
10697
10698 The final "insert" command is considered successful, despite the
10699 writeError, because the server replied to the overall command with
10700 "ok": 1.
10701
10702 SDAM Monitoring Example
10703 example-sdam-monitoring.c
10704
10705 /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
10706 * $(pkg-config --cflags --libs libmongoc-1.0) */
10707
10708 /* ./example-sdam-monitoring [CONNECTION_STRING] */
10709
10710 #include <mongoc/mongoc.h>
10711 #include <stdio.h>
10712
10713
10714 typedef struct {
10715 int server_changed_events;
10716 int server_opening_events;
10717 int server_closed_events;
10718 int topology_changed_events;
10719 int topology_opening_events;
10720 int topology_closed_events;
10721 int heartbeat_started_events;
10722 int heartbeat_succeeded_events;
10723 int heartbeat_failed_events;
10724 } stats_t;
10725
10726
10727 static void
10728 server_changed (const mongoc_apm_server_changed_t *event)
10729 {
10730 stats_t *context;
10731 const mongoc_server_description_t *prev_sd, *new_sd;
10732
10733 context = (stats_t *) mongoc_apm_server_changed_get_context (event);
10734 context->server_changed_events++;
10735
10736 prev_sd = mongoc_apm_server_changed_get_previous_description (event);
10737 new_sd = mongoc_apm_server_changed_get_new_description (event);
10738
10739 printf ("server changed: %s %s -> %s\n",
10740 mongoc_apm_server_changed_get_host (event)->host_and_port,
10741 mongoc_server_description_type (prev_sd),
10742 mongoc_server_description_type (new_sd));
10743 }
10744
10745
10746 static void
10747 server_opening (const mongoc_apm_server_opening_t *event)
10748 {
10749 stats_t *context;
10750
10751 context = (stats_t *) mongoc_apm_server_opening_get_context (event);
10752 context->server_opening_events++;
10753
10754 printf ("server opening: %s\n",
10755 mongoc_apm_server_opening_get_host (event)->host_and_port);
10756 }
10757
10758
10759 static void
10760 server_closed (const mongoc_apm_server_closed_t *event)
10761 {
10762 stats_t *context;
10763
10764 context = (stats_t *) mongoc_apm_server_closed_get_context (event);
10765 context->server_closed_events++;
10766
10767 printf ("server closed: %s\n",
10768 mongoc_apm_server_closed_get_host (event)->host_and_port);
10769 }
10770
10771
10772 static void
10773 topology_changed (const mongoc_apm_topology_changed_t *event)
10774 {
10775 stats_t *context;
10776 const mongoc_topology_description_t *prev_td;
10777 const mongoc_topology_description_t *new_td;
10778 mongoc_server_description_t **prev_sds;
10779 size_t n_prev_sds;
10780 mongoc_server_description_t **new_sds;
10781 size_t n_new_sds;
10782 size_t i;
10783 mongoc_read_prefs_t *prefs;
10784
10785 context = (stats_t *) mongoc_apm_topology_changed_get_context (event);
10786 context->topology_changed_events++;
10787
10788 prev_td = mongoc_apm_topology_changed_get_previous_description (event);
10789 prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds);
10790 new_td = mongoc_apm_topology_changed_get_new_description (event);
10791 new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds);
10792
10793 printf ("topology changed: %s -> %s\n",
10794 mongoc_topology_description_type (prev_td),
10795 mongoc_topology_description_type (new_td));
10796
10797 if (n_prev_sds) {
10798 printf (" previous servers:\n");
10799 for (i = 0; i < n_prev_sds; i++) {
10800 printf (" %s %s\n",
10801 mongoc_server_description_type (prev_sds[i]),
10802 mongoc_server_description_host (prev_sds[i])->host_and_port);
10803 }
10804 }
10805
10806 if (n_new_sds) {
10807 printf (" new servers:\n");
10808 for (i = 0; i < n_new_sds; i++) {
10809 printf (" %s %s\n",
10810 mongoc_server_description_type (new_sds[i]),
10811 mongoc_server_description_host (new_sds[i])->host_and_port);
10812 }
10813 }
10814
10815 prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
10816
10817 /* it is safe, and unfortunately necessary, to cast away const here */
10818 if (mongoc_topology_description_has_readable_server (
10819 (mongoc_topology_description_t *) new_td, prefs)) {
10820 printf (" secondary AVAILABLE\n");
10821 } else {
10822 printf (" secondary UNAVAILABLE\n");
10823 }
10824
10825 if (mongoc_topology_description_has_writable_server (
10826 (mongoc_topology_description_t *) new_td)) {
10827 printf (" primary AVAILABLE\n");
10828 } else {
10829 printf (" primary UNAVAILABLE\n");
10830 }
10831
10832 mongoc_read_prefs_destroy (prefs);
10833 mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds);
10834 mongoc_server_descriptions_destroy_all (new_sds, n_new_sds);
10835 }
10836
10837
10838 static void
10839 topology_opening (const mongoc_apm_topology_opening_t *event)
10840 {
10841 stats_t *context;
10842
10843 context = (stats_t *) mongoc_apm_topology_opening_get_context (event);
10844 context->topology_opening_events++;
10845
10846 printf ("topology opening\n");
10847 }
10848
10849
10850 static void
10851 topology_closed (const mongoc_apm_topology_closed_t *event)
10852 {
10853 stats_t *context;
10854
10855 context = (stats_t *) mongoc_apm_topology_closed_get_context (event);
10856 context->topology_closed_events++;
10857
10858 printf ("topology closed\n");
10859 }
10860
10861
10862 static void
10863 server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event)
10864 {
10865 stats_t *context;
10866
10867 context =
10868 (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event);
10869 context->heartbeat_started_events++;
10870
10871 printf ("%s heartbeat started\n",
10872 mongoc_apm_server_heartbeat_started_get_host (event)->host_and_port);
10873 }
10874
10875
10876 static void
10877 server_heartbeat_succeeded (
10878 const mongoc_apm_server_heartbeat_succeeded_t *event)
10879 {
10880 stats_t *context;
10881 char *reply;
10882
10883 context =
10884 (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event);
10885 context->heartbeat_succeeded_events++;
10886
10887 reply = bson_as_canonical_extended_json (
10888 mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL);
10889
10890 printf (
10891 "%s heartbeat succeeded: %s\n",
10892 mongoc_apm_server_heartbeat_succeeded_get_host (event)->host_and_port,
10893 reply);
10894
10895 bson_free (reply);
10896 }
10897
10898
10899 static void
10900 server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event)
10901 {
10902 stats_t *context;
10903 bson_error_t error;
10904
10905 context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event);
10906 context->heartbeat_failed_events++;
10907 mongoc_apm_server_heartbeat_failed_get_error (event, &error);
10908
10909 printf ("%s heartbeat failed: %s\n",
10910 mongoc_apm_server_heartbeat_failed_get_host (event)->host_and_port,
10911 error.message);
10912 }
10913
10914
10915 int
10916 main (int argc, char *argv[])
10917 {
10918 mongoc_client_t *client;
10919 mongoc_apm_callbacks_t *cbs;
10920 stats_t stats = {0};
10921 const char *uri_string =
10922 "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
10923 mongoc_uri_t *uri;
10924 bson_t cmd = BSON_INITIALIZER;
10925 bson_t reply;
10926 bson_error_t error;
10927
10928 mongoc_init ();
10929
10930 if (argc > 1) {
10931 uri_string = argv[1];
10932 }
10933
10934 uri = mongoc_uri_new_with_error (uri_string, &error);
10935 if (!uri) {
10936 fprintf (stderr,
10937 "failed to parse URI: %s\n"
10938 "error message: %s\n",
10939 uri_string,
10940 error.message);
10941 return EXIT_FAILURE;
10942 }
10943
10944 client = mongoc_client_new_from_uri (uri);
10945 if (!client) {
10946 return EXIT_FAILURE;
10947 }
10948
10949 mongoc_client_set_error_api (client, 2);
10950 cbs = mongoc_apm_callbacks_new ();
10951 mongoc_apm_set_server_changed_cb (cbs, server_changed);
10952 mongoc_apm_set_server_opening_cb (cbs, server_opening);
10953 mongoc_apm_set_server_closed_cb (cbs, server_closed);
10954 mongoc_apm_set_topology_changed_cb (cbs, topology_changed);
10955 mongoc_apm_set_topology_opening_cb (cbs, topology_opening);
10956 mongoc_apm_set_topology_closed_cb (cbs, topology_closed);
10957 mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started);
10958 mongoc_apm_set_server_heartbeat_succeeded_cb (cbs,
10959 server_heartbeat_succeeded);
10960 mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed);
10961 mongoc_client_set_apm_callbacks (
10962 client, cbs, (void *) &stats /* context pointer */);
10963
10964 /* the driver connects on demand to perform first operation */
10965 BSON_APPEND_INT32 (&cmd, "buildinfo", 1);
10966 mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error);
10967 mongoc_uri_destroy (uri);
10968 mongoc_client_destroy (client);
10969
10970 printf ("Events:\n"
10971 " server changed: %d\n"
10972 " server opening: %d\n"
10973 " server closed: %d\n"
10974 " topology changed: %d\n"
10975 " topology opening: %d\n"
10976 " topology closed: %d\n"
10977 " heartbeat started: %d\n"
10978 " heartbeat succeeded: %d\n"
10979 " heartbeat failed: %d\n",
10980 stats.server_changed_events,
10981 stats.server_opening_events,
10982 stats.server_closed_events,
10983 stats.topology_changed_events,
10984 stats.topology_opening_events,
10985 stats.topology_closed_events,
10986 stats.heartbeat_started_events,
10987 stats.heartbeat_succeeded_events,
10988 stats.heartbeat_failed_events);
10989
10990 bson_destroy (&cmd);
10991 bson_destroy (&reply);
10992 mongoc_apm_callbacks_destroy (cbs);
10993
10994 mongoc_cleanup ();
10995
10996 return EXIT_SUCCESS;
10997 }
10998
10999
11000 Start a 3-node replica set on localhost with set name "rs" and start
11001 the program:
11002
11003 ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"
11004
11005 This example program prints something like:
11006
11007 topology opening
11008 topology changed: Unknown -> ReplicaSetNoPrimary
11009 secondary UNAVAILABLE
11010 primary UNAVAILABLE
11011 server opening: localhost:27017
11012 server opening: localhost:27018
11013 localhost:27017 heartbeat started
11014 localhost:27018 heartbeat started
11015 localhost:27017 heartbeat succeeded: { ... reply ... }
11016 server changed: localhost:27017 Unknown -> RSPrimary
11017 server opening: localhost:27019
11018 topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
11019 new servers:
11020 RSPrimary localhost:27017
11021 secondary UNAVAILABLE
11022 primary AVAILABLE
11023 localhost:27019 heartbeat started
11024 localhost:27018 heartbeat succeeded: { ... reply ... }
11025 server changed: localhost:27018 Unknown -> RSSecondary
11026 topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
11027 previous servers:
11028 RSPrimary localhost:27017
11029 new servers:
11030 RSPrimary localhost:27017
11031 RSSecondary localhost:27018
11032 secondary AVAILABLE
11033 primary AVAILABLE
11034 localhost:27019 heartbeat succeeded: { ... reply ... }
11035 server changed: localhost:27019 Unknown -> RSSecondary
11036 topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
11037 previous servers:
11038 RSPrimary localhost:27017
11039 RSSecondary localhost:27018
11040 new servers:
11041 RSPrimary localhost:27017
11042 RSSecondary localhost:27018
11043 RSSecondary localhost:27019
11044 secondary AVAILABLE
11045 primary AVAILABLE
11046 topology closed
11047
11048 Events:
11049 server changed: 3
11050 server opening: 3
11051 server closed: 0
11052 topology changed: 4
11053 topology opening: 1
11054 topology closed: 1
11055 heartbeat started: 3
11056 heartbeat succeeded: 3
11057 heartbeat failed: 0
11058
11059 The driver connects to the mongods on ports 27017 and 27018, which were
11060 specified in the URI, and determines which is primary. It also discov‐
11061 ers the third member, "localhost:27019", and adds it to the topology.
11062
11064 MongoDB, Inc
11065
11067 2017-present, MongoDB, Inc
11068
11069
11070
11071
110721.17.6 Jun 03, 2021 MONGOC_REFERENCE(3)