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