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