1MONGOC_REFERENCE(3) libmongoc MONGOC_REFERENCE(3)
2
3
4
6 A Cross Platform MongoDB Client Library for C
7
8 Introduction
9 The MongoDB C Driver, also known as "libmongoc", is a library for using
10 MongoDB from C applications, and for writing MongoDB drivers in
11 higher-level languages.
12
13 It depends on libbson to generate and parse BSON documents, the native
14 data format of MongoDB.
15
16 Tutorials
17 This section contains tutorials on how to get started with the basics
18 of using the C driver.
19
20 Obtaining the MongoDB C Driver Libraries
21 There are a few methods of obtaining the mongo-c-driver codebase:
22
23 Building the C Driver Libraries from Source
24 This page details how to download, unpack, configure, and build libbson
25 and libmongoc from their original source-code form.
26
27 Extra information
28
29 Dropdowns (like this one) contain extra information and explanatory de‐
30 tails that are not required to complete the tutorial, but may be help‐
31 ful for curious readers, and more advanced users that want an explana‐
32 tion of the meaning of certain tutorial steps.
33
34 The following page uses a few named "variables" that you must decide
35 up-front. When you see such a value referrenced in a tutorial step,
36 you should substitute the value into that step.
37
38 SEE ALSO:
39 Before building, you may want to check that you are running on a
40 supported platform. For the list of supported platforms, refer to
41 the mongo-c-driver Platform Support page.
42
43 Choose a Version
44 Before we begin, know what version of mongo-c-driver you will be down‐
45 loading. A list of available versions can be found on the GitHub
46 repository tags page. (The current version written for this documenta‐
47 tion is 1.25.1.)
48
49 For the remainder of this page, $VERSION will refer to the version num‐
50 ber of mongo-c-driver that you will be building for this tutorial.
51
52 Obtaining the Source
53 There are two primary recommended methods of obtaining the
54 mongo-c-driver source code:
55
56 1. Clone the repository using git (recommended). (See below)
57
58 2. Download a source archive at a specific version. (See below)
59
60 IMPORTANT:
61 It is highly recommended that new users use a stable released ver‐
62 sion of the driver, rather than building from a development branch.
63 When you git clone or download an archive of the repository, be sure
64 to specify a release tag (e.g. with Git's --branch argument).
65
66 Downloading Using Git
67 Using Git, the C driver repository can be cloned from the GitHub URL
68 https://github.com/mongodb/mongo-c-driver.git. Git tags for released
69 versions are named after the version for which they correspond (e.g.
70 "1.25.1"). To clone the repository using the command line, the follow‐
71 ing command may be used:
72
73 $ git clone https://github.com/mongodb/mongo-c-driver.git --branch="$VERSION" "$SOURCE"
74
75 TIP:
76 Despite the name, git-clone's --branch argument may also be used to
77 clone from repository tags.
78
79 Downloading a Release Archive
80 An archived snapshot of the repository can be obtained from the GitHub
81 Releases Page. The mongo-c-driver-x.y.z.tar.gz archive attached to any
82 release contains the minimal set of files that you'll need for the
83 build.
84
85 Using wget + tar
86
87 ## Download using wget:
88 $ wget "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/$VERSION.tar.gz" \
89 --output-document="mongo-c-driver-$VERSION.tar.gz"
90 ## Extract using tar:
91 $ tar xf "mongo-c-driver-$VERSION.tar.gz"
92
93 Using curl + tar
94
95 ## Using curl:
96 $ curl "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/$VERSION.tar.gz" \
97 --output="mongo-c-driver-$VERSION.tar.gz"
98 ## Extract using tar:
99 $ tar xf "mongo-c-driver-$VERSION.tar.gz"
100
101 PowerShell
102
103 ## Use Invoke-WebRequest:
104 PS> $url = "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/$VERSION.zip"
105 PS> $file = "mongo-c-driver-$VERSION.zip"
106 PS> Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $file
107 ## Extract using Expand-Archive:
108 PS> Expand-Archive mongo-c-driver-$VERSION.zip
109
110 The above commands will create a new directory mongo-c-driver-$VERSION
111 within the directory in which you ran the tar/Expand-Archive command
112 (note: PowerShell will create an additional intermediate subdirectory
113 of the same name). This directory is the root of the driver source tree
114 (which we refer to as $SOURCE in these documents). The $SOURCE direc‐
115 tory should contain the top-level CMakeLists.txt file.
116
117 Obtaining Prerequisites
118 In order to build the project, a few prerequisites need to be avail‐
119 able.
120
121 Both libmongoc and libbson projects use CMake for build configuration.
122
123 NOTE:
124 It is highly recommended -- but not required -- that you download
125 the latest stable CMake available for your platform.
126
127 Getting the Latest CMake
128
129 A new stable release of CMake can be obtained from the CMake downloads
130 page.
131
132 For Windows and macOS, simply download the CMake .msi/.dmg (not the
133 .zip/.tar.gz) and use it to install CMake.
134
135 On Linux, download the self-extracting shell script (ending with .sh)
136 and execute it using the sh utility, passing the appropriate arguments
137 to perform the install. For example, with the CMake 3.27.0 on the
138 x86_64 platform, the following command can be used on the
139 cmake-3.27.0-linux-x86_64.sh script:
140
141 $ sh cmake-3.27.0-linux-x86_64.sh --prefix="$HOME/.local" --exclude-subdir --skip-license
142
143 Assuming that $HOME/.local/bin is on your $PATH list, the cmake command
144 for 3.27.0 will then become available.
145
146 The --help option can be passed to the shell script for more informa‐
147 tion.
148
149 For the remainder of this page, it will be assumed that cmake is avail‐
150 able as a command on your PATH environment variable and can be executed
151 as "cmake" from a shell. You can test this by requesting the --version
152 from CMake from the command line:
153
154 $ cmake --version
155 cmake version 3.21.4
156
157 CMake suite maintained and supported by Kitware (kitware.com/cmake).
158
159 NOTE:
160 If you intend to build libbson only, then CMake is sufficient for
161 the build. Additional C driver features may require additional ex‐
162 ternal dependencies be installed, but we will not worry about them
163 here.
164
165 Configuring for libbson
166 IMPORTANT:
167 If you are building with Xcode [1] or Visual Studio [2], you may
168 need to execute CMake from within a special environment in which the
169 respective toolchain is available.
170
171 Let the name $BUILD be the path $SOURCE/_build. This will be the direc‐
172 tory where our built files will be written by CMake.
173
174 With the source directory for mongo-c-driver at $SOURCE and build di‐
175 rectory $BUILD, the following command can be executed from a com‐
176 mand-line to configure the project with both libbson and libmongoc:
177
178 $ cmake -S $SOURCE -B $BUILD \
179 -D ENABLE_EXTRA_ALIGNMENT=OFF \
180 -D ENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF \
181 -D CMAKE_BUILD_TYPE=RelWithDebInfo \
182 -D BUILD_VERSION="$VERSION" \
183 -D ENABLE_MONGOC=OFF
184
185 If all dependencies are satisfied, the above command should succeed and
186 end with:
187
188 $ cmake …
189 ## … (Lines of output) …
190 -- Generating done
191 -- Build files have been written to: $BUILD
192
193 If configuration failed with an error, refer to the CMake output for
194 error messages and information. Ensure that configuration succeeds be‐
195 fore proceeding.
196
197 What do these CMake arguments mean?
198
199 The BUILD_VERSION sets the version number that will be included in the
200 build results. This should be set to the same value as the version of
201 the source driver that was downloaded in Obtaining the Source.
202
203 The ENABLE_EXTRA_ALIGNMENT and ENABLE_AUTOMATIC_INIT_AND_CLEANUP are
204 part of mongo-c-driver, and correspond to deprecated features that are
205 only enabled by default for ABI compatibility purposes. It is highly
206 recommended to disable these features whenever possible.
207
208 The ENABLE_MONGOC=OFF argument disabled building libmongoc. We'll build
209 that in the next section.
210
211 The CMAKE_BUILD_TYPE setting tells CMake what variant of code will be
212 generated. In the case of RelWithDebInfo, optimized binaries will be
213 produced, but still include debug information. The CMAKE_BUILD_TYPE has
214 no effect on Multi-Config generators (i.e. Visual Studio), which in‐
215 stead rely on the --config option when building/installing.
216
217 Building the Project
218 After successfully configuring the project, the build can be executed
219 by using CMake:
220
221 $ cmake --build $BUILD --config RelWithDebInfo --parallel
222
223 If configured properly and all dependencies are satisfied, then the
224 above command should proceed to compile and link the configured compo‐
225 nents. If the above command fails, then there is likely an error with
226 your environment, or you are using an unsupported/untested platform.
227 Refer to the build tool output for more information.
228
229 The --config option
230
231 The --config option is used to set the build configuration to use in
232 the case of Multi-Config generators (i.e. Visual Studio). It has no ef‐
233 fect on other generators, which instead use CMAKE_BUILD_TYPE.
234
235 Installing the Built Results
236 Let $PREFIX be the path $SOURCE/_install. We can use CMake to install
237 the built results:
238
239 $ cmake --install "$BUILD" --prefix "$PREFIX" --config RelWithDebInfo
240
241 This command will install the mongo-c-driver build results into the
242 $PREFIX directory.
243
244 The --config option
245
246 The --config option is only used for Multi-Config generators (i.e. Vis‐
247 ual Studio) and is otherwise ignored. The value given for --config must
248 be the same as was given for --config with cmake --build.
249
250 SEE ALSO:
251 The above snippet simply installs mongo-c-driver in a subdirectory
252 of the source directory itself, but this is not a normal workflow.
253 Once you feel compfortable about configuring and building
254 mongo-c-driver, the page How to: Install libbson/libmongoc from
255 Source will do a deeper dive on from-source installation options.
256
257 Configuring with libmongoc
258 If you followed the above steps starting from Configuring for libbson,
259 your final result with only contain libbson and not the full C database
260 driver library. Building of libmongoc is enabled/disabled using the EN‐
261 ABLE_MONGOC CMake variable. Re-run CMake again, but set ENABLE_MONGOC
262 to TRUE:
263
264 $ cmake -D ENABLE_MONGOC=ON $BUILD
265
266 If the above command succeeds, then the project has been reconfigured
267 to build with libmongoc. Follow the process at Building the Project and
268 Installing the Built Results again to build and install libmongoc.
269
271 [1] If you wish to configure and build the project with Xcode, the
272 Xcode command-line tools need to be installed and made available
273 in the environment. From within a command-line environment, run:
274
275 $ xcode-select --install
276
277 This will ensure that the compilers and linkers are available on your
278 $PATH.
279
280 [2] If you wish to configure and build the project using Microsoft
281 Visual C++, then the Visual C++ tools and environment variables
282 may need to be set when running any CMake or build command.
283
284 In many cases, CMake will detect a Visual Studio installation and
285 automatically load the environment itself when it is executed.
286 This automatic detection can be controlled with CMake's -G, -T,
287 and -A options. The -G option is the most significant, as it se‐
288 lects which Visual Studio version will be used. The versions of
289 Visual Studio supported depends on the version of CMake that you
290 have installed. A list of supported Visual Studio versions can be
291 found here
292
293 For greater control and more tooling options, it is recommended to
294 run commands from within a Visual Studio Developer PowerShell
295 (preferred) or Developer Command Prompt (legacy).
296
297 For more information, refer to: Visual Studio Developer Command
298 Prompt and Developer PowerShell and Use the Microsoft C++ toolset
299 from the command line on the Microsoft Visual Studio documentation
300 pages.
301
302 Installing Prebuilt MongoDB C Driver Libraries
303 The libmongoc and libbson libraries are often available in the package
304 management repositories of common Linux distributions and macOS via
305 Homebrew.
306
307 NOTE:
308 For Windows, it is recommended to instead build the libraries from
309 source, for maximum compatibility with the local toolchain. Building
310 from source can be automated by using a from-source library package
311 management tool such as Conan or vcpkg (See: Cross Platform Installs
312 Using Library Package Managers).
313
314 CAUTION:
315 If you install and use prebuilt binaries from a third-party pack‐
316 ager, it is possible that it lags behind the version of the li‐
317 braries described in these documentation pages (1.25.1). Note the
318 version that you install and keep it in mind when reading these
319 pages.
320
321 For the most up-to-date versions of the C driver libraries, prefer
322 to instead build from source.
323
324 SEE ALSO:
325 For a listing and common reference on available packages, refer to
326 Package Installation Reference.
327
328 Cross Platform Installs Using Library Package Managers
329 Various library package managers offer libbson and libmongoc as instal‐
330 lable packages, including Conan and vcpkg. This section will detail how
331 to install using those tools.
332
333 Installing using vcpkg
334 NOTE:
335 This page will not detail how to get started using vcpkg. For that,
336 refer to Get started with vcpkg
337
338 vcpkg Manifest Mode (Recommended) In vcpkg manifest mode, add the de‐
339 sired libraries to your project's vcpkg.json manifest file:
340
341 vcpkg.json
342
343 {
344 // ...
345 "dependencies": [
346 // ...
347 "mongo-c-driver"
348 ]
349 }
350
351 When you build a CMake project with vcpkg integration and have a
352 vcpkg.json manifest file, vcpkg will automatically install the
353 project's dependencies before proceeding with the configuration phase,
354 so no additional manual work is required.
355
356 vcpkg Classic Mode In vcpkg classic mode, libbson and libmongoc can be
357 installed through the names libbson and mongo-c-driver, respectively:
358
359 $ vcpkg install mongo-c-driver
360
361 (Installing mongo-c-driver will transitively install libbson as well.)
362
363 When the libmongoc and libbson packages are installed and vcpkg has
364 been properly integrated into your build system, the desired libraries
365 will be available for import.
366
367 With CMake, the standard config-file package will be available, as well
368 as the generated IMPORTED targets:
369
370 CMakeLists.txt
371
372 find_package(mongoc-1.0 CONFIG REQUIRED)
373 target_link_libraries(my-application
374 PRIVATE $<IF:$<TARGET_EXISTS:mongo::mongoc_shared>,mongo::mongoc_shared,mongo::mongoc_static>)
375
376 NOTE:
377 The large $<IF:$<TARGET_EXISTS...>:...> generator expression (‐
378 cmake-generator-expressions(7)) can be used to switch the link type
379 of libmongoc based on whichever form is available from the
380 find_package() command. libmongoc supports building with both dy‐
381 namic and static library types, but vcpkg will only install one of
382 the two library types at a time.
383
384 Configuring a CMake project with vcpkg integration is a matter of set‐
385 ting the CMake toolchain file at the initial configure command:
386
387 $ cmake -S . -B _build -D CMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
388
389 Installing in Linux
390 The names and process of installing libbson and libmongoc varies be‐
391 tween distributions, but generally follows a similar pattern.
392
393 The following Linux distributions provide libbson and libmongoc pack‐
394 ages:
395
396 • Fedora via dnf
397
398 • RedHat Enterprise Linux (RHEL) 7 and Newer and distribusions based on
399 RHEL 7 or newer, including CentOS, Rocky Linux, and AlmaLinux, via
400 yum/dnf and EPEL.
401
402 • Debian and Debian-based distributions, including Ubuntu and Ubuntu
403 derivatives, via APT.
404
405 SEE ALSO:
406 For a list of available packages and package options, see: Package
407 Installation Reference.
408
409 RedHat-based Systems
410 In RedHat-based Linux distributions, including Fedora, CentOS, Rocky
411 Linux, and AlmaLinux, the C driver libraries can be installed with
412 Yum/DNF.
413
414 NOTE:
415 For Fedora and enterprise Linux of version 8 or greater, it is rec‐
416 ommended to use the dnf command in place of any yum command.
417
418 IMPORTANT:
419 Except for Fedora:
420
421 The C driver libraries are only available in version 7 and newer of
422 the resepective enterprise Linux distributions. However, the C
423 driver libraries are not available in the default repositories, but
424 can be obtained by enabling the EPEL repositories. This can be done
425 by installing the epel-release package:
426
427 # yum install epel-release
428
429 epel-release must be installed before attempting to install the C
430 driver libraries (i.e. one cannot install them both in a single yum
431 intsall command).
432
433 To install libbson only, install the libbson-devel package:
434
435 # yum install libbson-devel
436
437 To install the full C database driver (libmongoc), install
438 mongo-c-driver-devel:
439
440 ## (This package will transitively install libbson-devel)
441 # yum install mongo-c-driver-devel
442
443 Debian-based Systems
444 In Debian-based Linux distributions, including Ubuntu and Ubuntu deriv‐
445 atives, libbson and libmongoc are available in the distribution reposi‐
446 tories via APT, and can be installed as libbson-dev and libmongoc-dev,
447 respectively:
448
449 ## Update repository information, if necessary:
450 # apt update
451
452 To install only libbson:
453
454 # apt install libbson-dev
455
456 To install libmongoc (which will also install libbson):
457
458 # apt install libmongoc-dev
459
460 Installing on macOS with Homebrew
461 If you are using a macOS system, the C driver libraries (including both
462 libmongoc and libbson) may be installed using the Homebrew package man‐
463 ager [1] with the following command:
464
465 $ brew install mongo-c-driver
466
467 NOTE:
468 Homebrew does not provide separate packages for libbson and libmon‐
469 goc.
470
471 [1] The Homebrew package manager is not installed by default on macOS.
472 For information on installing Homebrew, refer to the Homebrew in‐
473 stallation documentation page.
474
475 Building the mongo-c-driver Documentation Pages
476 This documentation is rendered using Sphinx. To easily ensure that all
477 tooling matches expected versions, it is recommended to use Poetry to
478 install and run the required tools.
479
480 TIP:
481 Poetry itself may be installed externally, but can also be automati‐
482 cally managed using the included wrapping scripts for Bash (At
483 tools/poetry.sh) or PowerShell (at tools/poetry.ps1). These scripts
484 can stand in for poetry in any command written below.
485
486 Setting Up the Environment
487 To install the required tooling, use the poetry install command, en‐
488 abling documentation dependencies:
489
490 $ poetry install --with=docs
491
492 This will create a user-local Python virtualenv that contains the nec‐
493 essary tools for building this documentation. The poetry install com‐
494 mand only needs to be run when the pyproject.toml file is changed.
495
496 Running Sphinx
497 Poetry can be used to execute the sphinx-build command:
498
499 $ poetry run sphinx-build -b dirhtml "./src/libmongoc/doc" "./_build/docs/html"
500
501 This command will generate the HTML documentation in the
502 _build/docs/html subdirectory.
503
504 TIP:
505 Because Sphinx builds many pages, the build may run quite slowly.
506 For faster builds, it is recommended to use the --jobs command-line
507 option when invoking sphinx-build.
508
509 Viewing the Documentation
510 To quickly view the rendered HTML pages, a simple local HTTP server can
511 be spawned on the command line by using Python's built-in http.server
512 module:
513
514 $ poetry run python -m http.server --directory=_build/docs/html
515
516 By default, this will serve the documentation at http://127.0.0.1:8000,
517 which you can open in any web browser to see the rendered pages.
518
519 How-To Guides
520 IMPORTANT:
521 The "cookbook" is for problem-solving, and deeper dives into ap‐
522 proach particular tasks. It may assume some prior knowledge, and
523 these are not tutorials themselves! For learning the basics, see the
524 Tutorials section.
525
526 How to: Install libbson/libmongoc from Source
527 IMPORTANT:
528 This page assumes that you can successfully configure and build the
529 components that you wish to install, which is detailed and explained
530 on the Building the C Driver Libraries from Source tutorial page.
531 Whereas that tutorial walks through getting the sources built and a
532 minimal install working, this page will offer deeper guidance on the
533 nuance and available options for installing the mongo-c-driver li‐
534 braries from such a from-source build.
535
536 mongo-c-driver uses CMake to generate its installation rules, and in‐
537 stalls a variety of artifacts of interest. For integration with down‐
538 stream programs, the Config-file Packages and pkg-config files would be
539 of particular interest.
540
541 If you are intending to import libbson or libmongoc via CMake or
542 pkg-config, it can be helpful to be aware of how the respective tool
543 searches for package metadata.
544
545 CMake Package Lookup CMake builds a set of search paths based on a set
546 of prefixes, which are read from both the environment and from config‐
547 ure-time CMake settings.
548
549 In particular, the $PATH environment variable will be used to construct
550 the standard prefixes for the system. For each directory D in $PATH:
551
552 1. If the final path component of D is "bin" or "sbin", D is replaced
553 with the parent path of D.
554
555 2. D is added as a search prefix.
556
557 This has the effect that common Unix-specific directories on $PATH,
558 such as /usr/bin and /usr/local/bin will end up causing CMake to search
559 in /usr and /usr/local is prefixes, respectively. If you have the di‐
560 rectory $HOME/.local/bin on your $PATH, then the $HOME/.local directory
561 will also be added to the search path. Having $HOME/.local/bin on $PATH
562 is an increasingly common pattern for many Unix shells, and is recom‐
563 mended if you intend to do use a per-user-prefix for your installion.
564
565 Additionally, the CMAKE_PREFIX_PATH environment variable will be used
566 to construct a list of paths. By default, this environment variable is
567 not defined.
568
569 On Windows, the directories %ProgramW6432%, %ProgramFiles%, %Program‐
570 Files(x86)%, %SystemDrive%\Program Files, and %SystemDrive%\Program
571 Files (x86) will also be added. (These come from the
572 CMAKE_SYSTEM_PREFIX_PATH CMake variable, which is defined during
573 CMake's platform detection.)
574
575 SEE ALSO:
576 For detailed information on package lookup, refer to CMake's Config
577 Mode Search Procedure section for full details.
578
579 pkg-config Package Lookup The pkg-config command-line tool looks for
580 .pc files in various directories, by default relative to the path of
581 the pkg-config tool itself. To get the list of directories that your
582 pkg-config will search by default, use the following command:
583
584 Ask pkg-config what directories it will search by default
585
586 $ pkg-config "pkg-config" --variable="pc_path"
587
588 Additional directories can be specified using the $PKG_CONFIG_PATH en‐
589 vironment variable. Such paths will be searched before the default
590 pkg-config paths.
591
592 On Windows, registry keys HKCU\Software\pkgconfig\PKG_CONFIG_PATH and
593 HKLM\Software\pkgconfig\PKG_CONFIG_PATH can be used to specify addi‐
594 tional search directories for pkg-config. Adding directories to the
595 HKCU\… key is recommended for persisting user-specific search directo‐
596 ries.
597
598 SEE ALSO:
599 If you have man and pkg-config installed on your system, lookup pro‐
600 cedures are detailed in man 1 pkg-config. This documentation may
601 also be found at many man page archives on the web, such as
602 pkg-config at linux.die.net.
603
604 Choosing a Prefix
605 We will call the directory for the user-local installation $PREFIX. Se‐
606 lecting the path to this directory is somewhat arbitrary, but there are
607 some recommendations to consider. The $PREFIX directory is the path
608 that you will give to CMake or pkg-config when configuring a downstream
609 project.
610
611 Using an Unprivileged User-Local Install Prefix (Recommended)
612 It is recommended that you install custom-built mongo-c-driver li‐
613 braries in an unprivileged filesystem location particular to the user
614 account.
615
616 macOS Unlike other Unix-like systems, macOS does not have a specific
617 directory for user-local package installations, and it is up to the in‐
618 dividual to create such directories themselves.
619
620 The choice of directory to use is essentially arbitrary. For per-user
621 installations, the only requirement is that the directory be writeable
622 by the user that wishes to perform and use the installation.
623
624 For the purposes of uniformity with other Unix variants, this guide
625 will lightly recommend using $HOME/.local as a user-local installation
626 prefix. This is based on the behavior specified by the XDG base direc‐
627 tory specifications and the systemd file-hierarchy common on Linux and
628 various BSDs, but it is not a standard on other platforms.
629
630 Linux & Other Unixes On Linux and BSD systems, it is common to use the
631 $HOME/.local directory as the prefix for user-specific package instal‐
632 lations. This convention originates in the XDG base directory specifi‐
633 cation and the systemd file-hierarchy
634
635 Because of its wide-spread use and support in many other tools, this
636 guide recommends using $HOME/.local as a user-local installation pre‐
637 fix.
638
639 Windows On Windows, there exists a dedicated directory for user-local
640 files in %UserProfile%\AppData\Local. To reference it, expand the %Lo‐
641 calAppData% environment variable. (Do not use the %AppData% environment
642 variable!)
643
644 Despite this directory existing, it has no prescribed structure that
645 suits our purposes. The choice of user-local installation prefix is ar‐
646 bitrary. This guide strongly discourages creating additional files and
647 directories directly within the user's home directory.
648
649 Consider using %LocalAppData%\MongoDB as a prefix for the purposes of
650 manually installed components.
651
652 Selecting a System-Wide Installation Prefix
653 If you wish to install the mongo-c-driver libraries in a directory that
654 is visible to all users, there are a few standard options.
655
656 Linux, macOS, BSD, or Other Unix Using an install $PREFIX of /usr/lo‐
657 cal/ is the primary recommendation for all Unix platforms, but this may
658 vary on some obscure systems.
659
660 WARNING:
661 DO NOT use /usr/ nor / (the root directory) as a prefix: These di‐
662 rectories are designed to be carefully managed by the system. The
663 /usr/local directory is intentionally reserved for the purpose of
664 unmanaged software installation.
665
666 Alternatively, consider installing to a distinct directory that can be
667 easily removed or relocated, such as /opt/mongo-c-driver/. This will be
668 easily identifiable and not interact with other software on the system
669 without explicitly opting-in.
670
671 Windows
672
673 WARNING:
674 It is strongly discouraged to manually install software system-wide
675 on Windows. Prefer instead to use a per-user unprivileged installa‐
676 tion prefix.
677
678 If you wish to perform a system-wide installation on Windows, prefer to
679 use a named subdirectory of %ProgramData%, which does not require ad‐
680 ministrative privileges to read and write. (e.g. %Program‐
681 Data%\mongo-c-driver)
682
683 Installing with CMake
684 After you have successfully configured and built the libraries and have
685 selected a suitable $PREFIX, you can install the built results. Let the
686 name $BUILD refer to the directory where you executed the build (this
687 is the directory that contains CMakeCache.txt, among many other files).
688
689 From a command line, the installation into your chosen $PREFIX can be
690 run via CMake using the cmake --install subcommand:
691
692 $ cmake --install "$BUILD" --prefix "$PREFIX"
693
694 IMPORTANT:
695 If you configured the libraries while using a multi-config generator
696 (e.g Visual Studio, Xcode), then you will also need to pass the
697 --config command-line option, and must pass the value for the build
698 configuration that you wish to install. For any chosen value of
699 --config used for installation, you must also have previously exe‐
700 cuted a cmake --build within that directory with that same --config
701 value.
702
703 NOTE:
704 If you chose to use a system-wide installation $PREFIX, it is possi‐
705 ble that you will need to execute the installation as a privileged
706 user. If you cannot run or do not want to run the installation as a
707 privileged user, you should instead use a per-user installation pre‐
708 fix.
709
710 HINT:
711 It is not necessary to set a CMAKE_INSTALL_PREFIX if you use the
712 --prefix command-line option with cmake --install. The --prefix op‐
713 tion will override whatever was specified by CMAKE_INSTALL_PREFIX
714 when the project was configured.
715
716 Reference
717 Package Installation Reference
718 libbson and libmongoc are available from several package management
719 tools on a variety of systems.
720
721 IMPORTANT:
722 The third-party packages detailed here are not directly controlled
723 via the mongo-c-driver maintainers, and the information found here
724 may be incomplete or out-of-date.
725
726 Package Names and Availability
727 This table details the names and usage notes of such packages.
728
729 SEE ALSO:
730 For a step-by-step tutorial on installing packages, refer to
731 Installing Prebuilt MongoDB C Driver Libraries.
732
733┌──────────────┬───────────────┬────────────────┬──────────────────────┬───────────────┐
734│Packaging │ Platform(s) │ libbson pack‐ │ libmongoc │ Notes │
735│Tool │ │ age(s) │ package(s) │ │
736├──────────────┼───────────────┼────────────────┼──────────────────────┼───────────────┤
737│APT │ Debian-based │ libb‐ │ libmon‐ │ │
738│(apt/apt-get) │ Linux distri‐ │ son-1.0-0, │ goc-1.0-0, │ │
739│ │ butions (De‐ │ libbson-dev, │ libmon‐ │ │
740│ │ bian, Ubuntu, │ libbson-doc │ goc-dev, lib‐ │ │
741│ │ Linux Mint, │ │ mongoc-doc │ │
742│ │ etc.) │ │ │ │
743├──────────────┼───────────────┼────────────────┼──────────────────────┼───────────────┤
744│Yum/DNF │ RHEL-based │ libbson, │ mongo-c-driver-libs, │ Except on Fe‐ │
745│ │ systems │ libbson-devel │ mongo-c-driver-de‐ │ dora the EPEL │
746│ │ (RHEL, Fe‐ │ │ vel │ repositories │
747│ │ dora, CentOS, │ │ │ must be en‐ │
748│ │ Rocky Linux, │ │ │ abled (i.e. │
749│ │ AlmaLinux) │ │ │ install the │
750│ │ │ │ │ epel-release │
751│ │ │ │ │ package │
752│ │ │ │ │ first) │
753└──────────────┴───────────────┴────────────────┴──────────────────────┴───────────────┘
754
755
756│APK │ Alpine Linux │ libbson, │ libmongoc, libmon‐ │ │
757│ │ │ libbson-dev, │ goc-dev, libmon‐ │ │
758│ │ │ libb‐ │ goc-static │ │
759│ │ │ son-static │ │ │
760├──────────────┼───────────────┼────────────────┼──────────────────────┼───────────────┤
761│pacman │ Arch Linux │ mongo-c-driver │ mongo-c-driver │ A single │
762│ │ │ │ │ package pro‐ │
763│ │ │ │ │ vides both │
764│ │ │ │ │ runtime and │
765│ │ │ │ │ development │
766│ │ │ │ │ support for │
767│ │ │ │ │ both libbson │
768│ │ │ │ │ and libmongoc │
769├──────────────┼───────────────┼────────────────┼──────────────────────┼───────────────┤
770│Homebrew │ macOS │ mongo-c-driver │ mongo-c-driver │ │
771├──────────────┼───────────────┼────────────────┼──────────────────────┼───────────────┤
772│Conan │ Cross-plat‐ │ mongo-c-driver │ mongo-c-driver │ See: Conan │
773│ │ form │ │ │ Settings and │
774│ │ │ │ │ Features │
775├──────────────┼───────────────┼────────────────┼──────────────────────┼───────────────┤
776│vcpkg │ Cross-plat‐ │ libbson │ mongo-c-driver │ See: vcpkg │
777│ │ form │ │ │ Optional Fea‐ │
778│ │ │ │ │ tures │
779└──────────────┴───────────────┴────────────────┴──────────────────────┴───────────────┘
780
781 Conan Settings and Features
782 The mongo-c-driver Conan recipe includes several build settings that
783 correspond to the configure-time build settings available when building
784 the mongo-c-driver project.
785
786 SEE ALSO:
787 The mongo-c-driver Conan recipe (includes libbson)
788
789 ┌────────────┬──────────────────┬──────────────────┬──────────────────┐
790 │Setting │ Options │ Default │ Notes │
791 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
792 │shared │ (Boolean) │ False │ Build the shared │
793 │ │ │ │ library instead │
794 │ │ │ │ of the static │
795 │ │ │ │ library │
796 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
797 │fPIC │ (Boolean) │ True │ Compile code as │
798 │ │ │ │ position-inde‐ │
799 │ │ │ │ pendent │
800 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
801 │srv │ (Boolean) │ True │ Enables MongoDB │
802 │ │ │ │ SRV URI support │
803 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
804 │with_ssl │ openssl, li‐ │ openssl [1] │ Select a TLS │
805 │ │ bressl, windows, │ │ backend. Setting │
806 │ │ darwin, False │ │ to "False" dis‐ │
807 │ │ │ │ ables TLS sup‐ │
808 │ │ │ │ port. │
809 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
810 │with_sasl │ sspi, cyrus, │ sspi on Windows, │ Enable SASL au‐ │
811 │ │ False │ False elsewhere │ thentication │
812 │ │ │ │ support │
813 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
814 │with_snappy │ (Boolean) │ True │ Enable Snappy │
815 │ │ │ │ compression │
816 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
817 │with_zlib │ (Boolean) │ True │ Enable Zlib com‐ │
818 │ │ │ │ pression │
819 ├────────────┼──────────────────┼──────────────────┼──────────────────┤
820 │with_zstd │ (Boolean) │ True │ Enable Zstd com‐ │
821 │ │ │ │ pression │
822 └────────────┴──────────────────┴──────────────────┴──────────────────┘
823
824 [1] Conan will use OpenSSL as the default TLS backend, even on plat‐
825 forms that ship with their own TLS implementation (e.g. Windows
826 and macOS). This behavior differs from the upstream default-con‐
827 figured libmongoc or the vcpkg distribution of mongo-c-driver,
828 which both default to use the TLS implementation preferred for the
829 target platform.
830
831 vcpkg Optional Features
832 The mongo-c-driver package offered by vcpkg supports several optional
833 features.
834
835 SEE ALSO:
836
837 • The vcpkg libbson port
838
839 • The vcpkg mongo-c-driver port
840
841 ┌────────┬────────────────────────────┐
842 │Feature │ Notes │
843 ├────────┼────────────────────────────┤
844 │icu │ Installs the ICU library, │
845 │ │ which is necessary for │
846 │ │ non-ASCII usernames and │
847 │ │ passwords in pre-1.25 lib‐ │
848 │ │ mongoc │
849 ├────────┼────────────────────────────┤
850 │openssl │ Use OpenSSL for encryp‐ │
851 │ │ tion, even on Windows and │
852 │ │ Apple platforms which pro‐ │
853 │ │ vide a native TLS backend. │
854 │ │ │
855 │ │ If omitted, the default │
856 │ │ will be to use the pre‐ │
857 │ │ ferred TLS implementation │
858 │ │ for the system. │
859 ├────────┼────────────────────────────┤
860 │snappy │ Enable the Snappy compres‐ │
861 │ │ sion backend │
862 ├────────┼────────────────────────────┤
863 │zstd │ Enable the Zstd compres‐ │
864 │ │ sion backend │
865 └────────┴────────────────────────────┘
866
867 mongo-c-driver Platform Support
868 This page documents information about the target platforms and
869 toolchains that are supported by the mongo-c-driver libraries.
870
871 Operating Systems
872 The following operating systems are continually tested with
873 mongo-c-driver:
874
875 ┌───────────────────────────┬────────────────────────────┐
876 │Operating System │ Notes │
877 ├───────────────────────────┼────────────────────────────┤
878 │Debian │ Versions 9.2, 10.0, and │
879 │ │ 11.0 │
880 ├───────────────────────────┼────────────────────────────┤
881 │RHEL │ Versions 7.0, 7.1, 8.1, │
882 │ │ 8.2, and 8.3. RHEL deriva‐ │
883 │ │ tives (e.g. CentOS, Rocky │
884 │ │ Linux, AlmaLinux) of the │
885 │ │ same release version are │
886 │ │ supported. Fedora is also │
887 │ │ supported, but not contin‐ │
888 │ │ ually tested. │
889 └───────────────────────────┴────────────────────────────┘
890
891
892
893
894
895
896 │Ubuntu │ Versions 16.04, 18.04, and │
897 │ │ 20.04. Subsequent minor │
898 │ │ releases are also sup‐ │
899 │ │ ported. Ubuntu 22.04 and │
900 │ │ newer is not yet tested. │
901 │ │ Ubuntu derivatives based │
902 │ │ on supported Ubuntu ver‐ │
903 │ │ sions are also supported. │
904 ├───────────────────────────┼────────────────────────────┤
905 │Arch Linux │ │
906 ├───────────────────────────┼────────────────────────────┤
907 │macOS │ Version 11.0 │
908 ├───────────────────────────┼────────────────────────────┤
909 │Windows Server 2008 and │ Windows variants of the │
910 │Windows Server 2016 │ same generation are sup‐ │
911 │ │ ported │
912 └───────────────────────────┴────────────────────────────┘
913
914 Compilers
915 The following compilers are continually tested for mongo-c-driver:
916
917 ┌───────────────────────────┬────────────────────────────┐
918 │Compiler │ Notes │
919 ├───────────────────────────┼────────────────────────────┤
920 │Clang │ Versions 3.7, 3.8, and │
921 │ │ 6.0. Newer versions are │
922 │ │ also supported, as well as │
923 │ │ the corresponding Apple │
924 │ │ Clang releases. │
925 ├───────────────────────────┼────────────────────────────┤
926 │GCC │ Versions 4.8, 5.4, 6.3, │
927 │ │ 7.5, 8.2, 8.3, 9.4, and │
928 │ │ 10.2. The MinGW-w64 GCC is │
929 │ │ also tested and supported. │
930 ├───────────────────────────┼────────────────────────────┤
931 │Microsoft Visual C++ │ Tested with MSVC 12.x │
932 │(MSVC) │ (Visual Studio 2013), 14.x │
933 │ │ (Visual Studio 2015), and │
934 │ │ 15.x (Visual Studio 2017). │
935 │ │ Newer MSVC versions are │
936 │ │ supported but not yet │
937 │ │ tested. │
938 └───────────────────────────┴────────────────────────────┘
939
940 Architectures
941 The following CPU architectures are continually tested for
942 mongo-c-driver:
943
944 ┌────────────────────┬────────────────────────────┐
945 │Architecture │ Notes │
946 ├────────────────────┼────────────────────────────┤
947 │x86 (32-bit) │ Only tested on Windows │
948 ├────────────────────┼────────────────────────────┤
949 │x86_64 (64-bit x86) │ Tested on Linux, macOS, │
950 │ │ and Windows │
951 ├────────────────────┼────────────────────────────┤
952 │ARM / aarch64 │ Tested on macOS and Linux │
953 ├────────────────────┼────────────────────────────┤
954 │Power8 (ppc64le) │ Only tested on Linux │
955 ├────────────────────┼────────────────────────────┤
956 │zSeries (s390x) │ Only tested on Linux │
957 └────────────────────┴────────────────────────────┘
958
959 Others
960 Other platforms and toolchains are not tested, but similar versions of
961 the above platforms should work. If you encounter a platform or
962 toolchain that you expect to work and find that it does not, please
963 open an issue describing the problem, and/or open a GitHub Pull Request
964 to fix it.
965
966 Simple pull requests to fix unsupported platforms are welcome, but will
967 be considered on a case-by-case basis. The acceptance of a pull request
968 to fix the libraries on an unsupported platform does not imply full
969 support of that platform.
970
971 Tutorial
972 This guide offers a brief introduction to the MongoDB C Driver.
973
974 For more information on the C API, please refer to the API Reference.
975
976 Installing
977 For detailed instructions on installing the MongoDB C Driver on a par‐
978 ticular platform, please see the installation guide.
979
980 Starting MongoDB
981 To run the examples in this tutorial, MongoDB must be installed and
982 running on localhost on the default port, 27017. To check if it is up
983 and running, connect to it with the MongoDB shell.
984
985 $ mongo --host localhost --port 27017
986 MongoDB shell version: 3.0.6
987 connecting to: localhost:27017/test
988 >
989
990 Include and link libmongoc in your C program
991 Include mongoc.h
992 All libmongoc's functions and types are available in one header file.
993 Simply include mongoc/mongoc.h:
994
995 #include <mongoc/mongoc.h>
996
997 CMake
998 The libmongoc installation includes a CMake config-file package, so you
999 can use CMake's find_package command to import libmongoc's CMake target
1000 and link to libmongoc (as a shared library):
1001
1002 CMakeLists.txt
1003
1004 # Specify the minimum version you require.
1005 find_package (mongoc-1.0 1.7 REQUIRED)
1006
1007 # The "hello_mongoc.c" sample program is shared among four tests.
1008 add_executable (hello_mongoc ../../hello_mongoc.c)
1009 target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_shared)
1010
1011
1012 You can also use libmongoc as a static library instead: Use the
1013 mongo::mongoc_static CMake target:
1014
1015 # Specify the minimum version you require.
1016 find_package (mongoc-1.0 1.7 REQUIRED)
1017
1018 # The "hello_mongoc.c" sample program is shared among four tests.
1019 add_executable (hello_mongoc ../../hello_mongoc.c)
1020 target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_static)
1021
1022
1023 pkg-config
1024 If you're not using CMake, use pkg-config on the command line to set
1025 header and library paths:
1026
1027 gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0)
1028
1029
1030 Or to statically link to libmongoc:
1031
1032 gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0)
1033
1034
1035 Specifying header and include paths manually
1036 If you aren't using CMake or pkg-config, paths and libraries can be
1037 managed manually.
1038
1039 $ gcc -o hello_mongoc hello_mongoc.c \
1040 -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \
1041 -lmongoc-1.0 -lbson-1.0
1042 $ ./hello_mongoc
1043 { "ok" : 1.000000 }
1044
1045 For Windows users, the code can be compiled and run with the following
1046 commands. (This assumes that the MongoDB C Driver has been installed to
1047 C:\mongo-c-driver; change the include directory as needed.)
1048
1049 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 hello_mongoc.c
1050 C:\> hello_mongoc
1051 { "ok" : 1.000000 }
1052
1053 Use libmongoc in a Microsoft Visual Studio Project
1054 See the libmongoc and Visual Studio guide.
1055
1056 Making a Connection
1057 Access MongoDB with a mongoc_client_t. It transparently connects to
1058 standalone servers, replica sets and sharded clusters on demand. To
1059 perform operations on a database or collection, create a
1060 mongoc_database_t or mongoc_collection_t struct from the
1061 mongoc_client_t.
1062
1063 At the start of an application, call mongoc_init() before any other
1064 libmongoc functions. At the end, call the appropriate destroy function
1065 for each collection, database, or client handle, in reverse order from
1066 how they were constructed. Call mongoc_cleanup() before exiting.
1067
1068 The example below establishes a connection to a standalone server on
1069 localhost, registers the client application as "connect-example," and
1070 performs a simple command.
1071
1072 More information about database operations can be found in the CRUD Op‐
1073 erations and Executing Commands sections. Examples of connecting to
1074 replica sets and sharded clusters can be found in the Advanced Connec‐
1075 tions page, while examples of data compression can be found in the Data
1076 Compression page.
1077
1078 hello_mongoc.c
1079
1080 #include <mongoc/mongoc.h>
1081
1082 int
1083 main (int argc, char *argv[])
1084 {
1085 const char *uri_string = "mongodb://localhost:27017";
1086 mongoc_uri_t *uri;
1087 mongoc_client_t *client;
1088 mongoc_database_t *database;
1089 mongoc_collection_t *collection;
1090 bson_t *command, reply, *insert;
1091 bson_error_t error;
1092 char *str;
1093 bool retval;
1094
1095 /*
1096 * Required to initialize libmongoc's internals
1097 */
1098 mongoc_init ();
1099
1100 /*
1101 * Optionally get MongoDB URI from command line
1102 */
1103 if (argc > 1) {
1104 uri_string = argv[1];
1105 }
1106
1107 /*
1108 * Safely create a MongoDB URI object from the given string
1109 */
1110 uri = mongoc_uri_new_with_error (uri_string, &error);
1111 if (!uri) {
1112 fprintf (stderr,
1113 "failed to parse URI: %s\n"
1114 "error message: %s\n",
1115 uri_string,
1116 error.message);
1117 return EXIT_FAILURE;
1118 }
1119
1120 /*
1121 * Create a new client instance
1122 */
1123 client = mongoc_client_new_from_uri (uri);
1124 if (!client) {
1125 return EXIT_FAILURE;
1126 }
1127
1128 /*
1129 * Register the application name so we can track it in the profile logs
1130 * on the server. This can also be done from the URI (see other examples).
1131 */
1132 mongoc_client_set_appname (client, "connect-example");
1133
1134 /*
1135 * Get a handle on the database "db_name" and collection "coll_name"
1136 */
1137 database = mongoc_client_get_database (client, "db_name");
1138 collection = mongoc_client_get_collection (client, "db_name", "coll_name");
1139
1140 /*
1141 * Do work. This example pings the database, prints the result as JSON and
1142 * performs an insert
1143 */
1144 command = BCON_NEW ("ping", BCON_INT32 (1));
1145
1146 retval = mongoc_client_command_simple (
1147 client, "admin", command, NULL, &reply, &error);
1148
1149 if (!retval) {
1150 fprintf (stderr, "%s\n", error.message);
1151 return EXIT_FAILURE;
1152 }
1153
1154 str = bson_as_json (&reply, NULL);
1155 printf ("%s\n", str);
1156
1157 insert = BCON_NEW ("hello", BCON_UTF8 ("world"));
1158
1159 if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) {
1160 fprintf (stderr, "%s\n", error.message);
1161 }
1162
1163 bson_destroy (insert);
1164 bson_destroy (&reply);
1165 bson_destroy (command);
1166 bson_free (str);
1167
1168 /*
1169 * Release our handles and clean up libmongoc
1170 */
1171 mongoc_collection_destroy (collection);
1172 mongoc_database_destroy (database);
1173 mongoc_uri_destroy (uri);
1174 mongoc_client_destroy (client);
1175 mongoc_cleanup ();
1176
1177 return EXIT_SUCCESS;
1178 }
1179
1180
1181 Creating BSON Documents
1182 Documents are stored in MongoDB's data format, BSON. The C driver uses
1183 libbson to create BSON documents. There are several ways to construct
1184 them: appending key-value pairs, using BCON, or parsing JSON.
1185
1186 Appending BSON
1187 A BSON document, represented as a bson_t in code, can be constructed
1188 one field at a time using libbson's append functions.
1189
1190 For example, to create a document like this:
1191
1192 {
1193 born : ISODate("1906-12-09"),
1194 died : ISODate("1992-01-01"),
1195 name : {
1196 first : "Grace",
1197 last : "Hopper"
1198 },
1199 languages : [ "MATH-MATIC", "FLOW-MATIC", "COBOL" ],
1200 degrees: [ { degree: "BA", school: "Vassar" }, { degree: "PhD", school: "Yale" } ]
1201 }
1202
1203 Use the following code:
1204
1205 #include <bson/bson.h>
1206
1207 int
1208 main (int argc, char *argv[])
1209 {
1210 struct tm born = {0};
1211 struct tm died = {0};
1212 const char *lang_names[] = {"MATH-MATIC", "FLOW-MATIC", "COBOL"};
1213 const char *schools[] = {"Vassar", "Yale"};
1214 const char *degrees[] = {"BA", "PhD"};
1215 uint32_t i;
1216 bson_t *document;
1217 bson_t child;
1218 bson_array_builder_t *bab;
1219 char *str;
1220
1221 document = bson_new ();
1222
1223 /*
1224 * Append { "born" : ISODate("1906-12-09") } to the document.
1225 * Passing -1 for the length argument tells libbson to calculate the
1226 * string length.
1227 */
1228 born.tm_year = 6; /* years are 1900-based */
1229 born.tm_mon = 11; /* months are 0-based */
1230 born.tm_mday = 9;
1231 bson_append_date_time (document, "born", -1, mktime (&born) * 1000);
1232
1233 /*
1234 * Append { "died" : ISODate("1992-01-01") } to the document.
1235 */
1236 died.tm_year = 92;
1237 died.tm_mon = 0;
1238 died.tm_mday = 1;
1239
1240 /*
1241 * For convenience, this macro passes length -1 by default.
1242 */
1243 BSON_APPEND_DATE_TIME (document, "died", mktime (&died) * 1000);
1244
1245 /*
1246 * Append a subdocument.
1247 */
1248 BSON_APPEND_DOCUMENT_BEGIN (document, "name", &child);
1249 BSON_APPEND_UTF8 (&child, "first", "Grace");
1250 BSON_APPEND_UTF8 (&child, "last", "Hopper");
1251 bson_append_document_end (document, &child);
1252
1253 /*
1254 * Append array of strings. Generate keys "0", "1", "2".
1255 */
1256 BSON_APPEND_ARRAY_BUILDER_BEGIN (document, "languages", &bab);
1257 for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) {
1258 bson_array_builder_append_utf8 (bab, lang_names[i], -1);
1259 }
1260 bson_append_array_builder_end (document, bab);
1261
1262 /*
1263 * Array of subdocuments:
1264 * degrees: [ { degree: "BA", school: "Vassar" }, ... ]
1265 */
1266 BSON_APPEND_ARRAY_BUILDER_BEGIN (document, "degrees", &bab);
1267 for (i = 0; i < sizeof degrees / sizeof (char *); ++i) {
1268 bson_array_builder_append_document_begin (bab, &child);
1269 BSON_APPEND_UTF8 (&child, "degree", degrees[i]);
1270 BSON_APPEND_UTF8 (&child, "school", schools[i]);
1271 bson_array_builder_append_document_end (bab, &child);
1272 }
1273 bson_append_array_builder_end (document, bab);
1274
1275 /*
1276 * Print the document as a JSON string.
1277 */
1278 str = bson_as_canonical_extended_json (document, NULL);
1279 printf ("%s\n", str);
1280 bson_free (str);
1281
1282 /*
1283 * Clean up allocated bson documents.
1284 */
1285 bson_destroy (document);
1286 return 0;
1287 }
1288
1289
1290 See the libbson documentation for all of the types that can be appended
1291 to a bson_t.
1292
1293 Using BCON
1294 BSON C Object Notation, BCON for short, is an alternative way of con‐
1295 structing BSON documents in a manner closer to the intended format. It
1296 has less type-safety than BSON's append functions but results in less
1297 code.
1298
1299 #include <bson/bson.h>
1300
1301 int
1302 main (int argc,
1303 char *argv[])
1304 {
1305 struct tm born = { 0 };
1306 struct tm died = { 0 };
1307 bson_t *document;
1308 char *str;
1309
1310 born.tm_year = 6;
1311 born.tm_mon = 11;
1312 born.tm_mday = 9;
1313
1314 died.tm_year = 92;
1315 died.tm_mon = 0;
1316 died.tm_mday = 1;
1317
1318 document = BCON_NEW (
1319 "born", BCON_DATE_TIME (mktime (&born) * 1000),
1320 "died", BCON_DATE_TIME (mktime (&died) * 1000),
1321 "name", "{",
1322 "first", BCON_UTF8 ("Grace"),
1323 "last", BCON_UTF8 ("Hopper"),
1324 "}",
1325 "languages", "[",
1326 BCON_UTF8 ("MATH-MATIC"),
1327 BCON_UTF8 ("FLOW-MATIC"),
1328 BCON_UTF8 ("COBOL"),
1329 "]",
1330 "degrees", "[",
1331 "{", "degree", BCON_UTF8 ("BA"), "school", BCON_UTF8 ("Vassar"), "}",
1332 "{", "degree", BCON_UTF8 ("PhD"), "school", BCON_UTF8 ("Yale"), "}",
1333 "]");
1334
1335 /*
1336 * Print the document as a JSON string.
1337 */
1338 str = bson_as_canonical_extended_json (document, NULL);
1339 printf ("%s\n", str);
1340 bson_free (str);
1341
1342 /*
1343 * Clean up allocated bson documents.
1344 */
1345 bson_destroy (document);
1346 return 0;
1347 }
1348
1349 Notice that BCON can create arrays, subdocuments and arbitrary fields.
1350
1351 Creating BSON from JSON
1352 For single documents, BSON can be created from JSON strings via
1353 bson_new_from_json.
1354
1355 #include <bson/bson.h>
1356
1357 int
1358 main (int argc,
1359 char *argv[])
1360 {
1361 bson_error_t error;
1362 bson_t *bson;
1363 char *string;
1364
1365 const char *json = "{\"name\": {\"first\":\"Grace\", \"last\":\"Hopper\"}}";
1366 bson = bson_new_from_json ((const uint8_t *)json, -1, &error);
1367
1368 if (!bson) {
1369 fprintf (stderr, "%s\n", error.message);
1370 return EXIT_FAILURE;
1371 }
1372
1373 string = bson_as_canonical_extended_json (bson, NULL);
1374 printf ("%s\n", string);
1375 bson_free (string);
1376
1377 return 0;
1378 }
1379
1380 To initialize BSON from a sequence of JSON documents, use
1381 bson_json_reader_t.
1382
1383 Basic CRUD Operations
1384 This section demonstrates the basics of using the C Driver to interact
1385 with MongoDB.
1386
1387 Inserting a Document
1388 To insert documents into a collection, first obtain a handle to a mon‐
1389 goc_collection_t via a mongoc_client_t. Then, use
1390 mongoc_collection_insert_one() to add BSON documents to the collection.
1391 This example inserts into the database "mydb" and collection "mycoll".
1392
1393 When finished, ensure that allocated structures are freed by using
1394 their respective destroy functions.
1395
1396 #include <bson/bson.h>
1397 #include <mongoc/mongoc.h>
1398 #include <stdio.h>
1399
1400 int
1401 main (int argc,
1402 char *argv[])
1403 {
1404 mongoc_client_t *client;
1405 mongoc_collection_t *collection;
1406 bson_error_t error;
1407 bson_oid_t oid;
1408 bson_t *doc;
1409
1410 mongoc_init ();
1411
1412 client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
1413 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1414
1415 doc = bson_new ();
1416 bson_oid_init (&oid, NULL);
1417 BSON_APPEND_OID (doc, "_id", &oid);
1418 BSON_APPEND_UTF8 (doc, "hello", "world");
1419
1420 if (!mongoc_collection_insert_one (
1421 collection, doc, NULL, NULL, &error)) {
1422 fprintf (stderr, "%s\n", error.message);
1423 }
1424
1425 bson_destroy (doc);
1426 mongoc_collection_destroy (collection);
1427 mongoc_client_destroy (client);
1428 mongoc_cleanup ();
1429
1430 return 0;
1431 }
1432
1433 Compile the code and run it:
1434
1435 $ gcc -o insert insert.c $(pkg-config --cflags --libs libmongoc-1.0)
1436 $ ./insert
1437
1438 On Windows:
1439
1440 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 insert.c
1441 C:\> insert
1442
1443 To verify that the insert succeeded, connect with the MongoDB shell.
1444
1445 $ mongo
1446 MongoDB shell version: 3.0.6
1447 connecting to: test
1448 > use mydb
1449 switched to db mydb
1450 > db.mycoll.find()
1451 { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" }
1452 >
1453
1454 Finding a Document
1455 To query a MongoDB collection with the C driver, use the function
1456 mongoc_collection_find_with_opts(). This returns a cursor to the match‐
1457 ing documents. The following examples iterate through the result cur‐
1458 sors and print the matches to stdout as JSON strings.
1459
1460 Use a document as a query specifier; for example,
1461
1462 { "color" : "red" }
1463
1464 will match any document with a field named "color" with value "red". An
1465 empty document {} can be used to match all documents.
1466
1467 This first example uses an empty query specifier to find all documents
1468 in the database "mydb" and collection "mycoll".
1469
1470 #include <bson/bson.h>
1471 #include <mongoc/mongoc.h>
1472 #include <stdio.h>
1473
1474 int
1475 main (int argc, char *argv[])
1476 {
1477 mongoc_client_t *client;
1478 mongoc_collection_t *collection;
1479 mongoc_cursor_t *cursor;
1480 const bson_t *doc;
1481 bson_t *query;
1482 char *str;
1483
1484 mongoc_init ();
1485
1486 client =
1487 mongoc_client_new ("mongodb://localhost:27017/?appname=find-example");
1488 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1489 query = bson_new ();
1490 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
1491
1492 while (mongoc_cursor_next (cursor, &doc)) {
1493 str = bson_as_canonical_extended_json (doc, NULL);
1494 printf ("%s\n", str);
1495 bson_free (str);
1496 }
1497
1498 bson_destroy (query);
1499 mongoc_cursor_destroy (cursor);
1500 mongoc_collection_destroy (collection);
1501 mongoc_client_destroy (client);
1502 mongoc_cleanup ();
1503
1504 return 0;
1505 }
1506
1507 Compile the code and run it:
1508
1509 $ gcc -o find find.c $(pkg-config --cflags --libs libmongoc-1.0)
1510 $ ./find
1511 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1512
1513 On Windows:
1514
1515 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find.c
1516 C:\> find
1517 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1518
1519 To look for a specific document, add a specifier to query. This example
1520 adds a call to BSON_APPEND_UTF8() to look for all documents matching
1521 {"hello" : "world"}.
1522
1523 #include <bson/bson.h>
1524 #include <mongoc/mongoc.h>
1525 #include <stdio.h>
1526
1527 int
1528 main (int argc, char *argv[])
1529 {
1530 mongoc_client_t *client;
1531 mongoc_collection_t *collection;
1532 mongoc_cursor_t *cursor;
1533 const bson_t *doc;
1534 bson_t *query;
1535 char *str;
1536
1537 mongoc_init ();
1538
1539 client = mongoc_client_new (
1540 "mongodb://localhost:27017/?appname=find-specific-example");
1541 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1542 query = bson_new ();
1543 BSON_APPEND_UTF8 (query, "hello", "world");
1544
1545 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
1546
1547 while (mongoc_cursor_next (cursor, &doc)) {
1548 str = bson_as_canonical_extended_json (doc, NULL);
1549 printf ("%s\n", str);
1550 bson_free (str);
1551 }
1552
1553 bson_destroy (query);
1554 mongoc_cursor_destroy (cursor);
1555 mongoc_collection_destroy (collection);
1556 mongoc_client_destroy (client);
1557 mongoc_cleanup ();
1558
1559 return 0;
1560 }
1561
1562 $ gcc -o find-specific find-specific.c $(pkg-config --cflags --libs libmongoc-1.0)
1563 $ ./find-specific
1564 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1565
1566 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find-specific.c
1567 C:\> find-specific
1568 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1569
1570 Updating a Document
1571 This code snippet gives an example of using
1572 mongoc_collection_update_one() to update the fields of a document.
1573
1574 Using the "mydb" database, the following example inserts an example
1575 document into the "mycoll" collection. Then, using its _id field, the
1576 document is updated with different values and a new field.
1577
1578 #include <bson/bson.h>
1579 #include <mongoc/mongoc.h>
1580 #include <stdio.h>
1581
1582 int
1583 main (int argc, char *argv[])
1584 {
1585 mongoc_collection_t *collection;
1586 mongoc_client_t *client;
1587 bson_error_t error;
1588 bson_oid_t oid;
1589 bson_t *doc = NULL;
1590 bson_t *update = NULL;
1591 bson_t *query = NULL;
1592
1593 mongoc_init ();
1594
1595 client =
1596 mongoc_client_new ("mongodb://localhost:27017/?appname=update-example");
1597 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1598
1599 bson_oid_init (&oid, NULL);
1600 doc = BCON_NEW ("_id", BCON_OID (&oid), "key", BCON_UTF8 ("old_value"));
1601
1602 if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
1603 fprintf (stderr, "%s\n", error.message);
1604 goto fail;
1605 }
1606
1607 query = BCON_NEW ("_id", BCON_OID (&oid));
1608 update = BCON_NEW ("$set",
1609 "{",
1610 "key",
1611 BCON_UTF8 ("new_value"),
1612 "updated",
1613 BCON_BOOL (true),
1614 "}");
1615
1616 if (!mongoc_collection_update_one (
1617 collection, query, update, NULL, NULL, &error)) {
1618 fprintf (stderr, "%s\n", error.message);
1619 goto fail;
1620 }
1621
1622 fail:
1623 if (doc)
1624 bson_destroy (doc);
1625 if (query)
1626 bson_destroy (query);
1627 if (update)
1628 bson_destroy (update);
1629
1630 mongoc_collection_destroy (collection);
1631 mongoc_client_destroy (client);
1632 mongoc_cleanup ();
1633
1634 return 0;
1635 }
1636
1637 Compile the code and run it:
1638
1639 $ gcc -o update update.c $(pkg-config --cflags --libs libmongoc-1.0)
1640 $ ./update
1641
1642 On Windows:
1643
1644 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 update.c
1645 C:\> update
1646 { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1647
1648 To verify that the update succeeded, connect with the MongoDB shell.
1649
1650 $ mongo
1651 MongoDB shell version: 3.0.6
1652 connecting to: test
1653 > use mydb
1654 switched to db mydb
1655 > db.mycoll.find({"updated" : true})
1656 { "_id" : ObjectId("55ef549236fe322f9490e17b"), "updated" : true, "key" : "new_value" }
1657 >
1658
1659 Deleting a Document
1660 This example illustrates the use of mongoc_collection_delete_one() to
1661 delete a document.
1662
1663 The following code inserts a sample document into the database "mydb"
1664 and collection "mycoll". Then, it deletes all documents matching
1665 {"hello" : "world"}.
1666
1667 #include <bson/bson.h>
1668 #include <mongoc/mongoc.h>
1669 #include <stdio.h>
1670
1671 int
1672 main (int argc, char *argv[])
1673 {
1674 mongoc_client_t *client;
1675 mongoc_collection_t *collection;
1676 bson_error_t error;
1677 bson_oid_t oid;
1678 bson_t *doc;
1679
1680 mongoc_init ();
1681
1682 client =
1683 mongoc_client_new ("mongodb://localhost:27017/?appname=delete-example");
1684 collection = mongoc_client_get_collection (client, "test", "test");
1685
1686 doc = bson_new ();
1687 bson_oid_init (&oid, NULL);
1688 BSON_APPEND_OID (doc, "_id", &oid);
1689 BSON_APPEND_UTF8 (doc, "hello", "world");
1690
1691 if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
1692 fprintf (stderr, "Insert failed: %s\n", error.message);
1693 }
1694
1695 bson_destroy (doc);
1696
1697 doc = bson_new ();
1698 BSON_APPEND_OID (doc, "_id", &oid);
1699
1700 if (!mongoc_collection_delete_one (
1701 collection, doc, NULL, NULL, &error)) {
1702 fprintf (stderr, "Delete failed: %s\n", error.message);
1703 }
1704
1705 bson_destroy (doc);
1706 mongoc_collection_destroy (collection);
1707 mongoc_client_destroy (client);
1708 mongoc_cleanup ();
1709
1710 return 0;
1711 }
1712
1713 Compile the code and run it:
1714
1715 $ gcc -o delete delete.c $(pkg-config --cflags --libs libmongoc-1.0)
1716 $ ./delete
1717
1718 On Windows:
1719
1720 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 delete.c
1721 C:\> delete
1722
1723 Use the MongoDB shell to prove that the documents have been removed
1724 successfully.
1725
1726 $ mongo
1727 MongoDB shell version: 3.0.6
1728 connecting to: test
1729 > use mydb
1730 switched to db mydb
1731 > db.mycoll.count({"hello" : "world"})
1732 0
1733 >
1734
1735 Counting Documents
1736 Counting the number of documents in a MongoDB collection is similar to
1737 performing a find operation. This example counts the number of docu‐
1738 ments matching {"hello" : "world"} in the database "mydb" and collec‐
1739 tion "mycoll".
1740
1741 #include <bson/bson.h>
1742 #include <mongoc/mongoc.h>
1743 #include <stdio.h>
1744
1745 int
1746 main (int argc, char *argv[])
1747 {
1748 mongoc_client_t *client;
1749 mongoc_collection_t *collection;
1750 bson_error_t error;
1751 bson_t *doc;
1752 int64_t count;
1753
1754 mongoc_init ();
1755
1756 client =
1757 mongoc_client_new ("mongodb://localhost:27017/?appname=count-example");
1758 collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1759 doc = bson_new_from_json (
1760 (const uint8_t *) "{\"hello\" : \"world\"}", -1, &error);
1761
1762 count = mongoc_collection_count (
1763 collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
1764
1765 if (count < 0) {
1766 fprintf (stderr, "%s\n", error.message);
1767 } else {
1768 printf ("%" PRId64 "\n", count);
1769 }
1770
1771 bson_destroy (doc);
1772 mongoc_collection_destroy (collection);
1773 mongoc_client_destroy (client);
1774 mongoc_cleanup ();
1775
1776 return 0;
1777 }
1778
1779 Compile the code and run it:
1780
1781 $ gcc -o count count.c $(pkg-config --cflags --libs libmongoc-1.0)
1782 $ ./count
1783 1
1784
1785 On Windows:
1786
1787 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 count.c
1788 C:\> count
1789 1
1790
1791 Executing Commands
1792 The driver provides helper functions for executing MongoDB commands on
1793 client, database and collection structures. The _simple variants return
1794 booleans indicating success or failure.
1795
1796 This example executes the ping command against the database "mydb".
1797
1798 #include <bson/bson.h>
1799 #include <mongoc/mongoc.h>
1800 #include <stdio.h>
1801
1802 int
1803 main (int argc, char *argv[])
1804 {
1805 mongoc_client_t *client;
1806 bson_error_t error;
1807 bson_t *command;
1808 bson_t reply;
1809 char *str;
1810
1811 mongoc_init ();
1812
1813 client = mongoc_client_new (
1814 "mongodb://localhost:27017/?appname=executing-example");
1815
1816 command = BCON_NEW ("ping", BCON_INT32 (1));
1817 if (mongoc_client_command_simple (
1818 client, "mydb", command, NULL, &reply, &error)) {
1819 str = bson_as_canonical_extended_json (&reply, NULL);
1820 printf ("%s\n", str);
1821 bson_free (str);
1822 } else {
1823 fprintf (stderr, "Failed to run command: %s\n", error.message);
1824 }
1825
1826 bson_destroy (command);
1827 bson_destroy (&reply);
1828 mongoc_client_destroy (client);
1829 mongoc_cleanup ();
1830
1831 return 0;
1832 }
1833
1834
1835 Compile the code and run it:
1836
1837 $ gcc -o executing executing.c $(pkg-config --cflags --libs libmongoc-1.0)
1838 $ ./executing
1839 { "ok" : { "$numberDouble" : "1.0" }, "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1682609211, "i" : 1 } }, "signature" : { "hash" : { "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType" : "00" } }, "keyId" : { "$numberLong" : "0" } } }, "operationTime" : { "$timestamp" : { "t" : 1682609211, "i" : 1 } } }
1840
1841 On Windows:
1842
1843 C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 executing.c
1844 C:\> executing
1845 { "ok" : { "$numberDouble" : "1.0" }, "$clusterTime" : { "clusterTime" : { "$timestamp" : { "t" : 1682609211, "i" : 1 } }, "signature" : { "hash" : { "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType" : "00" } }, "keyId" : { "$numberLong" : "0" } } }, "operationTime" : { "$timestamp" : { "t" : 1682609211, "i" : 1 } } }
1846
1847 Threading
1848 The MongoDB C Driver is thread-unaware in the vast majority of its op‐
1849 erations. This means it is up to the programmer to guarantee
1850 thread-safety.
1851
1852 However, mongoc_client_pool_t is thread-safe and is used to fetch a
1853 mongoc_client_t in a thread-safe manner. After retrieving a client from
1854 the pool, the client structure should be considered owned by the call‐
1855 ing thread. When the thread is finished, the client should be placed
1856 back into the pool.
1857
1858 example-pool.c
1859
1860 /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
1861 * libmongoc-1.0) */
1862
1863 /* ./example-pool [CONNECTION_STRING] */
1864
1865 #include <mongoc/mongoc.h>
1866 #include <pthread.h>
1867 #include <stdio.h>
1868
1869 static pthread_mutex_t mutex;
1870 static bool in_shutdown = false;
1871
1872 static void *
1873 worker (void *data)
1874 {
1875 mongoc_client_pool_t *pool = data;
1876 mongoc_client_t *client;
1877 bson_t ping = BSON_INITIALIZER;
1878 bson_error_t error;
1879 bool r;
1880
1881 BSON_APPEND_INT32 (&ping, "ping", 1);
1882
1883 while (true) {
1884 client = mongoc_client_pool_pop (pool);
1885 /* Do something with client. If you are writing an HTTP server, you
1886 * probably only want to hold onto the client for the portion of the
1887 * request performing database queries.
1888 */
1889 r = mongoc_client_command_simple (
1890 client, "admin", &ping, NULL, NULL, &error);
1891
1892 if (!r) {
1893 fprintf (stderr, "%s\n", error.message);
1894 }
1895
1896 mongoc_client_pool_push (pool, client);
1897
1898 pthread_mutex_lock (&mutex);
1899 if (in_shutdown || !r) {
1900 pthread_mutex_unlock (&mutex);
1901 break;
1902 }
1903
1904 pthread_mutex_unlock (&mutex);
1905 }
1906
1907 bson_destroy (&ping);
1908 return NULL;
1909 }
1910
1911 int
1912 main (int argc, char *argv[])
1913 {
1914 const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
1915 mongoc_uri_t *uri;
1916 bson_error_t error;
1917 mongoc_client_pool_t *pool;
1918 pthread_t threads[10];
1919 unsigned i;
1920 void *ret;
1921
1922 pthread_mutex_init (&mutex, NULL);
1923 mongoc_init ();
1924
1925 if (argc > 1) {
1926 uri_string = argv[1];
1927 }
1928
1929 uri = mongoc_uri_new_with_error (uri_string, &error);
1930 if (!uri) {
1931 fprintf (stderr,
1932 "failed to parse URI: %s\n"
1933 "error message: %s\n",
1934 uri_string,
1935 error.message);
1936 return EXIT_FAILURE;
1937 }
1938
1939 pool = mongoc_client_pool_new (uri);
1940 mongoc_client_pool_set_error_api (pool, 2);
1941
1942 for (i = 0; i < 10; i++) {
1943 pthread_create (&threads[i], NULL, worker, pool);
1944 }
1945
1946 sleep (10);
1947 pthread_mutex_lock (&mutex);
1948 in_shutdown = true;
1949 pthread_mutex_unlock (&mutex);
1950
1951 for (i = 0; i < 10; i++) {
1952 pthread_join (threads[i], &ret);
1953 }
1954
1955 mongoc_client_pool_destroy (pool);
1956 mongoc_uri_destroy (uri);
1957
1958 mongoc_cleanup ();
1959
1960 return EXIT_SUCCESS;
1961 }
1962
1963
1964 Next Steps
1965 To find information on advanced topics, browse the rest of the C driver
1966 guide or the official MongoDB documentation.
1967
1968 For help with common issues, consult the Troubleshooting page. To re‐
1969 port a bug or request a new feature, follow these instructions.
1970
1971 Authentication
1972 This guide covers the use of authentication options with the MongoDB C
1973 Driver. Ensure that the MongoDB server is also properly configured for
1974 authentication before making a connection. For more information, see
1975 the MongoDB security documentation.
1976
1977 The MongoDB C driver supports several authentication mechanisms through
1978 the use of MongoDB connection URIs.
1979
1980 By default, if a username and password are provided as part of the con‐
1981 nection string (and an optional authentication database), they are used
1982 to connect via the default authentication mechanism of the server.
1983
1984 To select a specific authentication mechanism other than the default,
1985 see the list of supported mechanism below.
1986
1987 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
1988
1989 Currently supported values for the authMechanism connection string op‐
1990 tion are:
1991
1992 • SCRAM-SHA-1
1993
1994 • MONGODB-CR (deprecated)
1995
1996 • GSSAPI
1997
1998 • PLAIN
1999
2000 • X509
2001
2002 • MONGODB-AWS
2003
2004 Basic Authentication (SCRAM-SHA-256)
2005 MongoDB 4.0 introduces support for authenticating using the SCRAM pro‐
2006 tocol with the more secure SHA-256 hash described in RFC 7677. Using
2007 this authentication mechanism means that the password is never actually
2008 sent over the wire when authenticating, but rather a computed proof
2009 that the client password is the same as the password the server knows.
2010 In MongoDB 4.0, the C driver can determine the correct default authen‐
2011 tication mechanism for users with stored SCRAM-SHA-1 and SCRAM-SHA-256
2012 credentials:
2013
2014 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
2015 /* the correct authMechanism is negotiated between the driver and server. */
2016
2017 Alternatively, SCRAM-SHA-256 can be explicitly specified as an auth‐
2018 Mechanism.
2019
2020 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-256&authSource=mydb");
2021
2022 Basic Authentication (SCRAM-SHA-1)
2023 The default authentication mechanism before MongoDB 4.0 is SCRAM-SHA-1
2024 (RFC 5802). Using this authentication mechanism means that the password
2025 is never actually sent over the wire when authenticating, but rather a
2026 computed proof that the client password is the same as the password the
2027 server knows.
2028
2029 mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1&authSource=mydb");
2030
2031 NOTE:
2032 SCRAM-SHA-1 authenticates against the admin database by default. If
2033 the user is created in another database, then specifying the auth‐
2034 Source is required.
2035
2036 Legacy Authentication (MONGODB-CR)
2037 The MONGODB-CR authMechanism is deprecated and will no longer function
2038 in MongoDB 4.0. Instead, specify no authMechanism and the driver will
2039 use an authentication mechanism compatible with your server.
2040
2041 GSSAPI (Kerberos) Authentication
2042 NOTE:
2043 On UNIX-like environments, Kerberos support requires compiling the
2044 driver against cyrus-sasl.
2045
2046 On Windows, Kerberos support requires compiling the driver against
2047 Windows Native SSPI or cyrus-sasl. The default configuration of the
2048 driver will use Windows Native SSPI.
2049
2050 To modify the default configuration, use the cmake option EN‐
2051 ABLE_SASL.
2052
2053 GSSAPI (Kerberos) authentication is available in the Enterprise Edition
2054 of MongoDB. To authenticate using GSSAPI, the MongoDB C driver must be
2055 installed with SASL support.
2056
2057 On UNIX-like environments, run the kinit command before using the fol‐
2058 lowing authentication methods:
2059
2060 $ kinit mongodbuser@EXAMPLE.COM
2061 mongodbuser@EXAMPLE.COM's Password:
2062 $ klistCredentials cache: FILE:/tmp/krb5cc_1000
2063 Principal: mongodbuser@EXAMPLE.COM
2064
2065 Issued Expires Principal
2066 Feb 9 13:48:51 2013 Feb 9 23:48:51 2013 krbtgt/EXAMPLE.COM@EXAMPLE.COM
2067
2068 Now authenticate using the MongoDB URI. GSSAPI authenticates against
2069 the $external virtual database, so a database does not need to be spec‐
2070 ified in the URI. Note that the Kerberos principal must be URL-encoded:
2071
2072 mongoc_client_t *client;
2073
2074 client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI");
2075
2076 NOTE:
2077 GSSAPI authenticates against the $external database, so specifying
2078 the authSource database is not required.
2079
2080 The driver supports these GSSAPI properties:
2081
2082 • CANONICALIZE_HOST_NAME: This might be required with Cyrus-SASL when
2083 the hosts report different hostnames than what is used in the Ker‐
2084 beros database. The default is "false".
2085
2086 • SERVICE_NAME: Use a different service name than the default, "mon‐
2087 godb".
2088
2089 Set properties in the URL:
2090
2091 mongoc_client_t *client;
2092
2093 client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&"
2094 "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true");
2095
2096 If you encounter errors such as Invalid net address, check if the ap‐
2097 plication is behind a NAT (Network Address Translation) firewall. If
2098 so, create a ticket that uses forwardable and addressless Kerberos
2099 tickets. This can be done by passing -f -A to kinit.
2100
2101 $ kinit -f -A mongodbuser@EXAMPLE.COM
2102
2103 SASL Plain Authentication
2104 NOTE:
2105 The MongoDB C Driver must be compiled with SASL support in order to
2106 use SASL PLAIN authentication.
2107
2108 MongoDB Enterprise Edition supports the SASL PLAIN authentication mech‐
2109 anism, initially intended for delegating authentication to an LDAP
2110 server. Using the SASL PLAIN mechanism is very similar to the challenge
2111 response mechanism with usernames and passwords. This authentication
2112 mechanism uses the $external virtual database for LDAP support:
2113
2114 NOTE:
2115 SASL PLAIN is a clear-text authentication mechanism. It is strongly
2116 recommended to connect to MongoDB using TLS with certificate valida‐
2117 tion when using the PLAIN mechanism.
2118
2119 mongoc_client_t *client;
2120
2121 client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN");
2122
2123 PLAIN authenticates against the $external database, so specifying the
2124 authSource database is not required.
2125
2126 X.509 Certificate Authentication
2127 NOTE:
2128 The MongoDB C Driver must be compiled with TLS support for X.509 au‐
2129 thentication support. Once this is done, start a server with the
2130 following options:
2131
2132 $ mongod --tlsMode requireTLS --tlsCertificateKeyFile server.pem --tlsCAFile ca.pem
2133
2134 The MONGODB-X509 mechanism authenticates a username derived from the
2135 distinguished subject name of the X.509 certificate presented by the
2136 driver during TLS negotiation. This authentication method requires the
2137 use of TLS connections with certificate validation.
2138
2139 mongoc_client_t *client;
2140 mongoc_ssl_opt_t ssl_opts = { 0 };
2141
2142 ssl_opts.pem_file = "mycert.pem";
2143 ssl_opts.pem_pwd = "mycertpassword";
2144 ssl_opts.ca_file = "myca.pem";
2145 ssl_opts.ca_dir = "trust_dir";
2146 ssl_opts.weak_cert_validation = false;
2147
2148 client = mongoc_client_new ("mongodb://x509_derived_username@localhost/?authMechanism=MONGODB-X509");
2149 mongoc_client_set_ssl_opts (client, &ssl_opts);
2150
2151 MONGODB-X509 authenticates against the $external database, so specify‐
2152 ing the authSource database is not required. For more information on
2153 the x509_derived_username, see the MongoDB server x.509 tutorial.
2154
2155 NOTE:
2156 The MongoDB C Driver will attempt to determine the x509 derived
2157 username when none is provided, and as of MongoDB 3.4 providing the
2158 username is not required at all.
2159
2160 Authentication via AWS IAM
2161 The MONGODB-AWS mechanism authenticates to MongoDB servers with creden‐
2162 tials provided by AWS Identity and Access Management (IAM).
2163
2164 To authenticate, create a user with an associated Amazon Resource Name
2165 (ARN) on the $external database, and specify the MONGODB-AWS authMecha‐
2166 nism in the URI.
2167
2168 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost/?authMechanism=MONGODB-AWS");
2169
2170 Since MONGODB-AWS always authenticates against the $external database,
2171 so specifying the authSource database is not required.
2172
2173 Credentials include the access key id, secret access key, and optional
2174 session token. They may be obtained from the following ways.
2175
2176 AWS credentials via URI
2177 Credentials may be passed directly in the URI as username/password.
2178
2179 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://<access key id>:<secret access key>localhost/?authMechanism=MONGODB-AWS");
2180
2181 This may include a session token passed with authMechanismProperties.
2182
2183 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://<access key id>:<secret access key>localhost/?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:<token>");
2184
2185 AWS credentials via environment
2186 If credentials are not passed through the URI, libmongoc will check for
2187 the following environment variables.
2188
2189 • AWS_ACCESS_KEY_ID
2190
2191 • AWS_SECRET_ACCESS_KEY
2192
2193 • AWS_SESSION_TOKEN (optional)
2194
2195 AWS Credentials via ECS
2196 If credentials are not passed in the URI or with environment variables,
2197 libmongoc will check if the environment variable AWS_CONTAINER_CREDEN‐
2198 TIALS_RELATIVE_URI is set, and if so, attempt to retrieve temporary
2199 credentials from the ECS task metadata by querying a link local ad‐
2200 dress.
2201
2202 AWS Credentials via EC2
2203 If credentials are not passed in the URI or with environment variables,
2204 and the environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is
2205 not set, libmongoc will attempt to retrieve temporary credentials from
2206 the EC2 machine metadata by querying link local addresses.
2207
2208 Basic Troubleshooting
2209 Troubleshooting Checklist
2210 The following is a short list of things to check when you have a prob‐
2211 lem.
2212
2213 • Did you call mongoc_init() in main()? If not, you will likely see a
2214 segfault.
2215
2216 • Have you leaked any clients or cursors as can be found with mon‐
2217 goc-stat <PID>?
2218
2219 • Have packets been delivered to the server? See egress bytes from mon‐
2220 goc-stat <PID>.
2221
2222 • Does ASAN show any leaks? Ensure you call mongoc_cleanup() at the end
2223 of your process to cleanup lingering allocations from the MongoDB C
2224 driver.
2225
2226 • If compiling your own copy of MongoDB C Driver, consider using the
2227 cmake option -DENABLE_TRACING=ON to enable function tracing and hex
2228 dumps of network packets to STDERR and STDOUT.
2229
2230 Performance Counters
2231 The MongoDB C Driver comes with an optional and unique feature to help
2232 developers and sysadmins troubleshoot problems in production. Perfor‐
2233 mance counters are available for each process using the C Driver. If
2234 available, the counters can be accessed outside of the application
2235 process via a shared memory segment. The counters may be used graph
2236 statistics about your application process easily from tools like Munin
2237 or Nagios. For example, the command watch --interval=0.5 -d mon‐
2238 goc-stat $PID may be used to monitor an application.
2239
2240 Performance counters are only available on Linux platforms and macOS
2241 arm64 platforms that support shared memory segments. On supported
2242 platforms, they are enabled by default. Applications can be built
2243 without the counters by specifying the cmake option -DENABLE_SHM_COUN‐
2244 TERS=OFF. Additionally, if performance counters are already compiled,
2245 they can be disabled at runtime by specifying the environment variable
2246 MONGOC_DISABLE_SHM.
2247
2248 Performance counters keep track of the following:
2249
2250 • Active and Disposed Cursors
2251
2252 • Active and Disposed Clients, Client Pools, and Socket Streams.
2253
2254 • Number of operations sent and received, by type.
2255
2256 • Bytes transferred and received.
2257
2258 • Authentication successes and failures.
2259
2260 • Number of wire protocol errors.
2261
2262 NOTE:
2263 An operation is considered "sent" when one or more bytes of the cor‐
2264 responding message is written to the stream, regardless of whether
2265 the entire message is successfully written or if the operation ulti‐
2266 mately succeeds or fails. This does not include bytes that may be
2267 written during the stream connection process, such as TLS handshake
2268 messages.
2269
2270 To access counters for a given process, simply provide the process id
2271 to the mongoc-stat program installed with the MongoDB C Driver.
2272
2273 $ mongoc-stat 22203
2274 Operations : Egress Total : The number of sent operations. : 13247
2275 Operations : Ingress Total : The number of received operations. : 13246
2276 Operations : Egress Queries : The number of sent Query operations. : 13247
2277 Operations : Ingress Queries : The number of received Query operations. : 0
2278 Operations : Egress GetMore : The number of sent GetMore operations. : 0
2279 Operations : Ingress GetMore : The number of received GetMore operations. : 0
2280 Operations : Egress Insert : The number of sent Insert operations. : 0
2281 Operations : Ingress Insert : The number of received Insert operations. : 0
2282 Operations : Egress Delete : The number of sent Delete operations. : 0
2283 Operations : Ingress Delete : The number of received Delete operations. : 0
2284 Operations : Egress Update : The number of sent Update operations. : 0
2285 Operations : Ingress Update : The number of received Update operations. : 0
2286 Operations : Egress KillCursors : The number of sent KillCursors operations. : 0
2287 Operations : Ingress KillCursors : The number of received KillCursors operations. : 0
2288 Operations : Egress Msg : The number of sent Msg operations. : 0
2289 Operations : Ingress Msg : The number of received Msg operations. : 0
2290 Operations : Egress Reply : The number of sent Reply operations. : 0
2291 Operations : Ingress Reply : The number of received Reply operations. : 13246
2292 Cursors : Active : The number of active cursors. : 1
2293 Cursors : Disposed : The number of disposed cursors. : 13246
2294 Clients : Active : The number of active clients. : 1
2295 Clients : Disposed : The number of disposed clients. : 0
2296 Streams : Active : The number of active streams. : 1
2297 Streams : Disposed : The number of disposed streams. : 0
2298 Streams : Egress Bytes : The number of bytes sent. : 794931
2299 Streams : Ingress Bytes : The number of bytes received. : 589694
2300 Streams : N Socket Timeouts : The number of socket timeouts. : 0
2301 Client Pools : Active : The number of active client pools. : 1
2302 Client Pools : Disposed : The number of disposed client pools. : 0
2303 Protocol : Ingress Errors : The number of protocol errors on ingress. : 0
2304 Auth : Failures : The number of failed authentication requests. : 0
2305 Auth : Success : The number of successful authentication requests. : 0
2306
2307 Submitting a Bug Report
2308 Think you've found a bug? Want to see a new feature in the MongoDB C
2309 driver? Please open a case in our issue management tool, JIRA:
2310
2311 • Create an account and login.
2312
2313 • Navigate to the CDRIVER project.
2314
2315 • Click Create Issue - Please provide as much information as possible
2316 about the issue type and how to reproduce it.
2317
2318 Bug reports in JIRA for all driver projects (i.e. CDRIVER, CSHARP,
2319 JAVA) and the Core Server (i.e. SERVER) project are public.
2320
2321 Guides
2322 Configuring TLS
2323 Configuration with URI options
2324 Enable TLS by including tls=true in the URI.
2325
2326 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/");
2327 mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
2328
2329 mongoc_client_t *client = mongoc_client_new_from_uri (uri);
2330
2331 The following URI options may be used to further configure TLS:
2332
2333 ┌────────────────────┬─────────────────────┬─────────────────────┐
2334 │Constant │ Key │ Description │
2335 ├────────────────────┼─────────────────────┼─────────────────────┤
2336 │MONGOC_URI_TLS │ tls │ {true|false}, indi‐ │
2337 │ │ │ cating if TLS must │
2338 │ │ │ be used. │
2339 ├────────────────────┼─────────────────────┼─────────────────────┤
2340 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ Path to PEM format‐ │
2341 │TIFICATEKEYFILE │ file │ ted Private Key, │
2342 │ │ │ with its Public │
2343 │ │ │ Certificate con‐ │
2344 │ │ │ catenated at the │
2345 │ │ │ end. │
2346 ├────────────────────┼─────────────────────┼─────────────────────┤
2347 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ The password, if │
2348 │TIFICATEKEY‐ │ password │ any, to use to un‐ │
2349 │FILEPASSWORD │ │ lock encrypted Pri‐ │
2350 │ │ │ vate Key. │
2351 ├────────────────────┼─────────────────────┼─────────────────────┤
2352 │MON‐ │ tlscafile │ One, or a bundle │
2353 │GOC_URI_TLSCAFILE │ │ of, Certificate Au‐ │
2354 │ │ │ thorities whom │
2355 │ │ │ should be consid‐ │
2356 │ │ │ ered to be trusted. │
2357 ├────────────────────┼─────────────────────┼─────────────────────┤
2358 │MONGOC_URI_TLSAL‐ │ tlsallowinvalidcer‐ │ Accept and ignore │
2359 │LOWINVALIDCERTIFI‐ │ tificates │ certificate verifi‐ │
2360 │CATES │ │ cation errors (e.g. │
2361 │ │ │ untrusted issuer, │
2362 │ │ │ expired, etc.) │
2363 └────────────────────┴─────────────────────┴─────────────────────┘
2364
2365
2366
2367
2368
2369
2370
2371 │MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │ Ignore hostname │
2372 │LOWINVALIDHOSTNAMES │ hostnames │ verification of the │
2373 │ │ │ certificate (e.g. │
2374 │ │ │ Man In The Middle, │
2375 │ │ │ using valid cer‐ │
2376 │ │ │ tificate, but is‐ │
2377 │ │ │ sued for another │
2378 │ │ │ hostname) │
2379 ├────────────────────┼─────────────────────┼─────────────────────┤
2380 │MONGOC_URI_TLSINSE‐ │ tlsinsecure │ {true|false}, indi‐ │
2381 │CURE │ │ cating if insecure │
2382 │ │ │ TLS options should │
2383 │ │ │ be used. Currently │
2384 │ │ │ this implies MON‐ │
2385 │ │ │ GOC_URI_TLSALLOWIN‐ │
2386 │ │ │ VALIDCERTIFICATES │
2387 │ │ │ and MONGOC_URI_TL‐ │
2388 │ │ │ SALLOWINVALIDHOST‐ │
2389 │ │ │ NAMES. │
2390 ├────────────────────┼─────────────────────┼─────────────────────┤
2391 │MONGOC_URI_TLSDIS‐ │ tlsdisablecertifi‐ │ {true|false}, indi‐ │
2392 │ABLECERTIFICATERE‐ │ caterevocationcheck │ cates if revocation │
2393 │VOCATIONCHECK │ │ checking (CRL / │
2394 │ │ │ OCSP) should be │
2395 │ │ │ disabled. │
2396 ├────────────────────┼─────────────────────┼─────────────────────┤
2397 │MONGOC_URI_TLSDIS‐ │ tlsdisableocspend‐ │ {true|false}, indi‐ │
2398 │ABLEOCSPEND‐ │ pointcheck │ cates if OCSP re‐ │
2399 │POINTCHECK │ │ sponder endpoints │
2400 │ │ │ should not be re‐ │
2401 │ │ │ quested when an │
2402 │ │ │ OCSP response is │
2403 │ │ │ not stapled. │
2404 └────────────────────┴─────────────────────┴─────────────────────┘
2405
2406 Configuration with mongoc_ssl_opt_t
2407 Alternatively, the mongoc_ssl_opt_t struct may be used to configure TLS
2408 with mongoc_client_set_ssl_opts() or mongoc_client_pool_set_ssl_opts().
2409 Most of the configurable options can be set using the Connection String
2410 URI.
2411
2412 ┌───────────────────────┬──────────────────────────┐
2413 │mongoc_ssl_opt_t key │ URI key │
2414 ├───────────────────────┼──────────────────────────┤
2415 │pem_file │ tlsClientCertificateKey‐ │
2416 │ │ File │
2417 ├───────────────────────┼──────────────────────────┤
2418 │pem_pwd │ tlsClientCertificateKey‐ │
2419 │ │ Password │
2420 ├───────────────────────┼──────────────────────────┤
2421 │ca_file │ tlsCAFile │
2422 ├───────────────────────┼──────────────────────────┤
2423 │weak_cert_validation │ tlsAllowInvalidCertifi‐ │
2424 │ │ cates │
2425 ├───────────────────────┼──────────────────────────┤
2426 │allow_invalid_hostname │ tlsAllowInvalidHostnames │
2427 └───────────────────────┴──────────────────────────┘
2428
2429 The only exclusions are crl_file and ca_dir. Those may only be set with
2430 mongoc_ssl_opt_t.
2431
2432 Client Authentication
2433 When MongoDB is started with TLS enabled, it will by default require
2434 the client to provide a client certificate issued by a certificate au‐
2435 thority specified by --tlsCAFile, or an authority trusted by the native
2436 certificate store in use on the server.
2437
2438 To provide the client certificate, set the tlsCertificateKeyFile in the
2439 URI to a PEM armored certificate file.
2440
2441 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/");
2442 mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
2443 mongoc_uri_set_option_as_utf8 (uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, "/path/to/client-certificate.pem");
2444
2445 mongoc_client_t *client = mongoc_client_new_from_uri (uri);
2446
2447 Server Certificate Verification
2448 The MongoDB C Driver will automatically verify the validity of the
2449 server certificate, such as issued by configured Certificate Authority,
2450 hostname validation, and expiration.
2451
2452 To overwrite this behavior, it is possible to disable hostname valida‐
2453 tion, OCSP endpoint revocation checking, revocation checking entirely,
2454 and allow invalid certificates.
2455
2456 This behavior is controlled using the tlsAllowInvalidHostnames, tlsDis‐
2457 ableOCSPEndpointCheck, tlsDisableCertificateRevocationCheck, and tlsAl‐
2458 lowInvalidCertificates options respectively. By default, all are set to
2459 false.
2460
2461 It is not recommended to change these defaults as it exposes the client
2462 to Man In The Middle attacks (when tlsAllowInvalidHostnames is set),
2463 invalid certificates (when tlsAllowInvalidCertificates is set), or po‐
2464 tentially revoked certificates (when tlsDisableOCSPEndpointCheck or
2465 tlsDisableCertificateRevocationCheck are set).
2466
2467 Supported Libraries
2468 By default, libmongoc will attempt to find a supported TLS library and
2469 enable TLS support. This is controlled by the cmake flag ENABLE_SSL,
2470 which is set to AUTO by default. Valid values are:
2471
2472 • AUTO the default behavior. Link to the system's native TLS library,
2473 or attempt to find OpenSSL.
2474
2475 • DARWIN link to Secure Transport, the native TLS library on macOS.
2476
2477 • WINDOWS link to Secure Channel, the native TLS library on Windows.
2478
2479 • OPENSSL link to OpenSSL (libssl). An optional install path may be
2480 specified with OPENSSL_ROOT.
2481
2482 • LIBRESSL link to LibreSSL's libtls. (LibreSSL's compatible libssl may
2483 be linked to by setting OPENSSL).
2484
2485 • OFF disable TLS support.
2486
2487 OpenSSL
2488 The MongoDB C Driver uses OpenSSL, if available, on Linux and Unix
2489 platforms (besides macOS). Industry best practices and some regulations
2490 require the use of TLS 1.1 or newer, which requires at least OpenSSL
2491 1.0.1. Check your OpenSSL version like so:
2492
2493 $ openssl version
2494
2495 Ensure your system's OpenSSL is a recent version (at least 1.0.1), or
2496 install a recent version in a non-system path and build against it
2497 with:
2498
2499 cmake -DOPENSSL_ROOT_DIR=/absolute/path/to/openssl
2500
2501 When compiled against OpenSSL, the driver will attempt to load the sys‐
2502 tem default certificate store, as configured by the distribution. That
2503 can be overridden by setting the tlsCAFile URI option or with the
2504 fields ca_file and ca_dir in the mongoc_ssl_opt_t.
2505
2506 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is fully
2507 supported when using OpenSSL 1.0.1+ with the following notes:
2508
2509 • When a crl_file is set with mongoc_ssl_opt_t, and the crl_file re‐
2510 vokes the server's certificate, the certificate is considered revoked
2511 (even if the certificate has a valid stapled OCSP response)
2512
2513 LibreSSL / libtls
2514 The MongoDB C Driver supports LibreSSL through the use of OpenSSL com‐
2515 patibility checks when configured to compile against openssl. It also
2516 supports the new libtls library when configured to build against li‐
2517 bressl.
2518
2519 When compiled against the Windows native libraries, the crl_file option
2520 of a mongoc_ssl_opt_t is not supported, and will issue an error if
2521 used.
2522
2523 Setting tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevoca‐
2524 tionCheck has no effect.
2525
2526 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
2527 tially supported with the following notes:
2528
2529 • The Must-Staple extension (see RFC 7633) is ignored. Connection may
2530 continue if a Must-Staple certificate is presented with no stapled
2531 response (unless the client receives a revoked response from an OCSP
2532 responder).
2533
2534 • Connection will continue if a Must-Staple certificate is presented
2535 without a stapled response and the OCSP responder is down.
2536
2537 Native TLS Support on Windows (Secure Channel)
2538 The MongoDB C Driver supports the Windows native TLS library (Secure
2539 Channel, or SChannel), and its native crypto library (Cryptography API:
2540 Next Generation, or CNG).
2541
2542 When compiled against the Windows native libraries, the ca_dir option
2543 of a mongoc_ssl_opt_t is not supported, and will issue an error if
2544 used.
2545
2546 Encrypted PEM files (e.g., setting tlsCertificateKeyPassword) are also
2547 not supported, and will result in error when attempting to load them.
2548
2549 When tlsCAFile is set, the driver will only allow server certificates
2550 issued by the authority (or authorities) provided. When no tlsCAFile is
2551 set, the driver will look up the Certificate Authority using the System
2552 Local Machine Root certificate store to confirm the provided certifi‐
2553 cate.
2554
2555 When crl_file is set with mongoc_ssl_opt_t, the driver will import the
2556 revocation list to the System Local Machine Root certificate store.
2557
2558 Setting tlsDisableOCSPEndpointCheck has no effect.
2559
2560 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
2561 tially supported with the following notes:
2562
2563 • The Must-Staple extension (see RFC 7633) is ignored. Connection may
2564 continue if a Must-Staple certificate is presented with no stapled
2565 response (unless the client receives a revoked response from an OCSP
2566 responder).
2567
2568 • When a crl_file is set with mongoc_ssl_opt_t, and the crl_file re‐
2569 vokes the server's certificate, the OCSP response takes precedence.
2570 E.g. if the server presents a certificate with a valid stapled OCSP
2571 response, the certificate is considered valid even if the crl_file
2572 marks it as revoked.
2573
2574 • Connection will continue if a Must-Staple certificate is presented
2575 without a stapled response and the OCSP responder is down.
2576
2577 Native TLS Support on macOS / Darwin (Secure Transport)
2578 The MongoDB C Driver supports the Darwin (OS X, macOS, iOS, etc.) na‐
2579 tive TLS library (Secure Transport), and its native crypto library
2580 (Common Crypto, or CC).
2581
2582 When compiled against Secure Transport, the ca_dir and crl_file options
2583 of a mongoc_ssl_opt_t are not supported. An error is issued if either
2584 are used.
2585
2586 When tlsCAFile is set, the driver will only allow server certificates
2587 issued by the authority (or authorities) provided. When no tlsCAFile is
2588 set, the driver will use the Certificate Authorities in the currently
2589 unlocked keychains.
2590
2591 Setting tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevoca‐
2592 tionCheck has no effect.
2593
2594 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
2595 tially supported with the following notes.
2596
2597 • The Must-Staple extension (see RFC 7633) is ignored. Connection may
2598 continue if a Must-Staple certificate is presented with no stapled
2599 response (unless the client receives a revoked response from an OCSP
2600 responder).
2601
2602 • Connection will continue if a Must-Staple certificate is presented
2603 without a stapled response and the OCSP responder is down.
2604
2605 Common Tasks
2606 Drivers for some other languages provide helper functions to perform
2607 certain common tasks. In the C Driver we must explicitly build commands
2608 to send to the server.
2609
2610 Setup
2611 First we'll write some code to insert sample data:
2612
2613 doc-common-insert.c
2614
2615 /* Don't try to compile this file on its own. It's meant to be #included
2616 by example code */
2617
2618 /* Insert some sample data */
2619 bool
2620 insert_data (mongoc_collection_t *collection)
2621 {
2622 mongoc_bulk_operation_t *bulk;
2623 enum N { ndocs = 4 };
2624 bson_t *docs[ndocs];
2625 bson_error_t error;
2626 int i = 0;
2627 bool ret;
2628
2629 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2630
2631 docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
2632 docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
2633 docs[2] = BCON_NEW (
2634 "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
2635 docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
2636
2637 for (i = 0; i < ndocs; i++) {
2638 mongoc_bulk_operation_insert (bulk, docs[i]);
2639 bson_destroy (docs[i]);
2640 docs[i] = NULL;
2641 }
2642
2643 ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
2644
2645 if (!ret) {
2646 fprintf (stderr, "Error inserting data: %s\n", error.message);
2647 }
2648
2649 mongoc_bulk_operation_destroy (bulk);
2650 return ret;
2651 }
2652
2653 /* A helper which we'll use a lot later on */
2654 void
2655 print_res (const bson_t *reply)
2656 {
2657 char *str;
2658 BSON_ASSERT (reply);
2659 str = bson_as_canonical_extended_json (reply, NULL);
2660 printf ("%s\n", str);
2661 bson_free (str);
2662 }
2663
2664
2665 "explain" Command
2666 This is how to use the explain command in MongoDB 3.2+:
2667
2668 explain.c
2669
2670 bool
2671 explain (mongoc_collection_t *collection)
2672 {
2673 bson_t *command;
2674 bson_t reply;
2675 bson_error_t error;
2676 bool res;
2677
2678 command = BCON_NEW ("explain",
2679 "{",
2680 "find",
2681 BCON_UTF8 (COLLECTION_NAME),
2682 "filter",
2683 "{",
2684 "x",
2685 BCON_INT32 (1),
2686 "}",
2687 "}");
2688 res = mongoc_collection_command_simple (
2689 collection, command, NULL, &reply, &error);
2690 if (!res) {
2691 fprintf (stderr, "Error with explain: %s\n", error.message);
2692 goto cleanup;
2693 }
2694
2695 /* Do something with the reply */
2696 print_res (&reply);
2697
2698 cleanup:
2699 bson_destroy (&reply);
2700 bson_destroy (command);
2701 return res;
2702 }
2703
2704
2705 Running the Examples
2706 common-operations.c
2707
2708 /*
2709 * Copyright 2016 MongoDB, Inc.
2710 *
2711 * Licensed under the Apache License, Version 2.0 (the "License");
2712 * you may not use this file except in compliance with the License.
2713 * You may obtain a copy of the License at
2714 *
2715 * http://www.apache.org/licenses/LICENSE-2.0
2716 *
2717 * Unless required by applicable law or agreed to in writing, software
2718 * distributed under the License is distributed on an "AS IS" BASIS,
2719 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2720 * See the License for the specific language governing permissions and
2721 * limitations under the License.
2722 */
2723
2724
2725 #include <mongoc/mongoc.h>
2726 #include <stdio.h>
2727
2728
2729 const char *COLLECTION_NAME = "things";
2730
2731 #include "../doc-common-insert.c"
2732 #include "explain.c"
2733
2734
2735 int
2736 main (int argc, char *argv[])
2737 {
2738 mongoc_database_t *database = NULL;
2739 mongoc_client_t *client = NULL;
2740 mongoc_collection_t *collection = NULL;
2741 mongoc_uri_t *uri = NULL;
2742 bson_error_t error;
2743 char *host_and_port;
2744 int res = 0;
2745
2746 if (argc < 2 || argc > 3) {
2747 fprintf (stderr,
2748 "usage: %s MONGOD-1-CONNECTION-STRING "
2749 "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
2750 argv[0]);
2751 fprintf (stderr,
2752 "MONGOD-1-CONNECTION-STRING can be "
2753 "of the following forms:\n");
2754 fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
2755 fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
2756 fprintf (stderr,
2757 "mongodb://user:pass@localhost:27017\t"
2758 "local machine on port 27017, and authenticate with username "
2759 "user and password pass\n");
2760 return EXIT_FAILURE;
2761 }
2762
2763 mongoc_init ();
2764
2765 if (strncmp (argv[1], "mongodb://", 10) == 0) {
2766 host_and_port = bson_strdup (argv[1]);
2767 } else {
2768 host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
2769 }
2770
2771 uri = mongoc_uri_new_with_error (host_and_port, &error);
2772 if (!uri) {
2773 fprintf (stderr,
2774 "failed to parse URI: %s\n"
2775 "error message: %s\n",
2776 host_and_port,
2777 error.message);
2778 res = EXIT_FAILURE;
2779 goto cleanup;
2780 }
2781
2782 client = mongoc_client_new_from_uri (uri);
2783 if (!client) {
2784 res = EXIT_FAILURE;
2785 goto cleanup;
2786 }
2787
2788 mongoc_client_set_error_api (client, 2);
2789 database = mongoc_client_get_database (client, "test");
2790 collection = mongoc_database_get_collection (database, COLLECTION_NAME);
2791
2792 printf ("Inserting data\n");
2793 if (!insert_data (collection)) {
2794 res = EXIT_FAILURE;
2795 goto cleanup;
2796 }
2797
2798 printf ("explain\n");
2799 if (!explain (collection)) {
2800 res = EXIT_FAILURE;
2801 goto cleanup;
2802 }
2803
2804 cleanup:
2805 if (collection) {
2806 mongoc_collection_destroy (collection);
2807 }
2808
2809 if (database) {
2810 mongoc_database_destroy (database);
2811 }
2812
2813 if (client) {
2814 mongoc_client_destroy (client);
2815 }
2816
2817 if (uri) {
2818 mongoc_uri_destroy (uri);
2819 }
2820
2821 bson_free (host_and_port);
2822 mongoc_cleanup ();
2823 return res;
2824 }
2825
2826
2827 First launch two separate instances of mongod (must be done from sepa‐
2828 rate shells):
2829
2830 $ mongod
2831
2832 $ mkdir /tmp/db2
2833 $ mongod --dbpath /tmp/db2 --port 27018 # second instance
2834
2835 Now compile and run the example program:
2836
2837 $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
2838 Inserting data
2839 explain
2840 {
2841 "executionStats" : {
2842 "allPlansExecution" : [],
2843 "executionStages" : {
2844 "advanced" : 19,
2845 "direction" : "forward" ,
2846 "docsExamined" : 76,
2847 "executionTimeMillisEstimate" : 0,
2848 "filter" : {
2849 "x" : {
2850 "$eq" : 1
2851 }
2852 },
2853 "invalidates" : 0,
2854 "isEOF" : 1,
2855 "nReturned" : 19,
2856 "needTime" : 58,
2857 "needYield" : 0,
2858 "restoreState" : 0,
2859 "saveState" : 0,
2860 "stage" : "COLLSCAN" ,
2861 "works" : 78
2862 },
2863 "executionSuccess" : true,
2864 "executionTimeMillis" : 0,
2865 "nReturned" : 19,
2866 "totalDocsExamined" : 76,
2867 "totalKeysExamined" : 0
2868 },
2869 "ok" : 1,
2870 "queryPlanner" : {
2871 "indexFilterSet" : false,
2872 "namespace" : "test.things",
2873 "parsedQuery" : {
2874 "x" : {
2875 "$eq" : 1
2876 }
2877 },
2878 "plannerVersion" : 1,
2879 "rejectedPlans" : [],
2880 "winningPlan" : {
2881 "direction" : "forward" ,
2882 "filter" : {
2883 "x" : {
2884 "$eq" : 1
2885 }
2886 },
2887 "stage" : "COLLSCAN"
2888 }
2889 },
2890 "serverInfo" : {
2891 "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
2892 "host" : "MacBook-Pro-57.local",
2893 "port" : 27017,
2894 "version" : "3.2.6"
2895 }
2896 }
2897
2898 Advanced Connections
2899 The following guide contains information specific to certain types of
2900 MongoDB configurations.
2901
2902 For an example of connecting to a simple standalone server, see the
2903 Tutorial. To establish a connection with authentication options en‐
2904 abled, see the Authentication page. To see an example of a connection
2905 with data compression, see the Data Compression page.
2906
2907 Connecting to a Replica Set
2908 Connecting to a replica set is much like connecting to a standalone
2909 MongoDB server. Simply specify the replica set name using the ?repli‐
2910 caSet=myreplset URI option.
2911
2912 #include <bson/bson.h>
2913 #include <mongoc/mongoc.h>
2914
2915 int
2916 main (int argc, char *argv[])
2917 {
2918 mongoc_client_t *client;
2919
2920 mongoc_init ();
2921
2922 /* Create our MongoDB Client */
2923 client = mongoc_client_new (
2924 "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");
2925
2926 /* Do some work */
2927 /* TODO */
2928
2929 /* Clean up */
2930 mongoc_client_destroy (client);
2931 mongoc_cleanup ();
2932
2933 return 0;
2934 }
2935
2936 TIP:
2937 Multiple hostnames can be specified in the MongoDB connection string
2938 URI, with a comma separating hosts in the seed list.
2939
2940 It is recommended to use a seed list of members of the replica set
2941 to allow the driver to connect to any node.
2942
2943 Connecting to a Sharded Cluster
2944 To connect to a sharded cluster, specify the mongos nodes the client
2945 should connect to. The C Driver will automatically detect that it has
2946 connected to a mongos sharding server.
2947
2948 If more than one hostname is specified, a seed list will be created to
2949 attempt failover between the mongos instances.
2950
2951 WARNING:
2952 Specifying the replicaSet parameter when connecting to a mongos
2953 sharding server is invalid.
2954
2955 #include <bson/bson.h>
2956 #include <mongoc/mongoc.h>
2957
2958 int
2959 main (int argc, char *argv[])
2960 {
2961 mongoc_client_t *client;
2962
2963 mongoc_init ();
2964
2965 /* Create our MongoDB Client */
2966 client = mongoc_client_new ("mongodb://myshard01:27017/");
2967
2968 /* Do something with client ... */
2969
2970 /* Free the client */
2971 mongoc_client_destroy (client);
2972
2973 mongoc_cleanup ();
2974
2975 return 0;
2976 }
2977
2978 Connecting to an IPv6 Address
2979 The MongoDB C Driver will automatically resolve IPv6 addresses from
2980 host names. However, to specify an IPv6 address directly, wrap the ad‐
2981 dress in [].
2982
2983 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");
2984
2985 Connecting with IPv4 and IPv6
2986 If connecting to a hostname that has both IPv4 and IPv6 DNS records,
2987 the behavior follows RFC-6555. A connection to the IPv6 address is at‐
2988 tempted first. If IPv6 fails, then a connection is attempted to the
2989 IPv4 address. If the connection attempt to IPv6 does not complete
2990 within 250ms, then IPv4 is tried in parallel. Whichever succeeds con‐
2991 nection first cancels the other. The successful DNS result is cached
2992 for 10 minutes.
2993
2994 As a consequence, attempts to connect to a mongod only listening on
2995 IPv4 may be delayed if there are both A (IPv4) and AAAA (IPv6) DNS
2996 records associated with the host.
2997
2998 To avoid a delay, configure hostnames to match the MongoDB configura‐
2999 tion. That is, only create an A record if the mongod is only listening
3000 on IPv4.
3001
3002 Connecting to a UNIX Domain Socket
3003 On UNIX-like systems, the C Driver can connect directly to a MongoDB
3004 server using a UNIX domain socket. Pass the URL-encoded path to the
3005 socket, which must be suffixed with .sock. For example, to connect to a
3006 domain socket at /tmp/mongodb-27017.sock:
3007
3008 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");
3009
3010 Include username and password like so:
3011
3012 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");
3013
3014 Connecting to a server over TLS
3015 These are instructions for configuring TLS/SSL connections.
3016
3017 To run a server locally (on port 27017, for example):
3018
3019 $ mongod --port 27017 --tlsMode requireTLS --tlsCertificateKeyFile server.pem --tlsCAFile ca.pem
3020
3021 Add /?tls=true to the end of a client URI.
3022
3023 mongoc_client_t *client = NULL;
3024 client = mongoc_client_new ("mongodb://localhost:27017/?tls=true");
3025
3026 MongoDB requires client certificates by default, unless the --tlsAllow‐
3027 ConnectionsWithoutCertificates is provided. The C Driver can be config‐
3028 ured to present a client certificate using the URI option tlsCertifi‐
3029 cateKeyFile, which may be referenced through the constant MON‐
3030 GOC_URI_TLSCERTIFICATEKEYFILE.
3031
3032 mongoc_client_t *client = NULL;
3033 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/?tls=true");
3034 mongoc_uri_set_option_as_utf8 (uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, "client.pem");
3035
3036 client = mongoc_client_new_from_uri (uri);
3037
3038 The client certificate provided by tlsCertificateKeyFile must be issued
3039 by one of the server trusted Certificate Authorities listed in
3040 --tlsCAFile, or issued by a CA in the native certificate store on the
3041 server when omitted.
3042
3043 See Configuring TLS for more information on the various TLS related op‐
3044 tions.
3045
3046 Compressing data to and from MongoDB
3047 This content has been relocated to the Data Compression page.
3048
3049 Additional Connection Options
3050 The full list of connection options can be found in the mongoc_uri_t
3051 docs.
3052
3053 Certain socket/connection related options are not configurable:
3054
3055 ┌──────────────┬─────────────────────┬─────────────────────┐
3056 │Option │ Description │ Value │
3057 ├──────────────┼─────────────────────┼─────────────────────┤
3058 │SO_KEEPALIVE │ TCP Keep Alive │ Enabled │
3059 ├──────────────┼─────────────────────┼─────────────────────┤
3060 │TCP_KEEPIDLE │ How long a connec‐ │ 120 seconds │
3061 │ │ tion needs to re‐ │ │
3062 │ │ main idle before │ │
3063 │ │ TCP starts sending │ │
3064 │ │ keepalive probes │ │
3065 ├──────────────┼─────────────────────┼─────────────────────┤
3066 │TCP_KEEPINTVL │ The time in seconds │ 10 seconds │
3067 │ │ between TCP probes │ │
3068 ├──────────────┼─────────────────────┼─────────────────────┤
3069 │TCP_KEEPCNT │ How many probes to │ 9 probes │
3070 │ │ send, without ac‐ │ │
3071 │ │ knowledgement, be‐ │ │
3072 │ │ fore dropping the │ │
3073 │ │ connection │ │
3074 ├──────────────┼─────────────────────┼─────────────────────┤
3075 │TCP_NODELAY │ Send packets as │ Enabled (no buffer‐ │
3076 │ │ soon as possible or │ ing) │
3077 │ │ buffer small pack‐ │ │
3078 │ │ ets (Nagle algo‐ │ │
3079 │ │ rithm) │ │
3080 └──────────────┴─────────────────────┴─────────────────────┘
3081
3082 Connection Pooling
3083 The MongoDB C driver has two connection modes: single-threaded and
3084 pooled. Single-threaded mode is optimized for embedding the driver
3085 within languages like PHP. Multi-threaded programs should use pooled
3086 mode: this mode minimizes the total connection count, and in pooled
3087 mode background threads monitor the MongoDB server topology, so the
3088 program need not block to scan it.
3089
3090 Single Mode
3091 In single mode, your program creates a mongoc_client_t directly:
3092
3093 mongoc_client_t *client = mongoc_client_new (
3094 "mongodb://hostA,hostB/?replicaSet=my_rs");
3095
3096 The client connects on demand when your program first uses it for a
3097 MongoDB operation. Using a non-blocking socket per server, it begins a
3098 check on each server concurrently, and uses the asynchronous poll or
3099 select function to receive events from the sockets, until all have re‐
3100 sponded or timed out. Put another way, in single-threaded mode the C
3101 Driver fans out to begin all checks concurrently, then fans in once all
3102 checks have completed or timed out. Once the scan completes, the client
3103 executes your program's operation and returns.
3104
3105 In single mode, the client re-scans the server topology roughly once
3106 per minute. If more than a minute has elapsed since the previous scan,
3107 the next operation on the client will block while the client completes
3108 its scan. This interval is configurable with heartbeatFrequencyMS in
3109 the connection string. (See mongoc_uri_t.)
3110
3111 A single client opens one connection per server in your topology: these
3112 connections are used both for scanning the topology and performing nor‐
3113 mal operations.
3114
3115 Pooled Mode
3116 To activate pooled mode, create a mongoc_client_pool_t:
3117
3118 mongoc_uri_t *uri = mongoc_uri_new (
3119 "mongodb://hostA,hostB/?replicaSet=my_rs");
3120
3121 mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
3122
3123 When your program first calls mongoc_client_pool_pop(), the pool
3124 launches monitoring threads in the background. Monitoring threads inde‐
3125 pendently connect to all servers in the connection string. As monitor‐
3126 ing threads receive hello responses from the servers, they update the
3127 shared view of the server topology. Additional monitoring threads and
3128 connections are created as new servers are discovered. Monitoring
3129 threads are terminated when servers are removed from the shared view of
3130 the server topology.
3131
3132 Each thread that executes MongoDB operations must check out a client
3133 from the pool:
3134
3135 mongoc_client_t *client = mongoc_client_pool_pop (pool);
3136
3137 /* use the client for operations ... */
3138
3139 mongoc_client_pool_push (pool, client);
3140
3141 The mongoc_client_t object is not thread-safe, only the
3142 mongoc_client_pool_t is.
3143
3144 When the driver is in pooled mode, your program's operations are un‐
3145 blocked as soon as monitoring discovers a usable server. For example,
3146 if a thread in your program is waiting to execute an "insert" on the
3147 primary, it is unblocked as soon as the primary is discovered, rather
3148 than waiting for all secondaries to be checked as well.
3149
3150 The pool opens one connection per server for monitoring, and each
3151 client opens its own connection to each server it uses for application
3152 operations. Background monitoring threads re-scan servers independently
3153 roughly every 10 seconds. This interval is configurable with heartbeat‐
3154 FrequencyMS in the connection string. (See mongoc_uri_t.)
3155
3156 The connection string can also specify waitQueueTimeoutMS to limit the
3157 time that mongoc_client_pool_pop() will wait for a client from the
3158 pool. (See mongoc_uri_t.) If waitQueueTimeoutMS is specified, then it
3159 is necessary to confirm that a client was actually returned:
3160
3161 mongoc_uri_t *uri = mongoc_uri_new (
3162 "mongodb://hostA,hostB/?replicaSet=my_rs&waitQueueTimeoutMS=1000");
3163
3164 mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
3165
3166 mongoc_client_t *client = mongoc_client_pool_pop (pool);
3167
3168 if (client) {
3169 /* use the client for operations ... */
3170
3171 mongoc_client_pool_push (pool, client);
3172 } else {
3173 /* take appropriate action for a timeout */
3174 }
3175
3176 See Connection Pool Options to configure pool size and behavior, and
3177 see mongoc_client_pool_t for an extended example of a multi-threaded
3178 program that uses the driver in pooled mode.
3179
3180 Data Compression
3181 The following guide explains how data compression support works between
3182 the MongoDB server and client. It also shows an example of how to con‐
3183 nect to a server with data compression.
3184
3185 Compressing data to and from MongoDB
3186 MongoDB 3.4 added Snappy compression support, while zlib compression
3187 was added in 3.6, and zstd compression in 4.2. To enable compression
3188 support the client must be configured with which compressors to use:
3189
3190 mongoc_client_t *client = NULL;
3191 client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib,zstd");
3192
3193 The compressors option specifies the priority order of compressors the
3194 client wants to use. Messages are compressed if the client and server
3195 share any compressors in common.
3196
3197 Note that the compressor used by the server might not be the same com‐
3198 pressor as the client used. For example, if the client uses the con‐
3199 nection string compressors=zlib,snappy the client will use zlib com‐
3200 pression to send data (if possible), but the server might still reply
3201 using snappy, depending on how the server was configured.
3202
3203 The driver must be built with zlib and/or snappy and/or zstd support to
3204 enable compression support, any unknown (or not compiled in) compressor
3205 value will be ignored.
3206
3207 Cursors
3208 Handling Cursor Failures
3209 Cursors exist on a MongoDB server. However, the mongoc_cursor_t struc‐
3210 ture gives the local process a handle to the cursor. It is possible for
3211 errors to occur on the server while iterating a cursor on the client.
3212 Even a network partition may occur. This means that applications should
3213 be robust in handling cursor failures.
3214
3215 While iterating cursors, you should check to see if an error has oc‐
3216 curred. See the following example for how to robustly check for errors.
3217
3218 static void
3219 print_all_documents (mongoc_collection_t *collection)
3220 {
3221 mongoc_cursor_t *cursor;
3222 const bson_t *doc;
3223 bson_error_t error;
3224 bson_t query = BSON_INITIALIZER;
3225 char *str;
3226
3227 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
3228
3229 while (mongoc_cursor_next (cursor, &doc)) {
3230 str = bson_as_canonical_extended_json (doc, NULL);
3231 printf ("%s\n", str);
3232 bson_free (str);
3233 }
3234
3235 if (mongoc_cursor_error (cursor, &error)) {
3236 fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
3237 }
3238
3239 mongoc_cursor_destroy (cursor);
3240 }
3241
3242 Destroying Server-Side Cursors
3243 The MongoDB C driver will automatically destroy a server-side cursor
3244 when mongoc_cursor_destroy() is called. Failure to call this function
3245 when done with a cursor will leak memory client side as well as consume
3246 extra memory server side. If the cursor was configured to never time‐
3247 out, it will become a memory leak on the server.
3248
3249 Tailable Cursors
3250 Tailable cursors are cursors that remain open even after they've re‐
3251 turned a final result. This way, if more documents are added to a col‐
3252 lection (i.e., to the cursor's result set), then you can continue to
3253 call mongoc_cursor_next() to retrieve those additional results.
3254
3255 Here's a complete test case that demonstrates the use of tailable cur‐
3256 sors.
3257
3258 NOTE:
3259 Tailable cursors are for capped collections only.
3260
3261 An example to tail the oplog from a replica set.
3262
3263 mongoc-tail.c
3264
3265 #include <bson/bson.h>
3266 #include <mongoc/mongoc.h>
3267 #include <stdio.h>
3268 #include <stdlib.h>
3269
3270 #ifdef _WIN32
3271 #define sleep(_n) Sleep ((_n) *1000)
3272 #endif
3273
3274
3275 static void
3276 print_bson (const bson_t *b)
3277 {
3278 char *str;
3279
3280 str = bson_as_canonical_extended_json (b, NULL);
3281 fprintf (stdout, "%s\n", str);
3282 bson_free (str);
3283 }
3284
3285
3286 static mongoc_cursor_t *
3287 query_collection (mongoc_collection_t *collection, uint32_t last_time)
3288 {
3289 mongoc_cursor_t *cursor;
3290 bson_t query;
3291 bson_t gt;
3292 bson_t opts;
3293
3294 BSON_ASSERT (collection);
3295
3296 bson_init (&query);
3297 BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", >);
3298 BSON_APPEND_TIMESTAMP (>, "$gt", last_time, 0);
3299 bson_append_document_end (&query, >);
3300
3301 bson_init (&opts);
3302 BSON_APPEND_BOOL (&opts, "tailable", true);
3303 BSON_APPEND_BOOL (&opts, "awaitData", true);
3304
3305 cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
3306
3307 bson_destroy (&query);
3308 bson_destroy (&opts);
3309
3310 return cursor;
3311 }
3312
3313
3314 static void
3315 tail_collection (mongoc_collection_t *collection)
3316 {
3317 mongoc_cursor_t *cursor;
3318 uint32_t last_time;
3319 const bson_t *doc;
3320 bson_error_t error;
3321 bson_iter_t iter;
3322
3323 BSON_ASSERT (collection);
3324
3325 last_time = (uint32_t) time (NULL);
3326
3327 while (true) {
3328 cursor = query_collection (collection, last_time);
3329 while (!mongoc_cursor_error (cursor, &error) &&
3330 mongoc_cursor_more (cursor)) {
3331 if (mongoc_cursor_next (cursor, &doc)) {
3332 if (bson_iter_init_find (&iter, doc, "ts") &&
3333 BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
3334 bson_iter_timestamp (&iter, &last_time, NULL);
3335 }
3336 print_bson (doc);
3337 }
3338 }
3339 if (mongoc_cursor_error (cursor, &error)) {
3340 if (error.domain == MONGOC_ERROR_SERVER) {
3341 fprintf (stderr, "%s\n", error.message);
3342 exit (1);
3343 }
3344 }
3345
3346 mongoc_cursor_destroy (cursor);
3347 sleep (1);
3348 }
3349 }
3350
3351
3352 int
3353 main (int argc, char *argv[])
3354 {
3355 mongoc_collection_t *collection;
3356 mongoc_client_t *client;
3357 mongoc_uri_t *uri;
3358 bson_error_t error;
3359
3360 if (argc != 2) {
3361 fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
3362 return EXIT_FAILURE;
3363 }
3364
3365 mongoc_init ();
3366
3367 uri = mongoc_uri_new_with_error (argv[1], &error);
3368 if (!uri) {
3369 fprintf (stderr,
3370 "failed to parse URI: %s\n"
3371 "error message: %s\n",
3372 argv[1],
3373 error.message);
3374 return EXIT_FAILURE;
3375 }
3376
3377 client = mongoc_client_new_from_uri (uri);
3378 if (!client) {
3379 return EXIT_FAILURE;
3380 }
3381
3382 mongoc_client_set_error_api (client, 2);
3383
3384 collection = mongoc_client_get_collection (client, "local", "oplog.rs");
3385
3386 tail_collection (collection);
3387
3388 mongoc_collection_destroy (collection);
3389 mongoc_uri_destroy (uri);
3390 mongoc_client_destroy (client);
3391
3392 return EXIT_SUCCESS;
3393 }
3394
3395
3396 Let's compile and run this example against a replica set to see updates
3397 as they are made.
3398
3399 $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
3400 $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
3401 {
3402 "h" : -8458503739429355503,
3403 "ns" : "test.test",
3404 "o" : {
3405 "_id" : {
3406 "$oid" : "5372ab0a25164be923d10d50"
3407 }
3408 },
3409 "op" : "i",
3410 "ts" : {
3411 "$timestamp" : {
3412 "i" : 1,
3413 "t" : 1400023818
3414 }
3415 },
3416 "v" : 2
3417 }
3418
3419 The line of output is a sample from performing db.test.insert({}) from
3420 the mongo shell on the replica set.
3421
3422 SEE ALSO:
3423 mongoc_cursor_set_max_await_time_ms().
3424
3425
3426 Bulk Write Operations
3427 This tutorial explains how to take advantage of MongoDB C driver bulk
3428 write operation features. Executing write operations in batches reduces
3429 the number of network round trips, increasing write throughput.
3430
3431 Bulk Insert
3432 First we need to fetch a bulk operation handle from the
3433 mongoc_collection_t.
3434
3435 mongoc_bulk_operation_t *bulk =
3436 mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3437
3438 We can now start inserting documents to the bulk operation. These will
3439 be buffered until we execute the operation.
3440
3441 The bulk operation will coalesce insertions as a single batch for each
3442 consecutive call to mongoc_bulk_operation_insert(). This creates a
3443 pipelined effect when possible.
3444
3445 To execute the bulk operation and receive the result we call
3446 mongoc_bulk_operation_execute().
3447
3448 bulk1.c
3449
3450 #include <assert.h>
3451 #include <mongoc/mongoc.h>
3452 #include <stdio.h>
3453
3454 static void
3455 bulk1 (mongoc_collection_t *collection)
3456 {
3457 mongoc_bulk_operation_t *bulk;
3458 bson_error_t error;
3459 bson_t *doc;
3460 bson_t reply;
3461 char *str;
3462 bool ret;
3463 int i;
3464
3465 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3466
3467 for (i = 0; i < 10000; i++) {
3468 doc = BCON_NEW ("i", BCON_INT32 (i));
3469 mongoc_bulk_operation_insert (bulk, doc);
3470 bson_destroy (doc);
3471 }
3472
3473 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3474
3475 str = bson_as_canonical_extended_json (&reply, NULL);
3476 printf ("%s\n", str);
3477 bson_free (str);
3478
3479 if (!ret) {
3480 fprintf (stderr, "Error: %s\n", error.message);
3481 }
3482
3483 bson_destroy (&reply);
3484 mongoc_bulk_operation_destroy (bulk);
3485 }
3486
3487 int
3488 main (void)
3489 {
3490 mongoc_client_t *client;
3491 mongoc_collection_t *collection;
3492 const char *uri_string = "mongodb://localhost/?appname=bulk1-example";
3493 mongoc_uri_t *uri;
3494 bson_error_t error;
3495
3496 mongoc_init ();
3497
3498 uri = mongoc_uri_new_with_error (uri_string, &error);
3499 if (!uri) {
3500 fprintf (stderr,
3501 "failed to parse URI: %s\n"
3502 "error message: %s\n",
3503 uri_string,
3504 error.message);
3505 return EXIT_FAILURE;
3506 }
3507
3508 client = mongoc_client_new_from_uri (uri);
3509 if (!client) {
3510 return EXIT_FAILURE;
3511 }
3512
3513 mongoc_client_set_error_api (client, 2);
3514 collection = mongoc_client_get_collection (client, "test", "test");
3515
3516 bulk1 (collection);
3517
3518 mongoc_uri_destroy (uri);
3519 mongoc_collection_destroy (collection);
3520 mongoc_client_destroy (client);
3521
3522 mongoc_cleanup ();
3523
3524 return EXIT_SUCCESS;
3525 }
3526
3527
3528 Example reply document:
3529
3530 {"nInserted" : 10000,
3531 "nMatched" : 0,
3532 "nModified" : 0,
3533 "nRemoved" : 0,
3534 "nUpserted" : 0,
3535 "writeErrors" : []
3536 "writeConcernErrors" : [] }
3537
3538 Mixed Bulk Write Operations
3539 MongoDB C driver also supports executing mixed bulk write operations. A
3540 batch of insert, update, and remove operations can be executed together
3541 using the bulk write operations API.
3542
3543 Ordered Bulk Write Operations
3544 Ordered bulk write operations are batched and sent to the server in the
3545 order provided for serial execution. The reply document describes the
3546 type and count of operations performed.
3547
3548 bulk2.c
3549
3550 #include <assert.h>
3551 #include <mongoc/mongoc.h>
3552 #include <stdio.h>
3553
3554 static void
3555 bulk2 (mongoc_collection_t *collection)
3556 {
3557 mongoc_bulk_operation_t *bulk;
3558 bson_error_t error;
3559 bson_t *query;
3560 bson_t *doc;
3561 bson_t *opts;
3562 bson_t reply;
3563 char *str;
3564 bool ret;
3565 int i;
3566
3567 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3568
3569 /* Remove everything */
3570 query = bson_new ();
3571 mongoc_bulk_operation_remove (bulk, query);
3572 bson_destroy (query);
3573
3574 /* Add a few documents */
3575 for (i = 1; i < 4; i++) {
3576 doc = BCON_NEW ("_id", BCON_INT32 (i));
3577 mongoc_bulk_operation_insert (bulk, doc);
3578 bson_destroy (doc);
3579 }
3580
3581 /* {_id: 1} => {$set: {foo: "bar"}} */
3582 query = BCON_NEW ("_id", BCON_INT32 (1));
3583 doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
3584 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
3585 bson_destroy (query);
3586 bson_destroy (doc);
3587
3588 /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
3589 opts = BCON_NEW ("upsert", BCON_BOOL (true));
3590 query = BCON_NEW ("_id", BCON_INT32 (4));
3591 doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
3592 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
3593 bson_destroy (query);
3594 bson_destroy (doc);
3595 bson_destroy (opts);
3596
3597 /* replace {j:1} with {j:2} */
3598 query = BCON_NEW ("j", BCON_INT32 (1));
3599 doc = BCON_NEW ("j", BCON_INT32 (2));
3600 mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
3601 bson_destroy (query);
3602 bson_destroy (doc);
3603
3604 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3605
3606 str = bson_as_canonical_extended_json (&reply, NULL);
3607 printf ("%s\n", str);
3608 bson_free (str);
3609
3610 if (!ret) {
3611 printf ("Error: %s\n", error.message);
3612 }
3613
3614 bson_destroy (&reply);
3615 mongoc_bulk_operation_destroy (bulk);
3616 }
3617
3618 int
3619 main (void)
3620 {
3621 mongoc_client_t *client;
3622 mongoc_collection_t *collection;
3623 const char *uri_string = "mongodb://localhost/?appname=bulk2-example";
3624 mongoc_uri_t *uri;
3625 bson_error_t error;
3626
3627 mongoc_init ();
3628
3629 uri = mongoc_uri_new_with_error (uri_string, &error);
3630 if (!uri) {
3631 fprintf (stderr,
3632 "failed to parse URI: %s\n"
3633 "error message: %s\n",
3634 uri_string,
3635 error.message);
3636 return EXIT_FAILURE;
3637 }
3638
3639 client = mongoc_client_new_from_uri (uri);
3640 if (!client) {
3641 return EXIT_FAILURE;
3642 }
3643
3644 mongoc_client_set_error_api (client, 2);
3645 collection = mongoc_client_get_collection (client, "test", "test");
3646
3647 bulk2 (collection);
3648
3649 mongoc_uri_destroy (uri);
3650 mongoc_collection_destroy (collection);
3651 mongoc_client_destroy (client);
3652
3653 mongoc_cleanup ();
3654
3655 return EXIT_SUCCESS;
3656 }
3657
3658
3659 Example reply document:
3660
3661 { "nInserted" : 3,
3662 "nMatched" : 2,
3663 "nModified" : 2,
3664 "nRemoved" : 10000,
3665 "nUpserted" : 1,
3666 "upserted" : [{"index" : 5, "_id" : 4}],
3667 "writeErrors" : []
3668 "writeConcernErrors" : [] }
3669
3670 The index field in the upserted array is the 0-based index of the up‐
3671 sert operation; in this example, the sixth operation of the overall
3672 bulk operation was an upsert, so its index is 5.
3673
3674 Unordered Bulk Write Operations
3675 Unordered bulk write operations are batched and sent to the server in
3676 arbitrary order where they may be executed in parallel. Any errors that
3677 occur are reported after all operations are attempted.
3678
3679 In the next example the first and third operations fail due to the
3680 unique constraint on _id. Since we are doing unordered execution the
3681 second and fourth operations succeed.
3682
3683 bulk3.c
3684
3685 #include <assert.h>
3686 #include <mongoc/mongoc.h>
3687 #include <stdio.h>
3688
3689 static void
3690 bulk3 (mongoc_collection_t *collection)
3691 {
3692 bson_t opts = BSON_INITIALIZER;
3693 mongoc_bulk_operation_t *bulk;
3694 bson_error_t error;
3695 bson_t *query;
3696 bson_t *doc;
3697 bson_t reply;
3698 char *str;
3699 bool ret;
3700
3701 /* false indicates unordered */
3702 BSON_APPEND_BOOL (&opts, "ordered", false);
3703 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3704 bson_destroy (&opts);
3705
3706 /* Add a document */
3707 doc = BCON_NEW ("_id", BCON_INT32 (1));
3708 mongoc_bulk_operation_insert (bulk, doc);
3709 bson_destroy (doc);
3710
3711 /* remove {_id: 2} */
3712 query = BCON_NEW ("_id", BCON_INT32 (2));
3713 mongoc_bulk_operation_remove_one (bulk, query);
3714 bson_destroy (query);
3715
3716 /* insert {_id: 3} */
3717 doc = BCON_NEW ("_id", BCON_INT32 (3));
3718 mongoc_bulk_operation_insert (bulk, doc);
3719 bson_destroy (doc);
3720
3721 /* replace {_id:4} {'i': 1} */
3722 query = BCON_NEW ("_id", BCON_INT32 (4));
3723 doc = BCON_NEW ("i", BCON_INT32 (1));
3724 mongoc_bulk_operation_replace_one (bulk, query, doc, false);
3725 bson_destroy (query);
3726 bson_destroy (doc);
3727
3728 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3729
3730 str = bson_as_canonical_extended_json (&reply, NULL);
3731 printf ("%s\n", str);
3732 bson_free (str);
3733
3734 if (!ret) {
3735 printf ("Error: %s\n", error.message);
3736 }
3737
3738 bson_destroy (&reply);
3739 mongoc_bulk_operation_destroy (bulk);
3740 bson_destroy (&opts);
3741 }
3742
3743 int
3744 main (void)
3745 {
3746 mongoc_client_t *client;
3747 mongoc_collection_t *collection;
3748 const char *uri_string = "mongodb://localhost/?appname=bulk3-example";
3749 mongoc_uri_t *uri;
3750 bson_error_t error;
3751
3752 mongoc_init ();
3753
3754 uri = mongoc_uri_new_with_error (uri_string, &error);
3755 if (!uri) {
3756 fprintf (stderr,
3757 "failed to parse URI: %s\n"
3758 "error message: %s\n",
3759 uri_string,
3760 error.message);
3761 return EXIT_FAILURE;
3762 }
3763
3764 client = mongoc_client_new_from_uri (uri);
3765 if (!client) {
3766 return EXIT_FAILURE;
3767 }
3768
3769 mongoc_client_set_error_api (client, 2);
3770 collection = mongoc_client_get_collection (client, "test", "test");
3771
3772 bulk3 (collection);
3773
3774 mongoc_uri_destroy (uri);
3775 mongoc_collection_destroy (collection);
3776 mongoc_client_destroy (client);
3777
3778 mongoc_cleanup ();
3779
3780 return EXIT_SUCCESS;
3781 }
3782
3783
3784 Example reply document:
3785
3786 { "nInserted" : 0,
3787 "nMatched" : 1,
3788 "nModified" : 1,
3789 "nRemoved" : 1,
3790 "nUpserted" : 0,
3791 "writeErrors" : [
3792 { "index" : 0,
3793 "code" : 11000,
3794 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
3795 { "index" : 2,
3796 "code" : 11000,
3797 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
3798 "writeConcernErrors" : [] }
3799
3800 Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }
3801
3802 The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.
3803
3804 Bulk Operation Bypassing Document Validation
3805 This feature is only available when using MongoDB 3.2 and later.
3806
3807 By default bulk operations are validated against the schema, if any is
3808 defined. In certain cases however it may be necessary to bypass the
3809 document validation.
3810
3811 bulk5.c
3812
3813 #include <assert.h>
3814 #include <mongoc/mongoc.h>
3815 #include <stdio.h>
3816
3817 static void
3818 bulk5_fail (mongoc_collection_t *collection)
3819 {
3820 mongoc_bulk_operation_t *bulk;
3821 bson_error_t error;
3822 bson_t *doc;
3823 bson_t reply;
3824 char *str;
3825 bool ret;
3826
3827 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3828
3829 /* Two inserts */
3830 doc = BCON_NEW ("_id", BCON_INT32 (31));
3831 mongoc_bulk_operation_insert (bulk, doc);
3832 bson_destroy (doc);
3833
3834 doc = BCON_NEW ("_id", BCON_INT32 (32));
3835 mongoc_bulk_operation_insert (bulk, doc);
3836 bson_destroy (doc);
3837
3838 /* The above documents do not comply to the schema validation rules
3839 * we created previously, so this will result in an error */
3840 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3841
3842 str = bson_as_canonical_extended_json (&reply, NULL);
3843 printf ("%s\n", str);
3844 bson_free (str);
3845
3846 if (!ret) {
3847 printf ("Error: %s\n", error.message);
3848 }
3849
3850 bson_destroy (&reply);
3851 mongoc_bulk_operation_destroy (bulk);
3852 }
3853
3854 static void
3855 bulk5_success (mongoc_collection_t *collection)
3856 {
3857 mongoc_bulk_operation_t *bulk;
3858 bson_error_t error;
3859 bson_t *doc;
3860 bson_t reply;
3861 char *str;
3862 bool ret;
3863
3864 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3865
3866 /* Allow this document to bypass document validation.
3867 * NOTE: When authentication is enabled, the authenticated user must have
3868 * either the "dbadmin" or "restore" roles to bypass document validation */
3869 mongoc_bulk_operation_set_bypass_document_validation (bulk, true);
3870
3871 /* Two inserts */
3872 doc = BCON_NEW ("_id", BCON_INT32 (31));
3873 mongoc_bulk_operation_insert (bulk, doc);
3874 bson_destroy (doc);
3875
3876 doc = BCON_NEW ("_id", BCON_INT32 (32));
3877 mongoc_bulk_operation_insert (bulk, doc);
3878 bson_destroy (doc);
3879
3880 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3881
3882 str = bson_as_canonical_extended_json (&reply, NULL);
3883 printf ("%s\n", str);
3884 bson_free (str);
3885
3886 if (!ret) {
3887 printf ("Error: %s\n", error.message);
3888 }
3889
3890 bson_destroy (&reply);
3891 mongoc_bulk_operation_destroy (bulk);
3892 }
3893
3894 int
3895 main (void)
3896 {
3897 bson_t *options;
3898 bson_error_t error;
3899 mongoc_client_t *client;
3900 mongoc_collection_t *collection;
3901 mongoc_database_t *database;
3902 const char *uri_string = "mongodb://localhost/?appname=bulk5-example";
3903 mongoc_uri_t *uri;
3904
3905 mongoc_init ();
3906
3907 uri = mongoc_uri_new_with_error (uri_string, &error);
3908 if (!uri) {
3909 fprintf (stderr,
3910 "failed to parse URI: %s\n"
3911 "error message: %s\n",
3912 uri_string,
3913 error.message);
3914 return EXIT_FAILURE;
3915 }
3916
3917 client = mongoc_client_new_from_uri (uri);
3918 if (!client) {
3919 return EXIT_FAILURE;
3920 }
3921
3922 mongoc_client_set_error_api (client, 2);
3923 database = mongoc_client_get_database (client, "testasdf");
3924
3925 /* Create schema validator */
3926 options = BCON_NEW (
3927 "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
3928 collection =
3929 mongoc_database_create_collection (database, "collname", options, &error);
3930
3931 if (collection) {
3932 bulk5_fail (collection);
3933 bulk5_success (collection);
3934 mongoc_collection_destroy (collection);
3935 } else {
3936 fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
3937 }
3938
3939 bson_free (options);
3940 mongoc_uri_destroy (uri);
3941 mongoc_database_destroy (database);
3942 mongoc_client_destroy (client);
3943
3944 mongoc_cleanup ();
3945
3946 return EXIT_SUCCESS;
3947 }
3948
3949
3950 Running the above example will result in:
3951
3952 { "nInserted" : 0,
3953 "nMatched" : 0,
3954 "nModified" : 0,
3955 "nRemoved" : 0,
3956 "nUpserted" : 0,
3957 "writeErrors" : [
3958 { "index" : 0,
3959 "code" : 121,
3960 "errmsg" : "Document failed validation" } ] }
3961
3962 Error: Document failed validation
3963
3964 { "nInserted" : 2,
3965 "nMatched" : 0,
3966 "nModified" : 0,
3967 "nRemoved" : 0,
3968 "nUpserted" : 0,
3969 "writeErrors" : [] }
3970
3971 The bson_error_t domain is MONGOC_ERROR_COMMAND.
3972
3973 Bulk Operation Write Concerns
3974 By default bulk operations are executed with the write_concern of the
3975 collection they are executed against. A custom write concern can be
3976 passed to the mongoc_collection_create_bulk_operation_with_opts()
3977 method. Write concern errors (e.g. wtimeout) will be reported after all
3978 operations are attempted, regardless of execution order.
3979
3980 bulk4.c
3981
3982 #include <assert.h>
3983 #include <mongoc/mongoc.h>
3984 #include <stdio.h>
3985
3986 static void
3987 bulk4 (mongoc_collection_t *collection)
3988 {
3989 bson_t opts = BSON_INITIALIZER;
3990 mongoc_write_concern_t *wc;
3991 mongoc_bulk_operation_t *bulk;
3992 bson_error_t error;
3993 bson_t *doc;
3994 bson_t reply;
3995 char *str;
3996 bool ret;
3997
3998 wc = mongoc_write_concern_new ();
3999 mongoc_write_concern_set_w (wc, 4);
4000 mongoc_write_concern_set_wtimeout_int64 (wc, 100); /* milliseconds */
4001 mongoc_write_concern_append (wc, &opts);
4002
4003 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
4004
4005 /* Two inserts */
4006 doc = BCON_NEW ("_id", BCON_INT32 (10));
4007 mongoc_bulk_operation_insert (bulk, doc);
4008 bson_destroy (doc);
4009
4010 doc = BCON_NEW ("_id", BCON_INT32 (11));
4011 mongoc_bulk_operation_insert (bulk, doc);
4012 bson_destroy (doc);
4013
4014 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
4015
4016 str = bson_as_canonical_extended_json (&reply, NULL);
4017 printf ("%s\n", str);
4018 bson_free (str);
4019
4020 if (!ret) {
4021 printf ("Error: %s\n", error.message);
4022 }
4023
4024 bson_destroy (&reply);
4025 mongoc_bulk_operation_destroy (bulk);
4026 mongoc_write_concern_destroy (wc);
4027 bson_destroy (&opts);
4028 }
4029
4030 int
4031 main (void)
4032 {
4033 mongoc_client_t *client;
4034 mongoc_collection_t *collection;
4035 const char *uri_string = "mongodb://localhost/?appname=bulk4-example";
4036 mongoc_uri_t *uri;
4037 bson_error_t error;
4038
4039 mongoc_init ();
4040
4041 uri = mongoc_uri_new_with_error (uri_string, &error);
4042 if (!uri) {
4043 fprintf (stderr,
4044 "failed to parse URI: %s\n"
4045 "error message: %s\n",
4046 uri_string,
4047 error.message);
4048 return EXIT_FAILURE;
4049 }
4050
4051 client = mongoc_client_new_from_uri (uri);
4052 if (!client) {
4053 return EXIT_FAILURE;
4054 }
4055
4056 mongoc_client_set_error_api (client, 2);
4057 collection = mongoc_client_get_collection (client, "test", "test");
4058
4059 bulk4 (collection);
4060
4061 mongoc_uri_destroy (uri);
4062 mongoc_collection_destroy (collection);
4063 mongoc_client_destroy (client);
4064
4065 mongoc_cleanup ();
4066
4067 return EXIT_SUCCESS;
4068 }
4069
4070
4071 Example reply document and error message:
4072
4073 { "nInserted" : 2,
4074 "nMatched" : 0,
4075 "nModified" : 0,
4076 "nRemoved" : 0,
4077 "nUpserted" : 0,
4078 "writeErrors" : [],
4079 "writeConcernErrors" : [
4080 { "code" : 64,
4081 "errmsg" : "waiting for replication timed out" }
4082 ] }
4083
4084 Error: waiting for replication timed out
4085
4086 The bson_error_t domain is MONGOC_ERROR_WRITE_CONCERN if there are
4087 write concern errors and no write errors. Write errors indicate failed
4088 operations, so they take precedence over write concern errors, which
4089 mean merely that the write concern is not satisfied yet.
4090
4091 Setting Collation Order
4092 This feature is only available when using MongoDB 3.4 and later.
4093
4094 bulk-collation.c
4095
4096 #include <mongoc/mongoc.h>
4097 #include <stdio.h>
4098
4099 static void
4100 bulk_collation (mongoc_collection_t *collection)
4101 {
4102 mongoc_bulk_operation_t *bulk;
4103 bson_t *opts;
4104 bson_t *doc;
4105 bson_t *selector;
4106 bson_t *update;
4107 bson_error_t error;
4108 bson_t reply;
4109 char *str;
4110 uint32_t ret;
4111
4112 /* insert {_id: "one"} and {_id: "One"} */
4113 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
4114 doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
4115 mongoc_bulk_operation_insert (bulk, doc);
4116 bson_destroy (doc);
4117
4118 doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
4119 mongoc_bulk_operation_insert (bulk, doc);
4120 bson_destroy (doc);
4121
4122 /* "One" normally sorts before "one"; make "one" come first */
4123 opts = BCON_NEW ("collation",
4124 "{",
4125 "locale",
4126 BCON_UTF8 ("en_US"),
4127 "caseFirst",
4128 BCON_UTF8 ("lower"),
4129 "}");
4130
4131 /* set x=1 on the document with _id "One", which now sorts after "one" */
4132 update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
4133 selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
4134 mongoc_bulk_operation_update_one_with_opts (
4135 bulk, selector, update, opts, &error);
4136
4137 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
4138
4139 str = bson_as_canonical_extended_json (&reply, NULL);
4140 printf ("%s\n", str);
4141 bson_free (str);
4142
4143 if (!ret) {
4144 printf ("Error: %s\n", error.message);
4145 }
4146
4147 bson_destroy (&reply);
4148 bson_destroy (update);
4149 bson_destroy (selector);
4150 bson_destroy (opts);
4151 mongoc_bulk_operation_destroy (bulk);
4152 }
4153
4154 int
4155 main (void)
4156 {
4157 mongoc_client_t *client;
4158 mongoc_collection_t *collection;
4159 const char *uri_string = "mongodb://localhost/?appname=bulk-collation";
4160 mongoc_uri_t *uri;
4161 bson_error_t error;
4162
4163 mongoc_init ();
4164
4165 uri = mongoc_uri_new_with_error (uri_string, &error);
4166 if (!uri) {
4167 fprintf (stderr,
4168 "failed to parse URI: %s\n"
4169 "error message: %s\n",
4170 uri_string,
4171 error.message);
4172 return EXIT_FAILURE;
4173 }
4174
4175 client = mongoc_client_new_from_uri (uri);
4176 if (!client) {
4177 return EXIT_FAILURE;
4178 }
4179
4180 mongoc_client_set_error_api (client, 2);
4181 collection = mongoc_client_get_collection (client, "db", "collection");
4182 bulk_collation (collection);
4183
4184 mongoc_uri_destroy (uri);
4185 mongoc_collection_destroy (collection);
4186 mongoc_client_destroy (client);
4187
4188 mongoc_cleanup ();
4189
4190 return EXIT_SUCCESS;
4191 }
4192
4193
4194 Running the above example will result in:
4195
4196 { "nInserted" : 2,
4197 "nMatched" : 1,
4198 "nModified" : 1,
4199 "nRemoved" : 0,
4200 "nUpserted" : 0,
4201 "writeErrors" : [ ]
4202 }
4203
4204 Unacknowledged Bulk Writes
4205 Set "w" to zero for an unacknowledged write. The driver sends unac‐
4206 knowledged writes using the legacy opcodes OP_INSERT, OP_UPDATE, and
4207 OP_DELETE.
4208
4209 bulk6.c
4210
4211 #include <mongoc/mongoc.h>
4212 #include <stdio.h>
4213
4214 static void
4215 bulk6 (mongoc_collection_t *collection)
4216 {
4217 bson_t opts = BSON_INITIALIZER;
4218 mongoc_write_concern_t *wc;
4219 mongoc_bulk_operation_t *bulk;
4220 bson_error_t error;
4221 bson_t *doc;
4222 bson_t *selector;
4223 bson_t reply;
4224 char *str;
4225 bool ret;
4226
4227 wc = mongoc_write_concern_new ();
4228 mongoc_write_concern_set_w (wc, 0);
4229 mongoc_write_concern_append (wc, &opts);
4230
4231 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
4232
4233 doc = BCON_NEW ("_id", BCON_INT32 (10));
4234 mongoc_bulk_operation_insert (bulk, doc);
4235 bson_destroy (doc);
4236
4237 selector = BCON_NEW ("_id", BCON_INT32 (11));
4238 mongoc_bulk_operation_remove_one (bulk, selector);
4239 bson_destroy (selector);
4240
4241 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
4242
4243 str = bson_as_canonical_extended_json (&reply, NULL);
4244 printf ("%s\n", str);
4245 bson_free (str);
4246
4247 if (!ret) {
4248 printf ("Error: %s\n", error.message);
4249 }
4250
4251 bson_destroy (&reply);
4252 mongoc_bulk_operation_destroy (bulk);
4253 mongoc_write_concern_destroy (wc);
4254 bson_destroy (&opts);
4255 }
4256
4257 int
4258 main (void)
4259 {
4260 mongoc_client_t *client;
4261 mongoc_collection_t *collection;
4262 const char *uri_string = "mongodb://localhost/?appname=bulk6-example";
4263 mongoc_uri_t *uri;
4264 bson_error_t error;
4265
4266 mongoc_init ();
4267
4268 uri = mongoc_uri_new_with_error (uri_string, &error);
4269 if (!uri) {
4270 fprintf (stderr,
4271 "failed to parse URI: %s\n"
4272 "error message: %s\n",
4273 uri_string,
4274 error.message);
4275 return EXIT_FAILURE;
4276 }
4277
4278 client = mongoc_client_new_from_uri (uri);
4279 if (!client) {
4280 return EXIT_FAILURE;
4281 }
4282
4283 mongoc_client_set_error_api (client, 2);
4284 collection = mongoc_client_get_collection (client, "test", "test");
4285
4286 bulk6 (collection);
4287
4288 mongoc_uri_destroy (uri);
4289 mongoc_collection_destroy (collection);
4290 mongoc_client_destroy (client);
4291
4292 mongoc_cleanup ();
4293
4294 return EXIT_SUCCESS;
4295 }
4296
4297
4298 The reply document is empty:
4299
4300 { }
4301
4302 Further Reading
4303 See the Driver Bulk API Spec, which describes bulk write operations for
4304 all MongoDB drivers.
4305
4306 Aggregation Framework Examples
4307 This document provides a number of practical examples that display the
4308 capabilities of the aggregation framework.
4309
4310 The Aggregations using the Zip Codes Data Set examples uses a publicly
4311 available data set of all zipcodes and populations in the United
4312 States. These data are available at: zips.json.
4313
4314 Requirements
4315 Let's check if everything is installed.
4316
4317 Use the following command to load zips.json data set into mongod in‐
4318 stance:
4319
4320 $ mongoimport --drop -d test -c zipcodes zips.json
4321
4322 Let's use the MongoDB shell to verify that everything was imported suc‐
4323 cessfully.
4324
4325 $ mongo test
4326 connecting to: test
4327 > db.zipcodes.count()
4328 29467
4329 > db.zipcodes.findOne()
4330 {
4331 "_id" : "35004",
4332 "city" : "ACMAR",
4333 "loc" : [
4334 -86.51557,
4335 33.584132
4336 ],
4337 "pop" : 6055,
4338 "state" : "AL"
4339 }
4340
4341 Aggregations using the Zip Codes Data Set
4342 Each document in this collection has the following form:
4343
4344 {
4345 "_id" : "35004",
4346 "city" : "Acmar",
4347 "state" : "AL",
4348 "pop" : 6055,
4349 "loc" : [-86.51557, 33.584132]
4350 }
4351
4352 In these documents:
4353
4354 • The _id field holds the zipcode as a string.
4355
4356 • The city field holds the city name.
4357
4358 • The state field holds the two letter state abbreviation.
4359
4360 • The pop field holds the population.
4361
4362 • The loc field holds the location as a [latitude, longitude] array.
4363
4364 States with Populations Over 10 Million
4365 To get all states with a population greater than 10 million, use the
4366 following aggregation pipeline:
4367
4368 aggregation1.c
4369
4370 #include <mongoc/mongoc.h>
4371 #include <stdio.h>
4372
4373 static void
4374 print_pipeline (mongoc_collection_t *collection)
4375 {
4376 mongoc_cursor_t *cursor;
4377 bson_error_t error;
4378 const bson_t *doc;
4379 bson_t *pipeline;
4380 char *str;
4381
4382 pipeline = BCON_NEW ("pipeline",
4383 "[",
4384 "{",
4385 "$group",
4386 "{",
4387 "_id",
4388 "$state",
4389 "total_pop",
4390 "{",
4391 "$sum",
4392 "$pop",
4393 "}",
4394 "}",
4395 "}",
4396 "{",
4397 "$match",
4398 "{",
4399 "total_pop",
4400 "{",
4401 "$gte",
4402 BCON_INT32 (10000000),
4403 "}",
4404 "}",
4405 "}",
4406 "]");
4407
4408 cursor = mongoc_collection_aggregate (
4409 collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
4410
4411 while (mongoc_cursor_next (cursor, &doc)) {
4412 str = bson_as_canonical_extended_json (doc, NULL);
4413 printf ("%s\n", str);
4414 bson_free (str);
4415 }
4416
4417 if (mongoc_cursor_error (cursor, &error)) {
4418 fprintf (stderr, "Cursor Failure: %s\n", error.message);
4419 }
4420
4421 mongoc_cursor_destroy (cursor);
4422 bson_destroy (pipeline);
4423 }
4424
4425 int
4426 main (void)
4427 {
4428 mongoc_client_t *client;
4429 mongoc_collection_t *collection;
4430 const char *uri_string =
4431 "mongodb://localhost:27017/?appname=aggregation-example";
4432 mongoc_uri_t *uri;
4433 bson_error_t error;
4434
4435 mongoc_init ();
4436
4437 uri = mongoc_uri_new_with_error (uri_string, &error);
4438 if (!uri) {
4439 fprintf (stderr,
4440 "failed to parse URI: %s\n"
4441 "error message: %s\n",
4442 uri_string,
4443 error.message);
4444 return EXIT_FAILURE;
4445 }
4446
4447 client = mongoc_client_new_from_uri (uri);
4448 if (!client) {
4449 return EXIT_FAILURE;
4450 }
4451
4452 mongoc_client_set_error_api (client, 2);
4453 collection = mongoc_client_get_collection (client, "test", "zipcodes");
4454
4455 print_pipeline (collection);
4456
4457 mongoc_uri_destroy (uri);
4458 mongoc_collection_destroy (collection);
4459 mongoc_client_destroy (client);
4460
4461 mongoc_cleanup ();
4462
4463 return EXIT_SUCCESS;
4464 }
4465
4466
4467 You should see a result like the following:
4468
4469 { "_id" : "PA", "total_pop" : 11881643 }
4470 { "_id" : "OH", "total_pop" : 10847115 }
4471 { "_id" : "NY", "total_pop" : 17990455 }
4472 { "_id" : "FL", "total_pop" : 12937284 }
4473 { "_id" : "TX", "total_pop" : 16986510 }
4474 { "_id" : "IL", "total_pop" : 11430472 }
4475 { "_id" : "CA", "total_pop" : 29760021 }
4476
4477 The above aggregation pipeline is build from two pipeline operators:
4478 $group and $match.
4479
4480 The $group pipeline operator requires _id field where we specify group‐
4481 ing; remaining fields specify how to generate composite value and must
4482 use one of the group aggregation functions: $addToSet, $first, $last,
4483 $max, $min, $avg, $push, $sum. The $match pipeline operator syntax is
4484 the same as the read operation query syntax.
4485
4486 The $group process reads all documents and for each state it creates a
4487 separate document, for example:
4488
4489 { "_id" : "WA", "total_pop" : 4866692 }
4490
4491 The total_pop field uses the $sum aggregation function to sum the val‐
4492 ues of all pop fields in the source documents.
4493
4494 Documents created by $group are piped to the $match pipeline operator.
4495 It returns the documents with the value of total_pop field greater than
4496 or equal to 10 million.
4497
4498 Average City Population by State
4499 To get the first three states with the greatest average population per
4500 city, use the following aggregation:
4501
4502 pipeline = BCON_NEW ("pipeline", "[",
4503 "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
4504 "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
4505 "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
4506 "{", "$limit", BCON_INT32 (3) "}",
4507 "]");
4508
4509 This aggregate pipeline produces:
4510
4511 { "_id" : "DC", "avg_city_pop" : 303450.0 }
4512 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
4513 { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
4514
4515 The above aggregation pipeline is build from three pipeline operators:
4516 $group, $sort and $limit.
4517
4518 The first $group operator creates the following documents:
4519
4520 { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
4521
4522 Note, that the $group operator can't use nested documents except the
4523 _id field.
4524
4525 The second $group uses these documents to create the following docu‐
4526 ments:
4527
4528 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
4529
4530 These documents are sorted by the avg_city_pop field in descending or‐
4531 der. Finally, the $limit pipeline operator returns the first 3 docu‐
4532 ments from the sorted set.
4533
4534 "distinct" and "mapReduce"
4535 This document provides some practical, simple, examples to demonstrate
4536 the distinct and mapReduce commands.
4537
4538 Setup
4539 First we'll write some code to insert sample data:
4540
4541 doc-common-insert.c
4542
4543 /* Don't try to compile this file on its own. It's meant to be #included
4544 by example code */
4545
4546 /* Insert some sample data */
4547 bool
4548 insert_data (mongoc_collection_t *collection)
4549 {
4550 mongoc_bulk_operation_t *bulk;
4551 enum N { ndocs = 4 };
4552 bson_t *docs[ndocs];
4553 bson_error_t error;
4554 int i = 0;
4555 bool ret;
4556
4557 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
4558
4559 docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
4560 docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
4561 docs[2] = BCON_NEW (
4562 "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
4563 docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
4564
4565 for (i = 0; i < ndocs; i++) {
4566 mongoc_bulk_operation_insert (bulk, docs[i]);
4567 bson_destroy (docs[i]);
4568 docs[i] = NULL;
4569 }
4570
4571 ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
4572
4573 if (!ret) {
4574 fprintf (stderr, "Error inserting data: %s\n", error.message);
4575 }
4576
4577 mongoc_bulk_operation_destroy (bulk);
4578 return ret;
4579 }
4580
4581 /* A helper which we'll use a lot later on */
4582 void
4583 print_res (const bson_t *reply)
4584 {
4585 char *str;
4586 BSON_ASSERT (reply);
4587 str = bson_as_canonical_extended_json (reply, NULL);
4588 printf ("%s\n", str);
4589 bson_free (str);
4590 }
4591
4592
4593 "distinct" command
4594 This is how to use the distinct command to get the distinct values of x
4595 which are greater than 1:
4596
4597 distinct.c
4598
4599 bool
4600 distinct (mongoc_database_t *database)
4601 {
4602 bson_t *command;
4603 bson_t reply;
4604 bson_error_t error;
4605 bool res;
4606 bson_iter_t iter;
4607 bson_iter_t array_iter;
4608 double val;
4609
4610 command = BCON_NEW ("distinct",
4611 BCON_UTF8 (COLLECTION_NAME),
4612 "key",
4613 BCON_UTF8 ("x"),
4614 "query",
4615 "{",
4616 "x",
4617 "{",
4618 "$gt",
4619 BCON_DOUBLE (1.0),
4620 "}",
4621 "}");
4622 res =
4623 mongoc_database_command_simple (database, command, NULL, &reply, &error);
4624 if (!res) {
4625 fprintf (stderr, "Error with distinct: %s\n", error.message);
4626 goto cleanup;
4627 }
4628
4629 /* Do something with reply (in this case iterate through the values) */
4630 if (!(bson_iter_init_find (&iter, &reply, "values") &&
4631 BSON_ITER_HOLDS_ARRAY (&iter) &&
4632 bson_iter_recurse (&iter, &array_iter))) {
4633 fprintf (stderr, "Couldn't extract \"values\" field from response\n");
4634 goto cleanup;
4635 }
4636
4637 while (bson_iter_next (&array_iter)) {
4638 if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
4639 val = bson_iter_double (&array_iter);
4640 printf ("Next double: %f\n", val);
4641 }
4642 }
4643
4644 cleanup:
4645 /* cleanup */
4646 bson_destroy (command);
4647 bson_destroy (&reply);
4648 return res;
4649 }
4650
4651
4652 "mapReduce" - basic example
4653 A simple example using the map reduce framework. It simply adds up the
4654 number of occurrences of each "tag".
4655
4656 First define the map and reduce functions:
4657
4658 constants.c
4659
4660 const char *const COLLECTION_NAME = "things";
4661
4662 /* Our map function just emits a single (key, 1) pair for each tag
4663 in the array: */
4664 const char *const MAPPER = "function () {"
4665 "this.tags.forEach(function(z) {"
4666 "emit(z, 1);"
4667 "});"
4668 "}";
4669
4670 /* The reduce function sums over all of the emitted values for a
4671 given key: */
4672 const char *const REDUCER = "function (key, values) {"
4673 "var total = 0;"
4674 "for (var i = 0; i < values.length; i++) {"
4675 "total += values[i];"
4676 "}"
4677 "return total;"
4678 "}";
4679 /* Note We can't just return values.length as the reduce function
4680 might be called iteratively on the results of other reduce
4681 steps. */
4682
4683
4684 Run the mapReduce command. Use the generic command helpers (e.g.
4685 mongoc_database_command_simple()). Do not the read command helpers
4686 (e.g. mongoc_database_read_command_with_opts()) because they are con‐
4687 sidered retryable read operations. If retryable reads are enabled,
4688 those operations will retry once on a retryable error, giving undesir‐
4689 able behavior for mapReduce.
4690
4691 map-reduce-basic.c
4692
4693 bool
4694 map_reduce_basic (mongoc_database_t *database)
4695 {
4696 bson_t reply;
4697 bson_t *command;
4698 bool res;
4699 bson_error_t error;
4700 mongoc_cursor_t *cursor;
4701 const bson_t *doc;
4702
4703 bool query_done = false;
4704
4705 const char *out_collection_name = "outCollection";
4706 mongoc_collection_t *out_collection;
4707
4708 /* Empty find query */
4709 bson_t find_query = BSON_INITIALIZER;
4710
4711 /* Construct the mapReduce command */
4712
4713 /* Other arguments can also be specified here, like "query" or
4714 "limit" and so on */
4715 command = BCON_NEW ("mapReduce",
4716 BCON_UTF8 (COLLECTION_NAME),
4717 "map",
4718 BCON_CODE (MAPPER),
4719 "reduce",
4720 BCON_CODE (REDUCER),
4721 "out",
4722 BCON_UTF8 (out_collection_name));
4723 res =
4724 mongoc_database_command_simple (database, command, NULL, &reply, &error);
4725
4726 if (!res) {
4727 fprintf (stderr, "MapReduce failed: %s\n", error.message);
4728 goto cleanup;
4729 }
4730
4731 /* Do something with the reply (it doesn't contain the mapReduce results) */
4732 print_res (&reply);
4733
4734 /* Now we'll query outCollection to see what the results are */
4735 out_collection =
4736 mongoc_database_get_collection (database, out_collection_name);
4737 cursor = mongoc_collection_find_with_opts (
4738 out_collection, &find_query, NULL, NULL);
4739 query_done = true;
4740
4741 /* Do something with the results */
4742 while (mongoc_cursor_next (cursor, &doc)) {
4743 print_res (doc);
4744 }
4745
4746 if (mongoc_cursor_error (cursor, &error)) {
4747 fprintf (stderr, "ERROR: %s\n", error.message);
4748 res = false;
4749 goto cleanup;
4750 }
4751
4752 cleanup:
4753 /* cleanup */
4754 if (query_done) {
4755 mongoc_cursor_destroy (cursor);
4756 mongoc_collection_destroy (out_collection);
4757 }
4758
4759 bson_destroy (&reply);
4760 bson_destroy (command);
4761
4762 return res;
4763 }
4764
4765
4766 "mapReduce" - more complicated example
4767 You must have replica set running for this.
4768
4769 In this example we contact a secondary in the replica set and do an
4770 "inline" map reduce, so the results are returned immediately:
4771
4772 map-reduce-advanced.c
4773
4774 bool
4775 map_reduce_advanced (mongoc_database_t *database)
4776 {
4777 bson_t *command;
4778 bson_error_t error;
4779 bool res = true;
4780 mongoc_cursor_t *cursor;
4781 mongoc_read_prefs_t *read_pref;
4782 const bson_t *doc;
4783
4784 /* Construct the mapReduce command */
4785 /* Other arguments can also be specified here, like "query" or "limit"
4786 and so on */
4787
4788 /* Read the results inline from a secondary replica */
4789 command = BCON_NEW ("mapReduce",
4790 BCON_UTF8 (COLLECTION_NAME),
4791 "map",
4792 BCON_CODE (MAPPER),
4793 "reduce",
4794 BCON_CODE (REDUCER),
4795 "out",
4796 "{",
4797 "inline",
4798 "1",
4799 "}");
4800
4801 read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
4802 cursor = mongoc_database_command (
4803 database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
4804
4805 /* Do something with the results */
4806 while (mongoc_cursor_next (cursor, &doc)) {
4807 print_res (doc);
4808 }
4809
4810 if (mongoc_cursor_error (cursor, &error)) {
4811 fprintf (stderr, "ERROR: %s\n", error.message);
4812 res = false;
4813 }
4814
4815 mongoc_cursor_destroy (cursor);
4816 mongoc_read_prefs_destroy (read_pref);
4817 bson_destroy (command);
4818
4819 return res;
4820 }
4821
4822
4823 Running the Examples
4824 Here's how to run the example code
4825
4826 basic-aggregation.c
4827
4828 /*
4829 * Copyright 2016 MongoDB, Inc.
4830 *
4831 * Licensed under the Apache License, Version 2.0 (the "License");
4832 * you may not use this file except in compliance with the License.
4833 * You may obtain a copy of the License at
4834 *
4835 * http://www.apache.org/licenses/LICENSE-2.0
4836 *
4837 * Unless required by applicable law or agreed to in writing, software
4838 * distributed under the License is distributed on an "AS IS" BASIS,
4839 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4840 * See the License for the specific language governing permissions and
4841 * limitations under the License.
4842 */
4843
4844
4845 #include <mongoc/mongoc.h>
4846 #include <stdio.h>
4847
4848
4849 #include "constants.c"
4850
4851 #include "../doc-common-insert.c"
4852 #include "distinct.c"
4853 #include "map-reduce-basic.c"
4854 #include "map-reduce-advanced.c"
4855
4856
4857 int
4858 main (int argc, char *argv[])
4859 {
4860 mongoc_database_t *database = NULL;
4861 mongoc_client_t *client = NULL;
4862 mongoc_collection_t *collection = NULL;
4863 mongoc_uri_t *uri = NULL;
4864 bson_error_t error;
4865 char *host_and_port = NULL;
4866 int exit_code = EXIT_FAILURE;
4867
4868 if (argc != 2) {
4869 fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
4870 fprintf (stderr,
4871 "the connection string can be of the following forms:\n");
4872 fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
4873 fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
4874 fprintf (stderr,
4875 "mongodb://user:pass@localhost:27017\t"
4876 "local machine on port 27017, and authenticate with username "
4877 "user and password pass\n");
4878 return exit_code;
4879 }
4880
4881 mongoc_init ();
4882
4883 if (strncmp (argv[1], "mongodb://", 10) == 0) {
4884 host_and_port = bson_strdup (argv[1]);
4885 } else {
4886 host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
4887 }
4888
4889 uri = mongoc_uri_new_with_error (host_and_port, &error);
4890 if (!uri) {
4891 fprintf (stderr,
4892 "failed to parse URI: %s\n"
4893 "error message: %s\n",
4894 host_and_port,
4895 error.message);
4896 goto cleanup;
4897 }
4898
4899 client = mongoc_client_new_from_uri (uri);
4900 if (!client) {
4901 goto cleanup;
4902 }
4903
4904 mongoc_client_set_error_api (client, 2);
4905 database = mongoc_client_get_database (client, "test");
4906 collection = mongoc_database_get_collection (database, COLLECTION_NAME);
4907
4908 printf ("Inserting data\n");
4909 if (!insert_data (collection)) {
4910 goto cleanup;
4911 }
4912
4913 printf ("distinct\n");
4914 if (!distinct (database)) {
4915 goto cleanup;
4916 }
4917
4918 printf ("map reduce\n");
4919 if (!map_reduce_basic (database)) {
4920 goto cleanup;
4921 }
4922
4923 printf ("more complicated map reduce\n");
4924 if (!map_reduce_advanced (database)) {
4925 goto cleanup;
4926 }
4927
4928 exit_code = EXIT_SUCCESS;
4929
4930 cleanup:
4931 if (collection) {
4932 mongoc_collection_destroy (collection);
4933 }
4934
4935 if (database) {
4936 mongoc_database_destroy (database);
4937 }
4938
4939 if (client) {
4940 mongoc_client_destroy (client);
4941 }
4942
4943 if (uri) {
4944 mongoc_uri_destroy (uri);
4945 }
4946
4947 if (host_and_port) {
4948 bson_free (host_and_port);
4949 }
4950
4951 mongoc_cleanup ();
4952 return exit_code;
4953 }
4954
4955
4956 If you want to try the advanced map reduce example with a secondary,
4957 start a replica set (instructions for how to do this can be found
4958 here).
4959
4960 Otherwise, just start an instance of MongoDB:
4961
4962 $ mongod
4963
4964 Now compile and run the example program:
4965
4966 $ cd examples/basic_aggregation/
4967 $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
4968 $ ./agg-example localhost
4969
4970 Inserting data
4971 distinct
4972 Next double: 2.000000
4973 Next double: 3.000000
4974 map reduce
4975 { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
4976 { "_id" : "cat", "value" : 63 }
4977 { "_id" : "dog", "value" : 42 }
4978 { "_id" : "mouse", "value" : 21 }
4979 more complicated map reduce
4980 { "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 }
4981
4982 Using libmongoc in a Microsoft Visual Studio project
4983 Download and install libmongoc on your system, then open Visual Studio,
4984 select "File→New→Project...", and create a new Win32 Console Applica‐
4985 tion. [image]
4986
4987 Remember to switch the platform from 32-bit to 64-bit: [image]
4988
4989 Right-click on your console application in the Solution Explorer and
4990 select "Properties". Choose to edit properties for "All Configura‐
4991 tions", expand the "C/C++" options and choose "General". Add to the
4992 "Additional Include Directories" these paths:
4993
4994 C:\mongo-c-driver\include\libbson-1.0
4995 C:\mongo-c-driver\include\libmongoc-1.0
4996 [image]
4997
4998 (If you chose a different $PREFIX when you installed mongo-c-driver,
4999 your include paths will be different.)
5000
5001 Also in the Properties dialog, expand the "Linker" options and choose
5002 "Input", and add to the "Additional Dependencies" these libraries:
5003
5004 C:\mongo-c-driver\lib\bson-1.0.lib
5005 C:\mongo-c-driver\lib\mongoc-1.0.lib
5006 [image]
5007
5008 Adding these libraries as dependencies provides linker symbols to build
5009 your application, but to actually run it, libbson's and libmongoc's
5010 DLLs must be in your executable path. Select "Debugging" in the Proper‐
5011 ties dialog, and set the "Environment" option to:
5012
5013 PATH=c:/mongo-c-driver/bin
5014 [image]
5015
5016 Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
5017
5018 #include <mongoc/mongoc.h>
5019
5020 Static linking
5021 Following the instructions above, you have dynamically linked your ap‐
5022 plication to the libbson and libmongoc DLLs. This is usually the right
5023 choice. If you want to link statically instead, update your "Additional
5024 Dependencies" list by removing bson-1.0.lib and mongoc-1.0.lib and re‐
5025 placing them with these libraries:
5026
5027 C:\mongo-c-driver\lib\bson-static-1.0.lib
5028 C:\mongo-c-driver\lib\mongoc-static-1.0.lib
5029 ws2_32.lib
5030 Secur32.lib
5031 Crypt32.lib
5032 BCrypt.lib
5033 [image]
5034
5035 (To explain the purpose of each library: bson-static-1.0.lib and mon‐
5036 goc-static-1.0.lib are static archives of the driver code. The socket
5037 library ws2_32 is required by libbson, which uses the socket routine
5038 gethostname to help guarantee ObjectId uniqueness. The BCrypt library
5039 is used by libmongoc for TLS connections to MongoDB, and Secur32 and
5040 Crypt32 are required for enterprise authentication methods like Ker‐
5041 beros.)
5042
5043 Finally, define two preprocessor symbols before including mongoc/mon‐
5044 goc.h in your stdafx.h:
5045
5046 #define BSON_STATIC
5047 #define MONGOC_STATIC
5048 #include <mongoc/mongoc.h>
5049
5050 Making these changes to your project is only required for static link‐
5051 ing; for most people, the dynamic-linking instructions above are pre‐
5052 ferred.
5053
5054 Next Steps
5055 Now you can build and debug applications in Visual Studio that use
5056 libbson and libmongoc. Proceed to Making a Connection in the tutorial
5057 to learn how connect to MongoDB and perform operations.
5058
5059 Manage Collection Indexes
5060 To create indexes on a MongoDB collection, use
5061 mongoc_collection_create_indexes_with_opts():
5062
5063 // `keys` represents an ascending index on field `x`.
5064 bson_t *keys = BCON_NEW ("x", BCON_INT32 (1));
5065 mongoc_index_model_t *im = mongoc_index_model_new (keys, NULL /* opts */);
5066 if (mongoc_collection_create_indexes_with_opts (
5067 coll, &im, 1, NULL /* opts */, NULL /* reply */, &error)) {
5068 printf ("Successfully created index\n");
5069 } else {
5070 bson_destroy (keys);
5071 HANDLE_ERROR ("Failed to create index: %s", error.message);
5072 }
5073 bson_destroy (keys);
5074
5075
5076 To list indexes, use mongoc_collection_find_indexes_with_opts():
5077
5078 mongoc_cursor_t *cursor =
5079 mongoc_collection_find_indexes_with_opts (coll, NULL /* opts */);
5080 printf ("Listing indexes:\n");
5081 const bson_t *got;
5082 while (mongoc_cursor_next (cursor, &got)) {
5083 char *got_str = bson_as_canonical_extended_json (got, NULL);
5084 printf (" %s\n", got_str);
5085 bson_free (got_str);
5086 }
5087 if (mongoc_cursor_error (cursor, &error)) {
5088 mongoc_cursor_destroy (cursor);
5089 HANDLE_ERROR ("Failed to list indexes: %s", error.message);
5090 }
5091 mongoc_cursor_destroy (cursor);
5092
5093
5094 To drop an index, use mongoc_collection_drop_index_with_opts(). The in‐
5095 dex name may be obtained from the keys document with
5096 mongoc_collection_keys_to_index_string():
5097
5098 bson_t *keys = BCON_NEW ("x", BCON_INT32 (1));
5099 char *index_name = mongoc_collection_keys_to_index_string (keys);
5100 if (mongoc_collection_drop_index_with_opts (
5101 coll, index_name, NULL /* opts */, &error)) {
5102 printf ("Successfully dropped index\n");
5103 } else {
5104 bson_free (index_name);
5105 bson_destroy (keys);
5106 HANDLE_ERROR ("Failed to drop index: %s", error.message);
5107 }
5108 bson_free (index_name);
5109 bson_destroy (keys);
5110
5111
5112 For a full example, see example-manage-collection-indexes.c.
5113
5114 Manage Atlas Search Indexes
5115 To create an Atlas Search Index, use the createSearchIndexes command:
5116
5117 bson_t cmd;
5118 // Create command.
5119 {
5120 char *cmd_str = bson_strdup_printf (
5121 BSON_STR ({
5122 "createSearchIndexes" : "%s",
5123 "indexes" : [ {
5124 "definition" : {"mappings" : {"dynamic" : false}},
5125 "name" : "test-index"
5126 } ]
5127 }),
5128 collname);
5129 ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
5130 bson_free (cmd_str);
5131 }
5132 if (!mongoc_collection_command_simple (
5133 coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
5134 bson_destroy (&cmd);
5135 HANDLE_ERROR ("Failed to run createSearchIndexes: %s", error.message);
5136 }
5137 printf ("Created index: \"test-index\"\n");
5138 bson_destroy (&cmd);
5139
5140
5141 To list Atlas Search Indexes, use the $listSearchIndexes aggregation
5142 stage:
5143
5144 const char *pipeline_str =
5145 BSON_STR ({"pipeline" : [ {"$listSearchIndexes" : {}} ]});
5146 bson_t pipeline;
5147 ASSERT (bson_init_from_json (&pipeline, pipeline_str, -1, &error));
5148 mongoc_cursor_t *cursor =
5149 mongoc_collection_aggregate (coll,
5150 MONGOC_QUERY_NONE,
5151 &pipeline,
5152 NULL /* opts */,
5153 NULL /* read_prefs */);
5154 printf ("Listing indexes:\n");
5155 const bson_t *got;
5156 while (mongoc_cursor_next (cursor, &got)) {
5157 char *got_str = bson_as_canonical_extended_json (got, NULL);
5158 printf (" %s\n", got_str);
5159 bson_free (got_str);
5160 }
5161 if (mongoc_cursor_error (cursor, &error)) {
5162 bson_destroy (&pipeline);
5163 mongoc_cursor_destroy (cursor);
5164 HANDLE_ERROR ("Failed to run $listSearchIndexes: %s", error.message);
5165 }
5166 bson_destroy (&pipeline);
5167 mongoc_cursor_destroy (cursor);
5168
5169
5170 To update an Atlas Search Index, use the updateSearchIndex command:
5171
5172 bson_t cmd;
5173 // Create command.
5174 {
5175 char *cmd_str = bson_strdup_printf (
5176 BSON_STR ({
5177 "updateSearchIndex" : "%s",
5178 "definition" : {"mappings" : {"dynamic" : true}},
5179 "name" : "test-index"
5180 }),
5181 collname);
5182 ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
5183 bson_free (cmd_str);
5184 }
5185 if (!mongoc_collection_command_simple (
5186 coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
5187 bson_destroy (&cmd);
5188 HANDLE_ERROR ("Failed to run updateSearchIndex: %s", error.message);
5189 }
5190 printf ("Updated index: \"test-index\"\n");
5191 bson_destroy (&cmd);
5192
5193
5194 To drop an Atlas Search Index, use the dropSearchIndex command:
5195
5196 bson_t cmd;
5197 // Create command.
5198 {
5199 char *cmd_str = bson_strdup_printf (
5200 BSON_STR ({"dropSearchIndex" : "%s", "name" : "test-index"}),
5201 collname);
5202 ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
5203 bson_free (cmd_str);
5204 }
5205 if (!mongoc_collection_command_simple (
5206 coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
5207 bson_destroy (&cmd);
5208 HANDLE_ERROR ("Failed to run dropSearchIndex: %s", error.message);
5209 }
5210 printf ("Dropped index: \"test-index\"\n");
5211 bson_destroy (&cmd);
5212
5213
5214 For a full example, see example-manage-search-indexes.c.
5215
5216 Aids for Debugging
5217 GDB
5218 This repository contains a .gdbinit file that contains helper functions
5219 to aid debugging of data structures. GDB will load this file
5220 automatically if you have added the directory which contains the
5221 .gdbinit file to GDB's auto-load safe-path, and you start GDB from the
5222 directory which holds the .gdbinit file.
5223
5224 You can see the safe-path with show auto-load safe-path on a GDB
5225 prompt. You can configure it by setting it in ~/.gdbinit with:
5226
5227 add-auto-load-safe-path /path/to/mongo-c-driver
5228
5229 If you haven't added the path to your auto-load safe-path, or start GDB
5230 in another directory, load the file with:
5231
5232 source path/to/mongo-c-driver/.gdbinit
5233
5234 The .gdbinit file defines the printbson function, which shows the con‐
5235 tents of a bson_t * variable. If you have a local bson_t, then you
5236 must prefix the variable with a &.
5237
5238 An example GDB session looks like:
5239
5240 (gdb) printbson bson
5241 ALLOC [0x555556cd7310 + 0] (len=475)
5242 {
5243 'bool' : true,
5244 'int32' : NumberInt("42"),
5245 'int64' : NumberLong("3000000042"),
5246 'string' : "Stŕìñg",
5247 'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
5248 'utcDateTime' : UTCDateTime(1511277299031),
5249 'arrayOfInts' : [
5250 '0' : NumberInt("1"),
5251 '1' : NumberInt("2")
5252 ],
5253 'embeddedDocument' : {
5254 'arrayOfStrings' : [
5255 '0' : "one",
5256 '1' : "two"
5257 ],
5258 'double' : 2.718280,
5259 'notherDoc' : {
5260 'true' : NumberInt("1"),
5261 'false' : false
5262 }
5263 },
5264 'binary' : Binary("02", "3031343532333637"),
5265 'regex' : Regex("@[a-z]+@", "im"),
5266 'null' : null,
5267 'js' : JavaScript("print foo"),
5268 'jsws' : JavaScript("print foo") with scope: {
5269 'f' : NumberInt("42"),
5270 'a' : [
5271 '0' : 3.141593,
5272 '1' : 2.718282
5273 ]
5274 },
5275 'timestamp' : Timestamp(4294967295, 4294967295),
5276 'double' : 3.141593
5277 }
5278
5279 LLDB
5280 The mongo-c-driver repository contains a script lldb_bson.py that can
5281 be imported into an LLDB sessions and allows rich inspection of BSON
5282 values.
5283
5284 NOTE:
5285 The lldb_bson.py module requires an LLDB with Python 3.8 or newer.
5286
5287 To activate the script, import it from the LLDB command line:
5288
5289 (lldb) command script import /path/to/mongo-c-driver/lldb_bson.py
5290
5291 Upon success, the message lldb_bson is ready will be printed to the
5292 LLDB console.
5293
5294 The import of this script can be made automatic by adding the command
5295 to an .lldbinit file. For example: Create a file ~/.lldbinit contain‐
5296 ing:
5297
5298 command script import /path/to/mongo-c-driver/lldb_bson.py
5299
5300 The docstring at the top of the lldb_bson.py file contains more infor‐
5301 mation on the capabilities of the module.
5302
5303 Debug assertions
5304 To enable runtime debug assertions, configure with -DENABLE_DEBUG_AS‐
5305 SERTIONS=ON.
5306
5307 In-Use Encryption
5308 In-Use Encryption consists of two features:
5309
5310 Client-Side Field Level Encryption
5311 New in MongoDB 4.2, Client-Side Field Level Encryption (also referred
5312 to as CSFLE) allows administrators and developers to encrypt specific
5313 data fields in addition to other MongoDB encryption features.
5314
5315 With CSFLE, developers can encrypt fields client side without any
5316 server-side configuration or directives. CSFLE supports workloads where
5317 applications must guarantee that unauthorized parties, including server
5318 administrators, cannot read the encrypted data.
5319
5320 Automatic encryption, where sensitive fields in commands are encrypted
5321 automatically, requires an Enterprise-only dependency for Query Analy‐
5322 sis. See In-Use Encryption for more information.
5323
5324 SEE ALSO:
5325 The MongoDB Manual for Client-Side Field Level Encryption
5326
5327
5328 Automatic Client-Side Field Level Encryption
5329 Automatic encryption is enabled by calling
5330 mongoc_client_enable_auto_encryption() on a mongoc_client_t. The fol‐
5331 lowing examples show how to set up automatic encryption using
5332 mongoc_client_encryption_t to create a new encryption data key.
5333
5334 NOTE:
5335 Automatic encryption requires MongoDB 4.2 enterprise or a MongoDB
5336 4.2 Atlas cluster. The community version of the server supports au‐
5337 tomatic decryption as well as Explicit Encryption.
5338
5339 Providing Local Automatic Encryption Rules
5340 The following example shows how to specify automatic encryption rules
5341 using a schema map set with
5342 mongoc_auto_encryption_opts_set_schema_map(). The automatic encryption
5343 rules are expressed using a strict subset of the JSON Schema syntax.
5344
5345 Supplying a schema map provides more security than relying on JSON
5346 Schemas obtained from the server. It protects against a malicious
5347 server advertising a false JSON Schema, which could trick the client
5348 into sending unencrypted data that should be encrypted.
5349
5350 JSON Schemas supplied in the schema map only apply to configuring auto‐
5351 matic encryption. Other validation rules in the JSON schema will not be
5352 enforced by the driver and will result in an error:
5353
5354 client-side-encryption-schema-map.c
5355
5356 #include <mongoc/mongoc.h>
5357 #include <stdio.h>
5358 #include <stdlib.h>
5359
5360 #include "client-side-encryption-helpers.h"
5361
5362 /* Helper method to create a new data key in the key vault, a schema to use that
5363 * key, and writes the schema to a file for later use. */
5364 static bool
5365 create_schema_file (bson_t *kms_providers,
5366 const char *keyvault_db,
5367 const char *keyvault_coll,
5368 mongoc_client_t *keyvault_client,
5369 bson_error_t *error)
5370 {
5371 mongoc_client_encryption_t *client_encryption = NULL;
5372 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5373 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5374 bson_value_t datakey_id = {0};
5375 char *keyaltnames[] = {"mongoc_encryption_example_1"};
5376 bson_t *schema = NULL;
5377 char *schema_string = NULL;
5378 size_t schema_string_len;
5379 FILE *outfile = NULL;
5380 bool ret = false;
5381
5382 client_encryption_opts = mongoc_client_encryption_opts_new ();
5383 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5384 kms_providers);
5385 mongoc_client_encryption_opts_set_keyvault_namespace (
5386 client_encryption_opts, keyvault_db, keyvault_coll);
5387 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5388 keyvault_client);
5389
5390 client_encryption =
5391 mongoc_client_encryption_new (client_encryption_opts, error);
5392 if (!client_encryption) {
5393 goto fail;
5394 }
5395
5396 /* Create a new data key and json schema for the encryptedField.
5397 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5398 */
5399 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5400 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5401 datakey_opts, keyaltnames, 1);
5402 if (!mongoc_client_encryption_create_datakey (
5403 client_encryption, "local", datakey_opts, &datakey_id, error)) {
5404 goto fail;
5405 }
5406
5407 /* Create a schema describing that "encryptedField" is a string encrypted
5408 * with the newly created data key using deterministic encryption. */
5409 schema = BCON_NEW ("properties",
5410 "{",
5411 "encryptedField",
5412 "{",
5413 "encrypt",
5414 "{",
5415 "keyId",
5416 "[",
5417 BCON_BIN (datakey_id.value.v_binary.subtype,
5418 datakey_id.value.v_binary.data,
5419 datakey_id.value.v_binary.data_len),
5420 "]",
5421 "bsonType",
5422 "string",
5423 "algorithm",
5424 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
5425 "}",
5426 "}",
5427 "}",
5428 "bsonType",
5429 "object");
5430
5431 /* Use canonical JSON so that other drivers and tools will be
5432 * able to parse the MongoDB extended JSON file. */
5433 schema_string = bson_as_canonical_extended_json (schema, &schema_string_len);
5434 outfile = fopen ("jsonSchema.json", "w");
5435 if (0 == fwrite (schema_string, sizeof (char), schema_string_len, outfile)) {
5436 fprintf (stderr, "failed to write to file\n");
5437 goto fail;
5438 }
5439
5440 ret = true;
5441 fail:
5442 mongoc_client_encryption_destroy (client_encryption);
5443 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5444 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5445 bson_free (schema_string);
5446 bson_destroy (schema);
5447 bson_value_destroy (&datakey_id);
5448 if (outfile) {
5449 fclose (outfile);
5450 }
5451 return ret;
5452 }
5453
5454 /* This example demonstrates how to use automatic encryption with a client-side
5455 * schema map using the enterprise version of MongoDB */
5456 int
5457 main (void)
5458 {
5459 /* The collection used to store the encryption data keys. */
5460 #define KEYVAULT_DB "encryption"
5461 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5462 /* The collection used to store the encrypted documents in this example. */
5463 #define ENCRYPTED_DB "test"
5464 #define ENCRYPTED_COLL "coll"
5465
5466 int exit_status = EXIT_FAILURE;
5467 bool ret;
5468 uint8_t *local_masterkey = NULL;
5469 uint32_t local_masterkey_len;
5470 bson_t *kms_providers = NULL;
5471 bson_error_t error = {0};
5472 bson_t *index_keys = NULL;
5473 bson_t *index_opts = NULL;
5474 mongoc_index_model_t *index_model = NULL;
5475 bson_json_reader_t *reader = NULL;
5476 bson_t schema = BSON_INITIALIZER;
5477 bson_t *schema_map = NULL;
5478
5479 /* The MongoClient used to access the key vault (keyvault_namespace). */
5480 mongoc_client_t *keyvault_client = NULL;
5481 mongoc_collection_t *keyvault_coll = NULL;
5482 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
5483 mongoc_client_t *client = NULL;
5484 mongoc_collection_t *coll = NULL;
5485 bson_t *to_insert = NULL;
5486 mongoc_client_t *unencrypted_client = NULL;
5487 mongoc_collection_t *unencrypted_coll = NULL;
5488
5489 mongoc_init ();
5490
5491 /* Configure the master key. This must be the same master key that was used
5492 * to create the encryption key. */
5493 local_masterkey =
5494 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5495 if (!local_masterkey || local_masterkey_len != 96) {
5496 fprintf (stderr,
5497 "Specify LOCAL_MASTERKEY environment variable as a "
5498 "secure random 96 byte hex value.\n");
5499 goto fail;
5500 }
5501
5502 kms_providers = BCON_NEW ("local",
5503 "{",
5504 "key",
5505 BCON_BIN (0, local_masterkey, local_masterkey_len),
5506 "}");
5507
5508 /* Set up the key vault for this example. */
5509 keyvault_client = mongoc_client_new (
5510 "mongodb://localhost/?appname=client-side-encryption-keyvault");
5511 BSON_ASSERT (keyvault_client);
5512
5513 keyvault_coll = mongoc_client_get_collection (
5514 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
5515 mongoc_collection_drop (keyvault_coll, NULL);
5516
5517 /* Create a unique index to ensure that two data keys cannot share the same
5518 * keyAltName. This is recommended practice for the key vault. */
5519 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5520 index_opts = BCON_NEW ("unique",
5521 BCON_BOOL (true),
5522 "partialFilterExpression",
5523 "{",
5524 "keyAltNames",
5525 "{",
5526 "$exists",
5527 BCON_BOOL (true),
5528 "}",
5529 "}");
5530 index_model = mongoc_index_model_new (index_keys, index_opts);
5531 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
5532 &index_model,
5533 1,
5534 NULL /* opts */,
5535 NULL /* reply */,
5536 &error);
5537
5538 if (!ret) {
5539 goto fail;
5540 }
5541
5542 /* Create a new data key and a schema using it for encryption. Save the
5543 * schema to the file jsonSchema.json */
5544 ret = create_schema_file (
5545 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
5546
5547 if (!ret) {
5548 goto fail;
5549 }
5550
5551 /* Load the JSON Schema and construct the local schema_map option. */
5552 reader = bson_json_reader_new_from_file ("jsonSchema.json", &error);
5553 if (!reader) {
5554 goto fail;
5555 }
5556
5557 bson_json_reader_read (reader, &schema, &error);
5558
5559 /* Construct the schema map, mapping the namespace of the collection to the
5560 * schema describing encryption. */
5561 schema_map =
5562 BCON_NEW (ENCRYPTED_DB "." ENCRYPTED_COLL, BCON_DOCUMENT (&schema));
5563
5564 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5565 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
5566 keyvault_client);
5567 mongoc_auto_encryption_opts_set_keyvault_namespace (
5568 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5569 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5570 kms_providers);
5571 mongoc_auto_encryption_opts_set_schema_map (auto_encryption_opts,
5572 schema_map);
5573
5574 client =
5575 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5576 BSON_ASSERT (client);
5577
5578 /* Enable automatic encryption. It will determine that encryption is
5579 * necessary from the schema map instead of relying on the server to provide
5580 * a schema. */
5581 ret = mongoc_client_enable_auto_encryption (
5582 client, auto_encryption_opts, &error);
5583 if (!ret) {
5584 goto fail;
5585 }
5586
5587 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5588
5589 /* Clear old data */
5590 mongoc_collection_drop (coll, NULL);
5591
5592 to_insert = BCON_NEW ("encryptedField", "123456789");
5593 ret = mongoc_collection_insert_one (
5594 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5595 if (!ret) {
5596 goto fail;
5597 }
5598 printf ("decrypted document: ");
5599 if (!print_one_document (coll, &error)) {
5600 goto fail;
5601 }
5602 printf ("\n");
5603
5604 unencrypted_client = mongoc_client_new (
5605 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
5606 BSON_ASSERT (unencrypted_client);
5607
5608 unencrypted_coll = mongoc_client_get_collection (
5609 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5610 printf ("encrypted document: ");
5611 if (!print_one_document (unencrypted_coll, &error)) {
5612 goto fail;
5613 }
5614 printf ("\n");
5615
5616 exit_status = EXIT_SUCCESS;
5617 fail:
5618 if (error.code) {
5619 fprintf (stderr, "error: %s\n", error.message);
5620 }
5621
5622 bson_free (local_masterkey);
5623 bson_destroy (kms_providers);
5624 mongoc_collection_destroy (keyvault_coll);
5625 mongoc_index_model_destroy (index_model);
5626 bson_destroy (index_opts);
5627 bson_destroy (index_keys);
5628 bson_json_reader_destroy (reader);
5629 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5630 mongoc_collection_destroy (coll);
5631 mongoc_client_destroy (client);
5632 bson_destroy (to_insert);
5633 mongoc_collection_destroy (unencrypted_coll);
5634 mongoc_client_destroy (unencrypted_client);
5635 mongoc_client_destroy (keyvault_client);
5636 bson_destroy (&schema);
5637 bson_destroy (schema_map);
5638 mongoc_cleanup ();
5639 return exit_status;
5640 }
5641
5642
5643 Server-Side Field Level Encryption Enforcement
5644 The MongoDB 4.2 server supports using schema validation to enforce en‐
5645 cryption of specific fields in a collection. This schema validation
5646 will prevent an application from inserting unencrypted values for any
5647 fields marked with the "encrypt" JSON schema keyword.
5648
5649 The following example shows how to set up automatic encryption using
5650 mongoc_client_encryption_t to create a new encryption data key and cre‐
5651 ate a collection with the necessary JSON Schema:
5652
5653 client-side-encryption-server-schema.c
5654
5655 #include <mongoc/mongoc.h>
5656 #include <stdio.h>
5657 #include <stdlib.h>
5658
5659 #include "client-side-encryption-helpers.h"
5660
5661 /* Helper method to create and return a JSON schema to use for encryption.
5662 The caller will use the returned schema for server-side encryption validation.
5663 */
5664 static bson_t *
5665 create_schema (bson_t *kms_providers,
5666 const char *keyvault_db,
5667 const char *keyvault_coll,
5668 mongoc_client_t *keyvault_client,
5669 bson_error_t *error)
5670 {
5671 mongoc_client_encryption_t *client_encryption = NULL;
5672 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5673 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5674 bson_value_t datakey_id = {0};
5675 char *keyaltnames[] = {"mongoc_encryption_example_2"};
5676 bson_t *schema = NULL;
5677
5678 client_encryption_opts = mongoc_client_encryption_opts_new ();
5679 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5680 kms_providers);
5681 mongoc_client_encryption_opts_set_keyvault_namespace (
5682 client_encryption_opts, keyvault_db, keyvault_coll);
5683 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5684 keyvault_client);
5685
5686 client_encryption =
5687 mongoc_client_encryption_new (client_encryption_opts, error);
5688 if (!client_encryption) {
5689 goto fail;
5690 }
5691
5692 /* Create a new data key and json schema for the encryptedField.
5693 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5694 */
5695 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5696 mongoc_client_encryption_datakey_opts_set_keyaltnames (
5697 datakey_opts, keyaltnames, 1);
5698 if (!mongoc_client_encryption_create_datakey (
5699 client_encryption, "local", datakey_opts, &datakey_id, error)) {
5700 goto fail;
5701 }
5702
5703 /* Create a schema describing that "encryptedField" is a string encrypted
5704 * with the newly created data key using deterministic encryption. */
5705 schema = BCON_NEW ("properties",
5706 "{",
5707 "encryptedField",
5708 "{",
5709 "encrypt",
5710 "{",
5711 "keyId",
5712 "[",
5713 BCON_BIN (datakey_id.value.v_binary.subtype,
5714 datakey_id.value.v_binary.data,
5715 datakey_id.value.v_binary.data_len),
5716 "]",
5717 "bsonType",
5718 "string",
5719 "algorithm",
5720 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
5721 "}",
5722 "}",
5723 "}",
5724 "bsonType",
5725 "object");
5726
5727 fail:
5728 mongoc_client_encryption_destroy (client_encryption);
5729 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5730 mongoc_client_encryption_opts_destroy (client_encryption_opts);
5731 bson_value_destroy (&datakey_id);
5732 return schema;
5733 }
5734
5735 /* This example demonstrates how to use automatic encryption with a server-side
5736 * schema using the enterprise version of MongoDB */
5737 int
5738 main (void)
5739 {
5740 /* The collection used to store the encryption data keys. */
5741 #define KEYVAULT_DB "encryption"
5742 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5743 /* The collection used to store the encrypted documents in this example. */
5744 #define ENCRYPTED_DB "test"
5745 #define ENCRYPTED_COLL "coll"
5746
5747 int exit_status = EXIT_FAILURE;
5748 bool ret;
5749 uint8_t *local_masterkey = NULL;
5750 uint32_t local_masterkey_len;
5751 bson_t *kms_providers = NULL;
5752 bson_error_t error = {0};
5753 bson_t *index_keys = NULL;
5754 bson_t *index_opts = NULL;
5755 mongoc_index_model_t *index_model = NULL;
5756 bson_json_reader_t *reader = NULL;
5757 bson_t *schema = NULL;
5758
5759 /* The MongoClient used to access the key vault (keyvault_namespace). */
5760 mongoc_client_t *keyvault_client = NULL;
5761 mongoc_collection_t *keyvault_coll = NULL;
5762 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
5763 mongoc_client_t *client = NULL;
5764 mongoc_collection_t *coll = NULL;
5765 bson_t *to_insert = NULL;
5766 mongoc_client_t *unencrypted_client = NULL;
5767 mongoc_collection_t *unencrypted_coll = NULL;
5768 bson_t *create_cmd = NULL;
5769 bson_t *create_cmd_opts = NULL;
5770 mongoc_write_concern_t *wc = NULL;
5771
5772 mongoc_init ();
5773
5774 /* Configure the master key. This must be the same master key that was used
5775 * to create
5776 * the encryption key. */
5777 local_masterkey =
5778 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5779 if (!local_masterkey || local_masterkey_len != 96) {
5780 fprintf (stderr,
5781 "Specify LOCAL_MASTERKEY environment variable as a "
5782 "secure random 96 byte hex value.\n");
5783 goto fail;
5784 }
5785
5786 kms_providers = BCON_NEW ("local",
5787 "{",
5788 "key",
5789 BCON_BIN (0, local_masterkey, local_masterkey_len),
5790 "}");
5791
5792 /* Set up the key vault for this example. */
5793 keyvault_client = mongoc_client_new (
5794 "mongodb://localhost/?appname=client-side-encryption-keyvault");
5795 BSON_ASSERT (keyvault_client);
5796
5797 keyvault_coll = mongoc_client_get_collection (
5798 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
5799 mongoc_collection_drop (keyvault_coll, NULL);
5800
5801 /* Create a unique index to ensure that two data keys cannot share the same
5802 * keyAltName. This is recommended practice for the key vault. */
5803 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5804 index_opts = BCON_NEW ("unique",
5805 BCON_BOOL (true),
5806 "partialFilterExpression",
5807 "{",
5808 "keyAltNames",
5809 "{",
5810 "$exists",
5811 BCON_BOOL (true),
5812 "}",
5813 "}");
5814 index_model = mongoc_index_model_new (index_keys, index_opts);
5815 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
5816 &index_model,
5817 1,
5818 NULL /* opts */,
5819 NULL /* reply */,
5820 &error);
5821
5822 if (!ret) {
5823 goto fail;
5824 }
5825
5826 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5827 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
5828 keyvault_client);
5829 mongoc_auto_encryption_opts_set_keyvault_namespace (
5830 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5831 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5832 kms_providers);
5833 schema = create_schema (
5834 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
5835
5836 if (!schema) {
5837 goto fail;
5838 }
5839
5840 client =
5841 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5842 BSON_ASSERT (client);
5843
5844 ret = mongoc_client_enable_auto_encryption (
5845 client, auto_encryption_opts, &error);
5846 if (!ret) {
5847 goto fail;
5848 }
5849
5850 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5851
5852 /* Clear old data */
5853 mongoc_collection_drop (coll, NULL);
5854
5855 /* Create the collection with the encryption JSON Schema. */
5856 create_cmd = BCON_NEW ("create",
5857 ENCRYPTED_COLL,
5858 "validator",
5859 "{",
5860 "$jsonSchema",
5861 BCON_DOCUMENT (schema),
5862 "}");
5863 wc = mongoc_write_concern_new ();
5864 mongoc_write_concern_set_wmajority (wc, 0);
5865 create_cmd_opts = bson_new ();
5866 mongoc_write_concern_append (wc, create_cmd_opts);
5867 ret = mongoc_client_command_with_opts (client,
5868 ENCRYPTED_DB,
5869 create_cmd,
5870 NULL /* read prefs */,
5871 create_cmd_opts,
5872 NULL /* reply */,
5873 &error);
5874 if (!ret) {
5875 goto fail;
5876 }
5877
5878 to_insert = BCON_NEW ("encryptedField", "123456789");
5879 ret = mongoc_collection_insert_one (
5880 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5881 if (!ret) {
5882 goto fail;
5883 }
5884 printf ("decrypted document: ");
5885 if (!print_one_document (coll, &error)) {
5886 goto fail;
5887 }
5888 printf ("\n");
5889
5890 unencrypted_client = mongoc_client_new (
5891 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
5892 BSON_ASSERT (unencrypted_client);
5893
5894 unencrypted_coll = mongoc_client_get_collection (
5895 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5896 printf ("encrypted document: ");
5897 if (!print_one_document (unencrypted_coll, &error)) {
5898 goto fail;
5899 }
5900 printf ("\n");
5901
5902 /* Expect a server-side error if inserting with the unencrypted collection.
5903 */
5904 ret = mongoc_collection_insert_one (
5905 unencrypted_coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5906 if (!ret) {
5907 printf ("insert with unencrypted collection failed: %s\n", error.message);
5908 memset (&error, 0, sizeof (error));
5909 }
5910
5911 exit_status = EXIT_SUCCESS;
5912 fail:
5913 if (error.code) {
5914 fprintf (stderr, "error: %s\n", error.message);
5915 }
5916
5917 bson_free (local_masterkey);
5918 bson_destroy (kms_providers);
5919 mongoc_collection_destroy (keyvault_coll);
5920 mongoc_index_model_destroy (index_model);
5921 bson_destroy (index_opts);
5922 bson_destroy (index_keys);
5923 bson_json_reader_destroy (reader);
5924 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5925 mongoc_collection_destroy (coll);
5926 mongoc_client_destroy (client);
5927 bson_destroy (to_insert);
5928 mongoc_collection_destroy (unencrypted_coll);
5929 mongoc_client_destroy (unencrypted_client);
5930 mongoc_client_destroy (keyvault_client);
5931 bson_destroy (schema);
5932 bson_destroy (create_cmd);
5933 bson_destroy (create_cmd_opts);
5934 mongoc_write_concern_destroy (wc);
5935
5936 mongoc_cleanup ();
5937 return exit_status;
5938 }
5939
5940
5941 Explicit Encryption
5942 Explicit encryption is a MongoDB community feature and does not use
5943 Query Analysis (mongocryptd or crypt_shared). Explicit encryption is
5944 provided by the mongoc_client_encryption_t class, for example:
5945
5946 client-side-encryption-explicit.c
5947
5948 #include <mongoc/mongoc.h>
5949 #include <stdio.h>
5950 #include <stdlib.h>
5951
5952 #include "client-side-encryption-helpers.h"
5953
5954 /* This example demonstrates how to use explicit encryption and decryption using
5955 * the community version of MongoDB */
5956 int
5957 main (void)
5958 {
5959 /* The collection used to store the encryption data keys. */
5960 #define KEYVAULT_DB "encryption"
5961 #define KEYVAULT_COLL "__libmongocTestKeyVault"
5962 /* The collection used to store the encrypted documents in this example. */
5963 #define ENCRYPTED_DB "test"
5964 #define ENCRYPTED_COLL "coll"
5965
5966 int exit_status = EXIT_FAILURE;
5967 bool ret;
5968 uint8_t *local_masterkey = NULL;
5969 uint32_t local_masterkey_len;
5970 bson_t *kms_providers = NULL;
5971 bson_error_t error = {0};
5972 bson_t *index_keys = NULL;
5973 bson_t *index_opts = NULL;
5974 mongoc_index_model_t *index_model = NULL;
5975 bson_t *schema = NULL;
5976 mongoc_client_t *client = NULL;
5977 mongoc_collection_t *coll = NULL;
5978 mongoc_collection_t *keyvault_coll = NULL;
5979 bson_t *to_insert = NULL;
5980 bson_t *create_cmd = NULL;
5981 bson_t *create_cmd_opts = NULL;
5982 mongoc_write_concern_t *wc = NULL;
5983 mongoc_client_encryption_t *client_encryption = NULL;
5984 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5985 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5986 char *keyaltnames[] = {"mongoc_encryption_example_3"};
5987 bson_value_t datakey_id = {0};
5988 bson_value_t encrypted_field = {0};
5989 bson_value_t to_encrypt = {0};
5990 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
5991 bson_value_t decrypted = {0};
5992
5993 mongoc_init ();
5994
5995 /* Configure the master key. This must be the same master key that was used
5996 * to create the encryption key. */
5997 local_masterkey =
5998 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5999 if (!local_masterkey || local_masterkey_len != 96) {
6000 fprintf (stderr,
6001 "Specify LOCAL_MASTERKEY environment variable as a "
6002 "secure random 96 byte hex value.\n");
6003 goto fail;
6004 }
6005
6006 kms_providers = BCON_NEW ("local",
6007 "{",
6008 "key",
6009 BCON_BIN (0, local_masterkey, local_masterkey_len),
6010 "}");
6011
6012 /* The mongoc_client_t used to read/write application data. */
6013 client =
6014 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
6015 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
6016
6017 /* Clear old data */
6018 mongoc_collection_drop (coll, NULL);
6019
6020 /* Set up the key vault for this example. */
6021 keyvault_coll =
6022 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
6023 mongoc_collection_drop (keyvault_coll, NULL);
6024
6025 /* Create a unique index to ensure that two data keys cannot share the same
6026 * keyAltName. This is recommended practice for the key vault. */
6027 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
6028 index_opts = BCON_NEW ("unique",
6029 BCON_BOOL (true),
6030 "partialFilterExpression",
6031 "{",
6032 "keyAltNames",
6033 "{",
6034 "$exists",
6035 BCON_BOOL (true),
6036 "}",
6037 "}");
6038 index_model = mongoc_index_model_new (index_keys, index_opts);
6039 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
6040 &index_model,
6041 1,
6042 NULL /* opts */,
6043 NULL /* reply */,
6044 &error);
6045
6046 if (!ret) {
6047 goto fail;
6048 }
6049
6050 client_encryption_opts = mongoc_client_encryption_opts_new ();
6051 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
6052 kms_providers);
6053 mongoc_client_encryption_opts_set_keyvault_namespace (
6054 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
6055
6056 /* Set a mongoc_client_t to use for reading/writing to the key vault. This
6057 * can be the same mongoc_client_t used by the main application. */
6058 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
6059 client);
6060 client_encryption =
6061 mongoc_client_encryption_new (client_encryption_opts, &error);
6062 if (!client_encryption) {
6063 goto fail;
6064 }
6065
6066 /* Create a new data key for the encryptedField.
6067 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
6068 */
6069 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
6070 mongoc_client_encryption_datakey_opts_set_keyaltnames (
6071 datakey_opts, keyaltnames, 1);
6072 if (!mongoc_client_encryption_create_datakey (
6073 client_encryption, "local", datakey_opts, &datakey_id, &error)) {
6074 goto fail;
6075 }
6076
6077 /* Explicitly encrypt a field */
6078 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
6079 mongoc_client_encryption_encrypt_opts_set_algorithm (
6080 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
6081 mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts, &datakey_id);
6082 to_encrypt.value_type = BSON_TYPE_UTF8;
6083 to_encrypt.value.v_utf8.str = "123456789";
6084 const size_t len = strlen (to_encrypt.value.v_utf8.str);
6085 BSON_ASSERT (bson_in_range_unsigned (uint32_t, len));
6086 to_encrypt.value.v_utf8.len = (uint32_t) len;
6087
6088 ret = mongoc_client_encryption_encrypt (
6089 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
6090 if (!ret) {
6091 goto fail;
6092 }
6093
6094 to_insert = bson_new ();
6095 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
6096 ret = mongoc_collection_insert_one (
6097 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
6098 if (!ret) {
6099 goto fail;
6100 }
6101
6102 printf ("encrypted document: ");
6103 if (!print_one_document (coll, &error)) {
6104 goto fail;
6105 }
6106 printf ("\n");
6107
6108 /* Explicitly decrypt a field */
6109 ret = mongoc_client_encryption_decrypt (
6110 client_encryption, &encrypted_field, &decrypted, &error);
6111 if (!ret) {
6112 goto fail;
6113 }
6114 printf ("decrypted value: %s\n", decrypted.value.v_utf8.str);
6115
6116 exit_status = EXIT_SUCCESS;
6117 fail:
6118 if (error.code) {
6119 fprintf (stderr, "error: %s\n", error.message);
6120 }
6121
6122 bson_free (local_masterkey);
6123 bson_destroy (kms_providers);
6124 mongoc_collection_destroy (keyvault_coll);
6125 mongoc_index_model_destroy (index_model);
6126 bson_destroy (index_opts);
6127 bson_destroy (index_keys);
6128 mongoc_collection_destroy (coll);
6129 mongoc_client_destroy (client);
6130 bson_destroy (to_insert);
6131 bson_destroy (schema);
6132 bson_destroy (create_cmd);
6133 bson_destroy (create_cmd_opts);
6134 mongoc_write_concern_destroy (wc);
6135 mongoc_client_encryption_destroy (client_encryption);
6136 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
6137 mongoc_client_encryption_opts_destroy (client_encryption_opts);
6138 bson_value_destroy (&encrypted_field);
6139 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
6140 bson_value_destroy (&decrypted);
6141 bson_value_destroy (&datakey_id);
6142
6143 mongoc_cleanup ();
6144 return exit_status;
6145 }
6146
6147
6148 Explicit Encryption with Automatic Decryption
6149 Although automatic encryption requires MongoDB 4.2 enterprise or a Mon‐
6150 goDB 4.2 Atlas cluster, automatic decryption is supported for all
6151 users. To configure automatic decryption without automatic encryption
6152 set bypass_auto_encryption=True in mongoc_auto_encryption_opts_t:
6153
6154 client-side-encryption-auto-decryption.c
6155
6156 #include <mongoc/mongoc.h>
6157 #include <stdio.h>
6158 #include <stdlib.h>
6159
6160 #include "client-side-encryption-helpers.h"
6161
6162 /* This example demonstrates how to set up automatic decryption without
6163 * automatic encryption using the community version of MongoDB */
6164 int
6165 main (void)
6166 {
6167 /* The collection used to store the encryption data keys. */
6168 #define KEYVAULT_DB "encryption"
6169 #define KEYVAULT_COLL "__libmongocTestKeyVault"
6170 /* The collection used to store the encrypted documents in this example. */
6171 #define ENCRYPTED_DB "test"
6172 #define ENCRYPTED_COLL "coll"
6173
6174 int exit_status = EXIT_FAILURE;
6175 bool ret;
6176 uint8_t *local_masterkey = NULL;
6177 uint32_t local_masterkey_len;
6178 bson_t *kms_providers = NULL;
6179 bson_error_t error = {0};
6180 bson_t *index_keys = NULL;
6181 bson_t *index_opts = NULL;
6182 mongoc_index_model_t *index_model = NULL;
6183 bson_t *schema = NULL;
6184 mongoc_client_t *client = NULL;
6185 mongoc_collection_t *coll = NULL;
6186 mongoc_collection_t *keyvault_coll = NULL;
6187 bson_t *to_insert = NULL;
6188 bson_t *create_cmd = NULL;
6189 bson_t *create_cmd_opts = NULL;
6190 mongoc_write_concern_t *wc = NULL;
6191 mongoc_client_encryption_t *client_encryption = NULL;
6192 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
6193 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
6194 char *keyaltnames[] = {"mongoc_encryption_example_4"};
6195 bson_value_t datakey_id = {0};
6196 bson_value_t encrypted_field = {0};
6197 bson_value_t to_encrypt = {0};
6198 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
6199 bson_value_t decrypted = {0};
6200 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
6201 mongoc_client_t *unencrypted_client = NULL;
6202 mongoc_collection_t *unencrypted_coll = NULL;
6203
6204 mongoc_init ();
6205
6206 /* Configure the master key. This must be the same master key that was used
6207 * to create the encryption key. */
6208 local_masterkey =
6209 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
6210 if (!local_masterkey || local_masterkey_len != 96) {
6211 fprintf (stderr,
6212 "Specify LOCAL_MASTERKEY environment variable as a "
6213 "secure random 96 byte hex value.\n");
6214 goto fail;
6215 }
6216
6217 kms_providers = BCON_NEW ("local",
6218 "{",
6219 "key",
6220 BCON_BIN (0, local_masterkey, local_masterkey_len),
6221 "}");
6222
6223 client =
6224 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
6225 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
6226 mongoc_auto_encryption_opts_set_keyvault_namespace (
6227 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
6228 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
6229 kms_providers);
6230
6231 /* Setting bypass_auto_encryption to true disables automatic encryption but
6232 * keeps the automatic decryption behavior. bypass_auto_encryption will also
6233 * disable spawning mongocryptd */
6234 mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts,
6235 true);
6236
6237 /* Once bypass_auto_encryption is set, community users can enable auto
6238 * encryption on the client. This will, in fact, only perform automatic
6239 * decryption. */
6240 ret = mongoc_client_enable_auto_encryption (
6241 client, auto_encryption_opts, &error);
6242 if (!ret) {
6243 goto fail;
6244 }
6245
6246 /* Now that automatic decryption is on, we can test it by inserting a
6247 * document with an explicitly encrypted value into the collection. When we
6248 * look up the document later, it should be automatically decrypted for us.
6249 */
6250 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
6251
6252 /* Clear old data */
6253 mongoc_collection_drop (coll, NULL);
6254
6255 /* Set up the key vault for this example. */
6256 keyvault_coll =
6257 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
6258 mongoc_collection_drop (keyvault_coll, NULL);
6259
6260 /* Create a unique index to ensure that two data keys cannot share the same
6261 * keyAltName. This is recommended practice for the key vault. */
6262 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
6263 index_opts = BCON_NEW ("unique",
6264 BCON_BOOL (true),
6265 "partialFilterExpression",
6266 "{",
6267 "keyAltNames",
6268 "{",
6269 "$exists",
6270 BCON_BOOL (true),
6271 "}",
6272 "}");
6273 index_model = mongoc_index_model_new (index_keys, index_opts);
6274 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
6275 &index_model,
6276 1,
6277 NULL /* opts */,
6278 NULL /* reply */,
6279 &error);
6280
6281 if (!ret) {
6282 goto fail;
6283 }
6284
6285 client_encryption_opts = mongoc_client_encryption_opts_new ();
6286 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
6287 kms_providers);
6288 mongoc_client_encryption_opts_set_keyvault_namespace (
6289 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
6290
6291 /* The key vault client is used for reading to/from the key vault. This can
6292 * be the same mongoc_client_t used by the application. */
6293 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
6294 client);
6295 client_encryption =
6296 mongoc_client_encryption_new (client_encryption_opts, &error);
6297 if (!client_encryption) {
6298 goto fail;
6299 }
6300
6301 /* Create a new data key for the encryptedField.
6302 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
6303 */
6304 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
6305 mongoc_client_encryption_datakey_opts_set_keyaltnames (
6306 datakey_opts, keyaltnames, 1);
6307 ret = mongoc_client_encryption_create_datakey (
6308 client_encryption, "local", datakey_opts, &datakey_id, &error);
6309 if (!ret) {
6310 goto fail;
6311 }
6312
6313 /* Explicitly encrypt a field. */
6314 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
6315 mongoc_client_encryption_encrypt_opts_set_algorithm (
6316 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
6317 mongoc_client_encryption_encrypt_opts_set_keyaltname (
6318 encrypt_opts, "mongoc_encryption_example_4");
6319 to_encrypt.value_type = BSON_TYPE_UTF8;
6320 to_encrypt.value.v_utf8.str = "123456789";
6321 const size_t len = strlen (to_encrypt.value.v_utf8.str);
6322 BSON_ASSERT (bson_in_range_unsigned (uint32_t, len));
6323 to_encrypt.value.v_utf8.len = (uint32_t) len;
6324
6325 ret = mongoc_client_encryption_encrypt (
6326 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
6327 if (!ret) {
6328 goto fail;
6329 }
6330
6331 to_insert = bson_new ();
6332 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
6333 ret = mongoc_collection_insert_one (
6334 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
6335 if (!ret) {
6336 goto fail;
6337 }
6338
6339 /* When we retrieve the document, any encrypted fields will get automatically
6340 * decrypted by the driver. */
6341 printf ("decrypted document: ");
6342 if (!print_one_document (coll, &error)) {
6343 goto fail;
6344 }
6345 printf ("\n");
6346
6347 unencrypted_client =
6348 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
6349 unencrypted_coll = mongoc_client_get_collection (
6350 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
6351
6352 printf ("encrypted document: ");
6353 if (!print_one_document (unencrypted_coll, &error)) {
6354 goto fail;
6355 }
6356 printf ("\n");
6357
6358 exit_status = EXIT_SUCCESS;
6359 fail:
6360 if (error.code) {
6361 fprintf (stderr, "error: %s\n", error.message);
6362 }
6363
6364 bson_free (local_masterkey);
6365 bson_destroy (kms_providers);
6366 mongoc_collection_destroy (keyvault_coll);
6367 mongoc_index_model_destroy (index_model);
6368 bson_destroy (index_opts);
6369 bson_destroy (index_keys);
6370 mongoc_collection_destroy (coll);
6371 mongoc_client_destroy (client);
6372 bson_destroy (to_insert);
6373 bson_destroy (schema);
6374 bson_destroy (create_cmd);
6375 bson_destroy (create_cmd_opts);
6376 mongoc_write_concern_destroy (wc);
6377 mongoc_client_encryption_destroy (client_encryption);
6378 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
6379 mongoc_client_encryption_opts_destroy (client_encryption_opts);
6380 bson_value_destroy (&encrypted_field);
6381 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
6382 bson_value_destroy (&decrypted);
6383 bson_value_destroy (&datakey_id);
6384 mongoc_collection_destroy (unencrypted_coll);
6385 mongoc_client_destroy (unencrypted_client);
6386 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
6387
6388 mongoc_cleanup ();
6389 return exit_status;
6390 }
6391
6392
6393 Queryable Encryption
6394 Using Queryable Encryption requires MongoDB Server 7.0 or higher.
6395
6396 See the MongoDB Manual for Queryable Encryption for more information
6397 about the feature.
6398
6399 API related to the "rangePreview" algorithm is still experimental and
6400 subject to breaking changes!
6401
6402 Queryable Encryption in older MongoDB Server versions
6403 MongoDB Server 6.0 introduced Queryable Encryption as a Public Techni‐
6404 cal Preview. MongoDB Server 7.0 includes backwards breaking changes to
6405 the Queryable Encryption protocol.
6406
6407 The backwards breaking changes are applied in the client protocol in
6408 libmongocrypt 1.8.0. libmongoc 1.24.0 requires libmongocrypt 1.8.0 or
6409 newer. libmongoc 1.24.0 no longer supports Queryable Encryption in
6410 MongoDB Server <7.0. Using Queryable Encryption libmongoc 1.24.0 and
6411 higher requires MongoDB Server >=7.0.
6412
6413 Using Queryable Encryption with libmongocrypt<1.8.0 on a MongoDB
6414 Server>=7.0, or using libmongocrypt>=1.8.0 on a MongoDB Server<6.0 will
6415 result in a server error when using the incompatible protocol.
6416
6417 SEE ALSO:
6418 The MongoDB Manual for Queryable Encryption
6419
6420
6421 Installation
6422 Using In-Use Encryption in the C driver requires the dependency libmon‐
6423 gocrypt. See the MongoDB Manual for libmongocrypt installation instruc‐
6424 tions.
6425
6426 Once libmongocrypt is installed, configure the C driver with -DEN‐
6427 ABLE_CLIENT_SIDE_ENCRYPTION=ON to require In-Use Encryption be enabled.
6428
6429 $ cd mongo-c-driver
6430 $ mkdir cmake-build && cd cmake-build
6431 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_CLIENT_SIDE_ENCRYPTION=ON ..
6432 $ cmake --build . --target install
6433
6434 API
6435 mongoc_client_encryption_t is used for explicit encryption and key man‐
6436 agement. mongoc_client_enable_auto_encryption() and
6437 mongoc_client_pool_enable_auto_encryption() is used to enable automatic
6438 encryption.
6439
6440 The Queryable Encryption and CSFLE features share much of the same API
6441 with some exceptions.
6442
6443 • The supported algorithms documented in
6444 mongoc_client_encryption_encrypt_opts_set_algorithm() do not apply to
6445 both features.
6446
6447 • mongoc_auto_encryption_opts_set_encrypted_fields_map() only applies
6448 to Queryable Encryption.
6449
6450 • mongoc_auto_encryption_opts_set_schema_map() only applies to CSFLE.
6451
6452 Query Analysis
6453 To support the automatic encryption feature, one of the following de‐
6454 pendencies are required:
6455
6456 • The mongocryptd executable. See the MongoDB Manual documentation:
6457 Install and Configure mongocryptd
6458
6459 • The crypt_shared library. See the MongoDB Manual documentation:
6460 Automatic Encryption Shared Library
6461
6462 A mongoc_client_t or mongoc_client_pool_t configured with auto encryp‐
6463 tion will automatically try to load the crypt_shared library. If load‐
6464 ing the crypt_shared library fails, the mongoc_client_t or
6465 mongoc_client_pool_t will try to spawn the mongocryptd process from the
6466 application's PATH. To configure use of crypt_shared and mongocryptd
6467 see mongoc_auto_encryption_opts_set_extra().
6468
6469 API Reference
6470 Initialization and cleanup
6471 Synopsis
6472 Initialize the MongoDB C Driver by calling mongoc_init() exactly once
6473 at the beginning of your program. It is responsible for initializing
6474 global state such as process counters, SSL, and threading primitives.
6475
6476 Exception to this is mongoc_log_set_handler(), which should be called
6477 before mongoc_init() or some log traces would not use your log handling
6478 function. See Custom Log Handlers for a detailed example.
6479
6480 Call mongoc_cleanup() exactly once at the end of your program to re‐
6481 lease all memory and other resources allocated by the driver. You must
6482 not call any other MongoDB C Driver functions after mongoc_cleanup().
6483 Note that mongoc_init() does not reinitialize the driver after
6484 mongoc_cleanup().
6485
6486 Deprecated feature: automatic initialization and cleanup
6487 On some platforms the driver can automatically call mongoc_init() be‐
6488 fore main, and call mongoc_cleanup() as the process exits. This is
6489 problematic in situations where related libraries also execute cleanup
6490 code on shutdown, and it creates inconsistent rules across platforms.
6491 Therefore the automatic initialization and cleanup feature is depre‐
6492 cated, and will be dropped in version 2.0. Meanwhile, for backward com‐
6493 patibility, the feature is enabled by default on platforms where it is
6494 available.
6495
6496 For portable, future-proof code, always call mongoc_init() and
6497 mongoc_cleanup() yourself, and configure the driver like:
6498
6499 cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF
6500
6501 Logging
6502 MongoDB C driver Logging Abstraction
6503
6504 Synopsis
6505 typedef enum {
6506 MONGOC_LOG_LEVEL_ERROR,
6507 MONGOC_LOG_LEVEL_CRITICAL,
6508 MONGOC_LOG_LEVEL_WARNING,
6509 MONGOC_LOG_LEVEL_MESSAGE,
6510 MONGOC_LOG_LEVEL_INFO,
6511 MONGOC_LOG_LEVEL_DEBUG,
6512 MONGOC_LOG_LEVEL_TRACE,
6513 } mongoc_log_level_t;
6514
6515 #define MONGOC_ERROR(...)
6516 #define MONGOC_CRITICAL(...)
6517 #define MONGOC_WARNING(...)
6518 #define MONGOC_MESSAGE(...)
6519 #define MONGOC_INFO(...)
6520 #define MONGOC_DEBUG(...)
6521
6522 typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
6523 const char *log_domain,
6524 const char *message,
6525 void *user_data);
6526
6527 void
6528 mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
6529 void
6530 mongoc_log (mongoc_log_level_t log_level,
6531 const char *log_domain,
6532 const char *format,
6533 ...) BSON_GNUC_PRINTF (3, 4);
6534 const char *
6535 mongoc_log_level_str (mongoc_log_level_t log_level);
6536 void
6537 mongoc_log_default_handler (mongoc_log_level_t log_level,
6538 const char *log_domain,
6539 const char *message,
6540 void *user_data);
6541 void
6542 mongoc_log_trace_enable (void);
6543 void
6544 mongoc_log_trace_disable (void);
6545
6546 The MongoDB C driver comes with an abstraction for logging that you can
6547 use in your application, or integrate with an existing logging system.
6548
6549 Macros
6550 To make logging a little less painful, various helper macros are pro‐
6551 vided. See the following example.
6552
6553 #undef MONGOC_LOG_DOMAIN
6554 #define MONGOC_LOG_DOMAIN "my-custom-domain"
6555
6556 MONGOC_WARNING ("An error occurred: %s", strerror (errno));
6557
6558 Custom Log Handlers
6559 The default log handler prints a timestamp and the log message to std‐
6560 out, or to stderr for warnings, critical messages, and errors.
6561 You can override the handler with mongoc_log_set_handler().
6562 Your handler function is called in a mutex for thread safety.
6563
6564 For example, you could register a custom handler to suppress messages
6565 at INFO level and below:
6566
6567 void
6568 my_logger (mongoc_log_level_t log_level,
6569 const char *log_domain,
6570 const char *message,
6571 void *user_data)
6572 {
6573 /* smaller values are more important */
6574 if (log_level < MONGOC_LOG_LEVEL_INFO) {
6575 mongoc_log_default_handler (log_level, log_domain, message, user_data);
6576 }
6577 }
6578
6579 int
6580 main (int argc, char *argv[])
6581 {
6582 mongoc_log_set_handler (my_logger, NULL);
6583 mongoc_init ();
6584
6585 /* ... your code ... */
6586
6587 mongoc_cleanup ();
6588 return 0;
6589 }
6590
6591 Note that in the example above mongoc_log_set_handler() is called be‐
6592 fore mongoc_init(). Otherwise, some log traces could not be processed
6593 by the log handler.
6594
6595 To restore the default handler:
6596
6597 mongoc_log_set_handler (mongoc_log_default_handler, NULL);
6598
6599 Disable logging
6600 To disable all logging, including warnings, critical messages and er‐
6601 rors, provide an empty log handler:
6602
6603 mongoc_log_set_handler (NULL, NULL);
6604
6605 Tracing
6606 If compiling your own copy of the MongoDB C driver, consider configur‐
6607 ing with -DENABLE_TRACING=ON to enable function tracing and hex dumps
6608 of network packets to STDERR and STDOUT during development and debug‐
6609 ging.
6610
6611 This is especially useful when debugging what may be going on inter‐
6612 nally in the driver.
6613
6614 Trace messages can be enabled and disabled by calling mon‐
6615 goc_log_trace_enable() and mongoc_log_trace_disable()
6616
6617 NOTE:
6618 Compiling the driver with -DENABLE_TRACING=ON will affect its per‐
6619 formance. Disabling tracing with mongoc_log_trace_disable() signifi‐
6620 cantly reduces the overhead, but cannot remove it completely.
6621 « libmongoc
6622
6623 Error Reporting
6624 Description
6625 Many C Driver functions report errors by returning false or -1 and
6626 filling out a bson_error_t structure with an error domain, error code,
6627 and message. Use domain to determine which subsystem generated the er‐
6628 ror, and code for the specific error. message is a human-readable error
6629 description.
6630
6631 SEE ALSO:
6632 Handling Errors in libbson.
6633
6634
6635┌────────────────────┬──────────────────────────────────┬────────────────────────────────────────────┐
6636│Code │ Description │ │
6637├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6638│MONGOC_ERROR_CLIENT │ MONGOC_ER‐ │ You tried to send a │
6639│ │ ROR_CLIENT_TOO_BIG │ message larger than │
6640│ │ │ the server's max │
6641│ │ │ message size. │
6642└────────────────────┴──────────────────────────────────┴────────────────────────────────────────────┘
6643
6644
6645
6646│ │ MONGOC_ER‐ │ Wrong credentials, │
6647│ │ ROR_CLIENT_AUTHEN‐ │ or failure sending │
6648│ │ TICATE │ or receiving au‐ │
6649│ │ │ thentication mes‐ │
6650│ │ │ sages. │
6651├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6652│ │ MONGOC_ER‐ │ You tried an TLS │
6653│ │ ROR_CLIENT_NO_AC‐ │ connection but the │
6654│ │ CEPTABLE_PEER │ driver was not │
6655│ │ │ built with TLS. │
6656├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6657│ │ MONGOC_ER‐ │ You began iterating │
6658│ │ ROR_CLIENT_IN_EX‐ │ an exhaust cursor, │
6659│ │ HAUST │ then tried to begin │
6660│ │ │ another operation │
6661│ │ │ with the same │
6662│ │ │ mongoc_client_t. │
6663├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6664│ │ MONGOC_ER‐ │ Failure related to │
6665│ │ ROR_CLIENT_SES‐ │ creating or using a │
6666│ │ SION_FAILURE │ logical session. │
6667├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6668│ │ MONGOC_ER‐ │ Failure related to │
6669│ │ ROR_CLIENT_IN‐ │ arguments passed │
6670│ │ VALID_ENCRYP‐ │ when initializing │
6671│ │ TION_ARG │ In-Use Encryption. │
6672├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6673│ │ MONGOC_ER‐ │ Failure related to │
6674│ │ ROR_CLIENT_IN‐ │ In-Use Encryption. │
6675│ │ VALID_ENCRYP‐ │ │
6676│ │ TION_STATE │ │
6677├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6678│ │ MONGOC_ER‐ │ You attempted to │
6679│ │ ROR_CLIENT_IN‐ │ connect to a Mon‐ │
6680│ │ VALID_LOAD_BALANCER │ goDB server behind │
6681│ │ │ a load balancer, │
6682│ │ │ but the server does │
6683│ │ │ not advertize load │
6684│ │ │ balanced support. │
6685├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6686│MONGOC_ERROR_STREAM │ MONGOC_ER‐ │ DNS failure. │
6687│ │ ROR_STREAM_NAME_RES‐ │ │
6688│ │ OLUTION │ │
6689├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6690│ │ MONGOC_ER‐ │ Timeout communicat‐ │
6691│ │ ROR_STREAM_SOCKET │ ing with server, or │
6692│ │ │ connection closed. │
6693├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6694│ │ MONGOC_ER‐ │ Failed to connect │
6695│ │ ROR_STREAM_CONNECT │ to server. │
6696├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6697│MONGOC_ERROR_PROTO‐ │ MONGOC_ERROR_PROTO‐ │ Corrupt response │
6698│COL │ COL_INVALID_REPLY │ from server. │
6699├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6700│ │ MONGOC_ERROR_PROTO‐ │ The server version │
6701│ │ COL_BAD_WIRE_VERSION │ is too old or too │
6702│ │ │ new to communicate │
6703│ │ │ with the driver. │
6704├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6705│MONGOC_ERROR_CURSOR │ MONGOC_ERROR_CUR‐ │ You passed bad ar‐ │
6706│ │ SOR_INVALID_CURSOR │ guments to │
6707│ │ │ mongoc_collection_find_with_opts(), │
6708│ │ │ or you called │
6709│ │ │ mongoc_cursor_next() │
6710│ │ │ on a completed or │
6711│ │ │ failed cursor, or │
6712│ │ │ the cursor timed │
6713│ │ │ out on the server. │
6714├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6715│ │ MONGOC_ER‐ │ A resume token was not returned in │
6716│ │ ROR_CHANGE_STREAM_NO_RE‐ │ a document found with │
6717│ │ SUME_TOKEN │ mongoc_change_stream_next() │
6718└────────────────────┴──────────────────────────────────┴────────────────────────────────────────────┘
6719
6720
6721│MONGOC_ERROR_QUERY │ MONGOC_ERROR_QUERY_FAIL‐ │ Error API Version 1: Server error │
6722│ │ URE │ from command or query. The server │
6723│ │ │ error message is in message. │
6724├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6725│MONGOC_ERROR_SERVER │ MONGOC_ERROR_QUERY_FAIL‐ │ Error API Version 2: Server error │
6726│ │ URE │ from command or query. The server │
6727│ │ │ error message is in message. │
6728├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6729│MONGOC_ERROR_SASL │ A SASL error code. │ man sasl_errors for a list of │
6730│ │ │ codes. │
6731├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6732│MONGOC_ERROR_BSON │ MONGOC_ERROR_BSON_IN‐ │ You passed an invalid or oversized │
6733│ │ VALID │ BSON document as a parameter, or │
6734│ │ │ called │
6735│ │ │ mongoc_collection_create_index() │
6736│ │ │ with invalid keys, or the server │
6737│ │ │ reply was corrupt. │
6738├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6739│MONGOC_ERROR_NAME‐ │ MONGOC_ERROR_NAME‐ │ You tried to create a collection │
6740│SPACE │ SPACE_INVALID │ with an invalid name. │
6741├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6742│MONGOC_ERROR_COM‐ │ MONGOC_ERROR_COMMAND_IN‐ │ Many functions set this error code │
6743│MAND │ VALID_ARG │ when passed bad parameters. Print │
6744│ │ │ the error message for details. │
6745├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6746│ │ MONGOC_ERROR_PROTO‐ │ You tried to use a command option │
6747│ │ COL_BAD_WIRE_VERSION │ the server does not support. │
6748├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6749│ │ MONGOC_ERROR_DUPLI‐ │ An insert or update failed because │
6750│ │ CATE_KEY │ because of a duplicate _id or other │
6751│ │ │ unique-index violation. │
6752├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6753│ │ MONGOC_ER‐ │ The operation failed because max‐ │
6754│ │ ROR_MAX_TIME_MS_EXPIRED │ TimeMS expired. │
6755├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6756│ │ MONGOC_ERROR_SERVER_SE‐ │ The serverId option for an opera‐ │
6757│ │ LECTION_INVALID_ID │ tion conflicts with the pinned │
6758│ │ │ server for that operation's client │
6759│ │ │ session (denoted by the sessionId │
6760│ │ │ option). │
6761├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6762│MONGOC_ERROR_COM‐ │ Error code from server. │ Error API Version 1: Server error │
6763│MAND │ │ from a command. The server error │
6764│ │ │ message is in message. │
6765├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6766│MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: Server error │
6767│ │ │ from a command. The server error │
6768│ │ │ message is in message. │
6769├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6770│MONGOC_ERROR_COL‐ │ MONGOC_ERROR_COLLEC‐ │ Invalid or empty input to │
6771│LECTION │ TION_INSERT_FAILED, MON‐ │ mongoc_collection_insert_one(), │
6772│ │ GOC_ERROR_COLLECTION_UP‐ │ mongoc_collection_insert_bulk(), │
6773│ │ DATE_FAILED, MONGOC_ER‐ │ mongoc_collection_update_one(), │
6774│ │ ROR_COLLEC‐ │ mongoc_collection_update_many(), │
6775│ │ TION_DELETE_FAILED. │ mongoc_collection_replace_one(), │
6776│ │ │ mongoc_collection_delete_one(), or │
6777│ │ │ mongoc_collection_delete_many(). │
6778├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6779│MONGOC_ERROR_COL‐ │ Error code from server. │ Error API Version 1: Server error │
6780│LECTION │ │ from │
6781│ │ │ mongoc_collection_insert_one(), │
6782│ │ │ mongoc_collection_insert_bulk(), │
6783│ │ │ mongoc_collection_update_one(), │
6784│ │ │ mongoc_collection_update_many(), │
6785│ │ │ mongoc_collection_replace_one(), │
6786├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6787│MONGOC_ERROR_SERVER │ Error code from server. │ Error API Version 2: Server error │
6788│ │ │ from │
6789│ │ │ mongoc_collection_insert_one(), │
6790│ │ │ mongoc_collection_insert_bulk(), │
6791│ │ │ mongoc_collection_update_one(), │
6792│ │ │ mongoc_collection_update_many(), │
6793│ │ │ mongoc_collection_replace_one(), │
6794└────────────────────┴──────────────────────────────────┴────────────────────────────────────────────┘
6795
6796│MONGOC_ERROR_GRIDFS │ MONGOC_ER‐ │ The GridFS file is missing a docu‐ │
6797│ │ ROR_GRIDFS_CHUNK_MISSING │ ment in its chunks collection. │
6798├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6799│ │ MONGOC_ERROR_GRIDFS_COR‐ │ A data inconsistency was detected │
6800│ │ RUPT │ in GridFS. │
6801├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6802│ │ MONGOC_ERROR_GRIDFS_IN‐ │ You passed a NULL filename to │
6803│ │ VALID_FILENAME │ mongoc_gridfs_remove_by_filename(). │
6804├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6805│ │ MONGOC_ERROR_GRIDFS_PRO‐ │ You called │
6806│ │ TOCOL_ERROR │ mongoc_gridfs_file_set_id() after │
6807│ │ │ mongoc_gridfs_file_save(), or tried │
6808│ │ │ to write on a closed GridFS stream. │
6809├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6810│ │ MONGOC_ER‐ │ A GridFS file is missing from files │
6811│ │ ROR_GRIDFS_BUCKET_FILE_NOT_FOUND │ collection. │
6812├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6813│ │ MONGOC_ER‐ │ An error occurred on a stream cre‐ │
6814│ │ ROR_GRIDFS_BUCKET_STREAM │ ated from a GridFS operation like │
6815│ │ │ mongoc_gridfs_bucket_upload_from_stream(). │
6816├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6817│MONGOC_ERROR_SCRAM │ MONGOC_ERROR_SCRAM_PROTOCOL_ER‐ │ Failure in SCRAM-SHA-1 authentication. │
6818│ │ ROR │ │
6819├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6820│MONGOC_ER‐ │ MONGOC_ERROR_SERVER_SELEC‐ │ No replica set member or mongos is avail‐ │
6821│ROR_SERVER_SELEC‐ │ TION_FAILURE │ able, or none matches your read prefer‐ │
6822│TION │ │ ence, or you supplied an invalid │
6823│ │ │ mongoc_read_prefs_t. │
6824├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6825│MONGOC_ER‐ │ Error code from server. │ There was a write concern error or timeout │
6826│ROR_WRITE_CONCERN │ │ from the server. │
6827├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6828│MONGOC_ERROR_TRANS‐ │ MONGOC_ERROR_TRANSACTION_INVALID │ You attempted to start a transaction when │
6829│ACTION │ │ one is already in progress, or commit or │
6830│ │ │ abort when there is no transaction. │
6831├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6832│MONGOC_ER‐ │ Error code produced by libmon‐ │ An error occurred in the library responsi‐ │
6833│ROR_CLIENT_SIDE_EN‐ │ gocrypt. │ ble for In-Use Encryption │
6834│CRYPTION │ │ │
6835├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6836│MONGOC_ERROR_AZURE │ MONGOC_ERROR_KMS_SERVER_HTTP │ An Azure HTTP service responded with an │
6837│ │ │ error status │
6838├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6839│ │ MONGOC_ERROR_KMS_SERVER_BAD_JSON │ An Azure service responded with invalid │
6840│ │ │ JSON data │
6841├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6842│MONGOC_ERROR_GCP │ MONGOC_ERROR_KMS_SERVER_HTTP │ A GCP HTTP service responded with an error │
6843│ │ │ status │
6844├────────────────────┼──────────────────────────────────┼────────────────────────────────────────────┤
6845│ │ MONGOC_ERROR_KMS_SERVER_BAD_JSON │ A GCP service responded with invalid JSON │
6846│ │ │ data │
6847└────────────────────┴──────────────────────────────────┴────────────────────────────────────────────┘
6848
6849 Error Labels
6850 In some cases your application must make decisions based on what cate‐
6851 gory of error the driver has returned, but these categories do not cor‐
6852 respond perfectly to an error domain or code. In such cases, error la‐
6853 bels provide a reliable way to determine how your application should
6854 respond to an error.
6855
6856 Any C Driver function that has a bson_t out-parameter named reply may
6857 include error labels to the reply, in the form of a BSON field named
6858 "errorLabels" containing an array of strings:
6859
6860 { "errorLabels": [ "TransientTransactionError" ] }
6861
6862 Use mongoc_error_has_label() to test if a reply contains a specific la‐
6863 bel. See mongoc_client_session_start_transaction() for example code
6864 that demonstrates the use of error labels in application logic.
6865
6866 The following error labels are currently defined. Future versions of
6867 MongoDB may introduce new labels.
6868
6869 TransientTransactionError
6870 Within a multi-document transaction, certain errors can leave the
6871 transaction in an unknown or aborted state. These include write con‐
6872 flicts, primary stepdowns, and network errors. In response, the appli‐
6873 cation should abort the transaction and try the same sequence of opera‐
6874 tions again in a new transaction.
6875
6876 UnknownTransactionCommitResult
6877 When mongoc_client_session_commit_transaction() encounters a network
6878 error or certain server errors, it is not known whether the transaction
6879 was committed. Applications should attempt to commit the transaction
6880 again until: the commit succeeds, the commit fails with an error not
6881 labeled "UnknownTransactionCommitResult", or the application chooses to
6882 give up.
6883
6884 Setting the Error API Version
6885 The driver's error reporting began with a design flaw: when the error
6886 domain is MONGOC_ERROR_COLLECTION, MONGOC_ERROR_QUERY, or MONGOC_ER‐
6887 ROR_COMMAND, the error code might originate from the server or the
6888 driver. An application cannot always know where an error originated,
6889 and therefore cannot tell what the code means.
6890
6891 For example, if mongoc_collection_update_one() sets the error's domain
6892 to MONGOC_ERROR_COLLECTION and its code to 24, the application cannot
6893 know whether 24 is the generic driver error code MONGOC_ERROR_COLLEC‐
6894 TION_UPDATE_FAILED or the specific server error code "LockTimeout".
6895
6896 To fix this flaw while preserving backward compatibility, the C Driver
6897 1.4 introduces "Error API Versions". Version 1, the default Error API
6898 Version, maintains the flawed behavior. Version 2 adds a new error do‐
6899 main, MONGOC_ERROR_SERVER. In Version 2, error codes originating on the
6900 server always have error domain MONGOC_ERROR_SERVER or MONGOC_ER‐
6901 ROR_WRITE_CONCERN. When the driver uses Version 2 the application can
6902 always determine the origin and meaning of error codes. New applica‐
6903 tions should use Version 2, and existing applications should be updated
6904 to use Version 2 as well.
6905
6906┌──────────────────────────────────────────────┬────────────────────┬─────────────────────┐
6907│Error Source │ API Version 1 │ API Version 2 │
6908├──────────────────────────────────────────────┼────────────────────┼─────────────────────┤
6909│mongoc_cursor_error() │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6910├──────────────────────────────────────────────┼────────────────────┼─────────────────────┤
6911│mongoc_client_command_with_opts(), │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6912│mongoc_database_command_with_opts(), │ │ │
6913│and other command │ │ │
6914│functions │ │ │
6915├──────────────────────────────────────────────┼────────────────────┼─────────────────────┤
6916│mongoc_collection_count_with_opts() │ MONGOC_ERROR_QUERY │ MONGOC_ERROR_SERVER │
6917│mongoc_client_get_database_names_with_opts(), │ │ │
6918│and other command helper functions │ │ │
6919├──────────────────────────────────────────────┼────────────────────┼─────────────────────┤
6920│mongoc_collection_insert_one() │ MONGOC_ERROR_COM‐ │ MONGOC_ERROR_SERVER │
6921│mongoc_collection_insert_bulk() │ MAND │ │
6922│mongoc_collection_update_one() │ │ │
6923│mongoc_collection_update_many() │ │ │
6924│mongoc_collection_replace_one() │ │ │
6925│mongoc_collection_delete_one() │ │ │
6926│mongoc_collection_delete_many() │ │ │
6927├──────────────────────────────────────────────┼────────────────────┼─────────────────────┤
6928│mongoc_bulk_operation_execute() │ MONGOC_ERROR_COM‐ │ MONGOC_ERROR_SERVER │
6929│ │ MAND │ │
6930├──────────────────────────────────────────────┼────────────────────┼─────────────────────┤
6931│Write-concern timeout │ MONGOC_ER‐ │ MONGOC_ER‐ │
6932│ │ ROR_WRITE_CONCERN │ ROR_WRITE_CONCERN │
6933└──────────────────────────────────────────────┴────────────────────┴─────────────────────┘
6934
6935 The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY
6936 and MONGOC_ERROR_API_VERSION_2. Set the version with
6937 mongoc_client_set_error_api() or mongoc_client_pool_set_error_api().
6938
6939 SEE ALSO:
6940 MongoDB Server Error Codes
6941
6942
6943 Object Lifecycle
6944 This page documents the order of creation and destruction for libmon‐
6945 goc's main struct types.
6946
6947 Clients and pools
6948 Call mongoc_init() once, before calling any other libmongoc functions,
6949 and call mongoc_cleanup() once before your program exits.
6950
6951 A program that uses libmongoc from multiple threads should create a
6952 mongoc_client_pool_t with mongoc_client_pool_new(). Each thread ac‐
6953 quires a mongoc_client_t from the pool with mongoc_client_pool_pop()
6954 and returns it with mongoc_client_pool_push() when the thread is fin‐
6955 ished using it. To destroy the pool, first return all clients, then
6956 call mongoc_client_pool_destroy().
6957
6958 If your program uses libmongoc from only one thread, create a
6959 mongoc_client_t directly with mongoc_client_new() or
6960 mongoc_client_new_from_uri(). Destroy it with mongoc_client_destroy().
6961
6962 Databases, collections, and related objects
6963 You can create a mongoc_database_t or mongoc_collection_t from a
6964 mongoc_client_t, and create a mongoc_cursor_t or
6965 mongoc_bulk_operation_t from a mongoc_collection_t.
6966
6967 Each of these objects must be destroyed before the client they were
6968 created from, but their lifetimes are otherwise independent.
6969
6970 GridFS objects
6971 You can create a mongoc_gridfs_t from a mongoc_client_t, create a
6972 mongoc_gridfs_file_t or mongoc_gridfs_file_list_t from a
6973 mongoc_gridfs_t, create a mongoc_gridfs_file_t from a
6974 mongoc_gridfs_file_list_t, and create a mongoc_stream_t from a
6975 mongoc_gridfs_file_t.
6976
6977 Each of these objects depends on the object it was created from. Always
6978 destroy GridFS objects in the reverse of the order they were created.
6979 The sole exception is that a mongoc_gridfs_file_t need not be destroyed
6980 before the mongoc_gridfs_file_list_t it was created from.
6981
6982 GridFS bucket objects
6983 Create mongoc_gridfs_bucket_t with a mongoc_database_t derived from a
6984 mongoc_client_t. The mongoc_database_t is independent from the
6985 mongoc_gridfs_bucket_t. But the mongoc_client_t must outlive the
6986 mongoc_gridfs_bucket_t.
6987
6988 A mongoc_stream_t may be created from the mongoc_gridfs_bucket_t. The
6989 mongoc_gridfs_bucket_t must outlive the mongoc_stream_t.
6990
6991 Sessions
6992 Start a session with mongoc_client_start_session(), use the session for
6993 a sequence of operations and multi-document transactions, then free it
6994 with mongoc_client_session_destroy(). Any mongoc_cursor_t or
6995 mongoc_change_stream_t using a session must be destroyed before the
6996 session, and a session must be destroyed before the mongoc_client_t it
6997 came from.
6998
6999 By default, sessions are causally consistent. To disable causal consis‐
7000 tency, before starting a session create a mongoc_session_opt_t with
7001 mongoc_session_opts_new() and call
7002 mongoc_session_opts_set_causal_consistency(), then free the struct with
7003 mongoc_session_opts_destroy().
7004
7005 Unacknowledged writes are prohibited with sessions.
7006
7007 A mongoc_client_session_t must be used by only one thread at a time.
7008 Due to session pooling, mongoc_client_start_session() may return a ses‐
7009 sion that has been idle for some time and is about to be closed after
7010 its idle timeout. Use the session within one minute of acquiring it to
7011 refresh the session and avoid a timeout.
7012
7013 Client Side Encryption
7014 When configuring a mongoc_client_t for automatic encryption via
7015 mongoc_client_enable_auto_encryption(), if a separate key vault client
7016 is set in the options (via
7017 mongoc_auto_encryption_opts_set_keyvault_client()) the key vault client
7018 must outlive the encrypted client.
7019
7020 When configuring a mongoc_client_pool_t for automatic encryption via
7021 mongoc_client_pool_enable_auto_encryption(), if a separate key vault
7022 client pool is set in the options (via
7023 mongoc_auto_encryption_opts_set_keyvault_client_pool()) the key vault
7024 client pool must outlive the encrypted client pool.
7025
7026 When creating a mongoc_client_encryption_t, the configured key vault
7027 client (set via mongoc_client_encryption_opts_set_keyvault_client())
7028 must outlive the mongoc_client_encryption_t.
7029
7030 GridFS
7031 The C driver includes two APIs for GridFS.
7032
7033 The older API consists of mongoc_gridfs_t and its derivatives. It con‐
7034 tains deprecated API, does not support read preferences, and is not
7035 recommended in new applications. It does not conform to the MongoDB
7036 GridFS specification.
7037
7038 The newer API consists of mongoc_gridfs_bucket_t and allows upload‐
7039 ing/downloading through derived mongoc_stream_t objects. It conforms to
7040 the MongoDB GridFS specification.
7041
7042 There is not always a straightforward upgrade path from an application
7043 built with mongoc_gridfs_t to mongoc_gridfs_bucket_t (e.g. a
7044 mongoc_gridfs_file_t provides functions to seek but mongoc_stream_t
7045 does not). But users are encouraged to upgrade when possible.
7046
7047 mongoc_auto_encryption_opts_t
7048 Options for enabling automatic encryption and decryption for In-Use En‐
7049 cryption.
7050
7051 Synopsis
7052 typedef struct _mongoc_auto_encryption_opts_t mongoc_auto_encryption_opts_t;
7053
7054 SEE ALSO:
7055 In-Use Encryption
7056
7057
7058 mongoc_bulk_operation_t
7059 Bulk Write Operations
7060
7061 Synopsis
7062 typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t;
7063
7064 The opaque type mongoc_bulk_operation_t provides an abstraction for
7065 submitting multiple write operations as a single batch.
7066
7067 After adding all of the write operations to the mongoc_bulk_opera‐
7068 tion_t, call mongoc_bulk_operation_execute() to execute the operation.
7069
7070 WARNING:
7071 It is only valid to call mongoc_bulk_operation_execute() once. The
7072 mongoc_bulk_operation_t must be destroyed afterwards.
7073
7074 SEE ALSO:
7075 Bulk Write Operations
7076
7077
7078 mongoc_change_stream_t
7079 Synopsis
7080 #include <mongoc/mongoc.h>
7081
7082 typedef struct _mongoc_change_stream_t mongoc_change_stream_t;
7083
7084 mongoc_change_stream_t is a handle to a change stream. A collection
7085 change stream can be obtained using mongoc_collection_watch().
7086
7087 It is recommended to use a mongoc_change_stream_t and its functions in‐
7088 stead of a raw aggregation with a $changeStream stage. For more infor‐
7089 mation see the MongoDB Manual Entry on Change Streams.
7090
7091 Example
7092 example-collection-watch.c
7093
7094 #include <mongoc/mongoc.h>
7095
7096 int
7097 main (void)
7098 {
7099 bson_t empty = BSON_INITIALIZER;
7100 const bson_t *doc;
7101 bson_t *to_insert = BCON_NEW ("x", BCON_INT32 (1));
7102 const bson_t *err_doc;
7103 bson_error_t error;
7104 const char *uri_string;
7105 mongoc_uri_t *uri;
7106 mongoc_client_t *client;
7107 mongoc_collection_t *coll;
7108 mongoc_change_stream_t *stream;
7109 mongoc_write_concern_t *wc = mongoc_write_concern_new ();
7110 bson_t opts = BSON_INITIALIZER;
7111 bool r;
7112
7113 mongoc_init ();
7114
7115 uri_string = "mongodb://"
7116 "localhost:27017,localhost:27018,localhost:"
7117 "27019/db?replicaSet=rs0";
7118
7119 uri = mongoc_uri_new_with_error (uri_string, &error);
7120 if (!uri) {
7121 fprintf (stderr,
7122 "failed to parse URI: %s\n"
7123 "error message: %s\n",
7124 uri_string,
7125 error.message);
7126 return EXIT_FAILURE;
7127 }
7128
7129 client = mongoc_client_new_from_uri (uri);
7130 if (!client) {
7131 return EXIT_FAILURE;
7132 }
7133
7134 coll = mongoc_client_get_collection (client, "db", "coll");
7135 stream = mongoc_collection_watch (coll, &empty, NULL);
7136
7137 mongoc_write_concern_set_wmajority (wc, 10000);
7138 mongoc_write_concern_append (wc, &opts);
7139 r = mongoc_collection_insert_one (coll, to_insert, &opts, NULL, &error);
7140 if (!r) {
7141 fprintf (stderr, "Error: %s\n", error.message);
7142 return EXIT_FAILURE;
7143 }
7144
7145 while (mongoc_change_stream_next (stream, &doc)) {
7146 char *as_json = bson_as_relaxed_extended_json (doc, NULL);
7147 fprintf (stderr, "Got document: %s\n", as_json);
7148 bson_free (as_json);
7149 }
7150
7151 if (mongoc_change_stream_error_document (stream, &error, &err_doc)) {
7152 if (!bson_empty (err_doc)) {
7153 fprintf (stderr,
7154 "Server Error: %s\n",
7155 bson_as_relaxed_extended_json (err_doc, NULL));
7156 } else {
7157 fprintf (stderr, "Client Error: %s\n", error.message);
7158 }
7159 return EXIT_FAILURE;
7160 }
7161
7162 bson_destroy (to_insert);
7163 mongoc_write_concern_destroy (wc);
7164 bson_destroy (&opts);
7165 mongoc_change_stream_destroy (stream);
7166 mongoc_collection_destroy (coll);
7167 mongoc_uri_destroy (uri);
7168 mongoc_client_destroy (client);
7169 mongoc_cleanup ();
7170
7171 return EXIT_SUCCESS;
7172 }
7173
7174
7175 Starting and Resuming
7176 All watch functions accept several options to indicate where a change
7177 stream should start returning changes from: resumeAfter, startAfter,
7178 and startAtOperationTime.
7179
7180 All changes returned by mongoc_change_stream_next() include a resume
7181 token in the _id field. MongoDB 4.2 also includes an additional resume
7182 token in each "aggregate" and "getMore" command response, which points
7183 to the end of that response's batch. The current token is automatically
7184 cached by libmongoc. In the event of an error, libmongoc attempts to
7185 recreate the change stream starting where it left off by passing the
7186 cached resume token. libmongoc only attempts to resume once, but client
7187 applications can access the cached resume token with
7188 mongoc_change_stream_get_resume_token() and use it for their own resume
7189 logic by passing it as either the resumeAfter or startAfter option.
7190
7191 Additionally, change streams can start returning changes at an opera‐
7192 tion time by using the startAtOperationTime field. This can be the
7193 timestamp returned in the operationTime field of a command reply.
7194
7195 resumeAfter, startAfter, and startAtOperationTime are mutually exclu‐
7196 sive options. Setting more than one will result in a server error.
7197
7198 The following example implements custom resuming logic, persisting the
7199 resume token in a file.
7200
7201 example-resume.c
7202
7203 #include <mongoc/mongoc.h>
7204
7205 /* An example implementation of custom resume logic in a change stream.
7206 * example-resume starts a client-wide change stream and persists the resume
7207 * token in a file "resume-token.json". On restart, if "resume-token.json"
7208 * exists, the change stream starts watching after the persisted resume token.
7209 *
7210 * This behavior allows a user to exit example-resume, and restart it later
7211 * without missing any change events.
7212 */
7213 #include <unistd.h>
7214
7215 static const char *RESUME_TOKEN_PATH = "resume-token.json";
7216
7217 static bool
7218 _save_resume_token (const bson_t *doc)
7219 {
7220 FILE *file_stream;
7221 bson_iter_t iter;
7222 bson_t resume_token_doc;
7223 char *as_json = NULL;
7224 size_t as_json_len;
7225 ssize_t r, n_written;
7226 const bson_value_t *resume_token;
7227
7228 if (!bson_iter_init_find (&iter, doc, "_id")) {
7229 fprintf (stderr, "reply does not contain operationTime.");
7230 return false;
7231 }
7232 resume_token = bson_iter_value (&iter);
7233 /* store the resume token in a document, { resumeAfter: <resume token> }
7234 * which we can later append easily. */
7235 file_stream = fopen (RESUME_TOKEN_PATH, "w+");
7236 if (!file_stream) {
7237 fprintf (stderr, "failed to open %s for writing\n", RESUME_TOKEN_PATH);
7238 return false;
7239 }
7240 bson_init (&resume_token_doc);
7241 BSON_APPEND_VALUE (&resume_token_doc, "resumeAfter", resume_token);
7242 as_json = bson_as_canonical_extended_json (&resume_token_doc, &as_json_len);
7243 bson_destroy (&resume_token_doc);
7244 n_written = 0;
7245 while (n_written < as_json_len) {
7246 r = fwrite ((void *) (as_json + n_written),
7247 sizeof (char),
7248 as_json_len - n_written,
7249 file_stream);
7250 if (r == -1) {
7251 fprintf (stderr, "failed to write to %s\n", RESUME_TOKEN_PATH);
7252 bson_free (as_json);
7253 fclose (file_stream);
7254 return false;
7255 }
7256 n_written += r;
7257 }
7258
7259 bson_free (as_json);
7260 fclose (file_stream);
7261 return true;
7262 }
7263
7264 bool
7265 _load_resume_token (bson_t *opts)
7266 {
7267 bson_error_t error;
7268 bson_json_reader_t *reader;
7269 bson_t doc;
7270
7271 /* if the file does not exist, skip. */
7272 if (-1 == access (RESUME_TOKEN_PATH, R_OK)) {
7273 return true;
7274 }
7275 reader = bson_json_reader_new_from_file (RESUME_TOKEN_PATH, &error);
7276 if (!reader) {
7277 fprintf (stderr,
7278 "failed to open %s for reading: %s\n",
7279 RESUME_TOKEN_PATH,
7280 error.message);
7281 return false;
7282 }
7283
7284 bson_init (&doc);
7285 if (-1 == bson_json_reader_read (reader, &doc, &error)) {
7286 fprintf (stderr, "failed to read doc from %s\n", RESUME_TOKEN_PATH);
7287 bson_destroy (&doc);
7288 bson_json_reader_destroy (reader);
7289 return false;
7290 }
7291
7292 printf ("found cached resume token in %s, resuming change stream.\n",
7293 RESUME_TOKEN_PATH);
7294
7295 bson_concat (opts, &doc);
7296 bson_destroy (&doc);
7297 bson_json_reader_destroy (reader);
7298 return true;
7299 }
7300
7301 int
7302 main (void)
7303 {
7304 int exit_code = EXIT_FAILURE;
7305 const char *uri_string;
7306 mongoc_uri_t *uri = NULL;
7307 bson_error_t error;
7308 mongoc_client_t *client = NULL;
7309 bson_t pipeline = BSON_INITIALIZER;
7310 bson_t opts = BSON_INITIALIZER;
7311 mongoc_change_stream_t *stream = NULL;
7312 const bson_t *doc;
7313
7314 const int max_time = 30; /* max amount of time, in seconds, that
7315 mongoc_change_stream_next can block. */
7316
7317 mongoc_init ();
7318 uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
7319 uri = mongoc_uri_new_with_error (uri_string, &error);
7320 if (!uri) {
7321 fprintf (stderr,
7322 "failed to parse URI: %s\n"
7323 "error message: %s\n",
7324 uri_string,
7325 error.message);
7326 goto cleanup;
7327 }
7328
7329 client = mongoc_client_new_from_uri (uri);
7330 if (!client) {
7331 goto cleanup;
7332 }
7333
7334 if (!_load_resume_token (&opts)) {
7335 goto cleanup;
7336 }
7337 BSON_APPEND_INT64 (&opts, "maxAwaitTimeMS", max_time * 1000);
7338
7339 printf ("listening for changes on the client (max %d seconds).\n", max_time);
7340 stream = mongoc_client_watch (client, &pipeline, &opts);
7341
7342 while (mongoc_change_stream_next (stream, &doc)) {
7343 char *as_json;
7344
7345 as_json = bson_as_canonical_extended_json (doc, NULL);
7346 printf ("change received: %s\n", as_json);
7347 bson_free (as_json);
7348 if (!_save_resume_token (doc)) {
7349 goto cleanup;
7350 }
7351 }
7352
7353 exit_code = EXIT_SUCCESS;
7354
7355 cleanup:
7356 mongoc_uri_destroy (uri);
7357 bson_destroy (&pipeline);
7358 bson_destroy (&opts);
7359 mongoc_change_stream_destroy (stream);
7360 mongoc_client_destroy (client);
7361 mongoc_cleanup ();
7362 return exit_code;
7363 }
7364
7365
7366 The following example shows using startAtOperationTime to synchronize a
7367 change stream with another operation.
7368
7369 example-start-at-optime.c
7370
7371 /* An example of starting a change stream with startAtOperationTime. */
7372 #include <mongoc/mongoc.h>
7373
7374 int
7375 main (void)
7376 {
7377 int exit_code = EXIT_FAILURE;
7378 const char *uri_string;
7379 mongoc_uri_t *uri = NULL;
7380 bson_error_t error;
7381 mongoc_client_t *client = NULL;
7382 mongoc_collection_t *coll = NULL;
7383 bson_t pipeline = BSON_INITIALIZER;
7384 bson_t opts = BSON_INITIALIZER;
7385 mongoc_change_stream_t *stream = NULL;
7386 bson_iter_t iter;
7387 const bson_t *doc;
7388 bson_value_t cached_operation_time = {0};
7389 int i;
7390 bool r;
7391
7392 mongoc_init ();
7393 uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
7394 uri = mongoc_uri_new_with_error (uri_string, &error);
7395 if (!uri) {
7396 fprintf (stderr,
7397 "failed to parse URI: %s\n"
7398 "error message: %s\n",
7399 uri_string,
7400 error.message);
7401 goto cleanup;
7402 }
7403
7404 client = mongoc_client_new_from_uri (uri);
7405 if (!client) {
7406 goto cleanup;
7407 }
7408
7409 /* insert five documents. */
7410 coll = mongoc_client_get_collection (client, "db", "coll");
7411 for (i = 0; i < 5; i++) {
7412 bson_t reply;
7413 bson_t *insert_cmd = BCON_NEW ("insert",
7414 "coll",
7415 "documents",
7416 "[",
7417 "{",
7418 "x",
7419 BCON_INT64 (i),
7420 "}",
7421 "]");
7422
7423 r = mongoc_collection_write_command_with_opts (
7424 coll, insert_cmd, NULL, &reply, &error);
7425 bson_destroy (insert_cmd);
7426 if (!r) {
7427 bson_destroy (&reply);
7428 fprintf (stderr, "failed to insert: %s\n", error.message);
7429 goto cleanup;
7430 }
7431 if (i == 0) {
7432 /* cache the operation time in the first reply. */
7433 if (bson_iter_init_find (&iter, &reply, "operationTime")) {
7434 bson_value_copy (bson_iter_value (&iter), &cached_operation_time);
7435 } else {
7436 fprintf (stderr, "reply does not contain operationTime.");
7437 bson_destroy (&reply);
7438 goto cleanup;
7439 }
7440 }
7441 bson_destroy (&reply);
7442 }
7443
7444 /* start a change stream at the first returned operationTime. */
7445 BSON_APPEND_VALUE (&opts, "startAtOperationTime", &cached_operation_time);
7446 stream = mongoc_collection_watch (coll, &pipeline, &opts);
7447
7448 /* since the change stream started at the operation time of the first
7449 * insert, the five inserts are returned. */
7450 printf ("listening for changes on db.coll:\n");
7451 while (mongoc_change_stream_next (stream, &doc)) {
7452 char *as_json;
7453
7454 as_json = bson_as_canonical_extended_json (doc, NULL);
7455 printf ("change received: %s\n", as_json);
7456 bson_free (as_json);
7457 }
7458
7459 exit_code = EXIT_SUCCESS;
7460
7461 cleanup:
7462 mongoc_uri_destroy (uri);
7463 bson_destroy (&pipeline);
7464 bson_destroy (&opts);
7465 if (cached_operation_time.value_type) {
7466 bson_value_destroy (&cached_operation_time);
7467 }
7468 mongoc_change_stream_destroy (stream);
7469 mongoc_collection_destroy (coll);
7470 mongoc_client_destroy (client);
7471 mongoc_cleanup ();
7472 return exit_code;
7473 }
7474
7475
7476 mongoc_client_encryption_t
7477 Synopsis
7478 typedef struct _mongoc_client_encryption_t mongoc_client_encryption_t;
7479
7480 mongoc_client_encryption_t provides utility functions for In-Use En‐
7481 cryption.
7482
7483 Thread Safety
7484 mongoc_client_encryption_t is NOT thread-safe and should only be used
7485 in the same thread as the mongoc_client_t that is configured via
7486 mongoc_client_encryption_opts_set_keyvault_client().
7487
7488 Lifecycle
7489 The key vault client, configured via
7490 mongoc_client_encryption_opts_set_keyvault_client(), must outlive the
7491 mongoc_client_encryption_t.
7492
7493 SEE ALSO:
7494 mongoc_client_enable_auto_encryption()
7495
7496 mongoc_client_pool_enable_auto_encryption()
7497
7498 In-Use Encryption for libmongoc
7499
7500 The MongoDB Manual for Client-Side Field Level Encryption
7501
7502 The MongoDB Manual for Queryable Encryption
7503
7504
7505 mongoc_client_encryption_datakey_opts_t
7506 Synopsis
7507 typedef struct _mongoc_client_encryption_datakey_opts_t mongoc_client_encryption_datakey_opts_t;
7508
7509 Used to set options for mongoc_client_encryption_create_datakey().
7510
7511 SEE ALSO:
7512 mongoc_client_encryption_create_datakey()
7513
7514
7515 mongoc_client_encryption_rewrap_many_datakey_result_t
7516 Synopsis
7517 typedef struct _mongoc_client_encryption_rewrap_many_datakey_result_t
7518 mongoc_client_encryption_rewrap_many_datakey_result_t;
7519
7520 Used to access the result of
7521 mongoc_client_encryption_rewrap_many_datakey().
7522
7523 SEE ALSO:
7524 mongoc_client_encryption_rewrap_many_datakey()
7525
7526
7527 mongoc_client_encryption_encrypt_opts_t
7528 Synopsis
7529 typedef struct _mongoc_client_encryption_encrypt_opts_t mongoc_client_encryption_encrypt_opts_t;
7530
7531 Used to set options for mongoc_client_encryption_encrypt().
7532
7533 SEE ALSO:
7534 mongoc_client_encryption_encrypt()
7535
7536
7537 mongoc_client_encryption_encrypt_range_opts_t
7538 Synopsis
7539 typedef struct _mongoc_client_encryption_encrypt_range_opts_t mongoc_client_encryption_encrypt_range_opts_t;
7540
7541 IMPORTANT:
7542 The Range algorithm is experimental only and not intended for public
7543 use. It is subject to breaking changes. This API is part of the ex‐
7544 perimental Queryable Encryption API and may be subject to breaking
7545 changes in future releases.
7546
7547 New in version 1.24.0.
7548
7549
7550 RangeOpts specifies index options for a Queryable Encryption field sup‐
7551 porting "rangePreview" queries. Used to set options for
7552 mongoc_client_encryption_encrypt().
7553
7554 The options min, max, sparsity, and range must match the values set in
7555 the encryptedFields of the destination collection.
7556
7557 For double and decimal128 fields, min/max/precision must all be set, or
7558 all be unset.
7559
7560 SEE ALSO:
7561 mongoc_client_encryption_encrypt()
7562 mongoc_client_encryption_encrypt_opts_t
7563
7564
7565 mongoc_client_encryption_opts_t
7566 Synopsis
7567 typedef struct _mongoc_client_encryption_opts_t mongoc_client_encryption_opts_t;
7568
7569 Used to set options for mongoc_client_encryption_new().
7570
7571 SEE ALSO:
7572 mongoc_client_encryption_new()
7573
7574
7575 mongoc_client_pool_t
7576 A connection pool for multi-threaded programs. See Connection Pooling.
7577
7578 Synopsis
7579 typedef struct _mongoc_client_pool_t mongoc_client_pool_t
7580
7581 mongoc_client_pool_t is the basis for multi-threading in the MongoDB C
7582 driver. Since mongoc_client_t structures are not thread-safe, this
7583 structure is used to retrieve a new mongoc_client_t for a given thread.
7584 This structure is thread-safe, except for its destructor method,
7585 mongoc_client_pool_destroy(), which is not thread-safe and must only be
7586 called from one thread.
7587
7588 Example
7589 example-pool.c
7590
7591 /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
7592 * libmongoc-1.0) */
7593
7594 /* ./example-pool [CONNECTION_STRING] */
7595
7596 #include <mongoc/mongoc.h>
7597 #include <pthread.h>
7598 #include <stdio.h>
7599
7600 static pthread_mutex_t mutex;
7601 static bool in_shutdown = false;
7602
7603 static void *
7604 worker (void *data)
7605 {
7606 mongoc_client_pool_t *pool = data;
7607 mongoc_client_t *client;
7608 bson_t ping = BSON_INITIALIZER;
7609 bson_error_t error;
7610 bool r;
7611
7612 BSON_APPEND_INT32 (&ping, "ping", 1);
7613
7614 while (true) {
7615 client = mongoc_client_pool_pop (pool);
7616 /* Do something with client. If you are writing an HTTP server, you
7617 * probably only want to hold onto the client for the portion of the
7618 * request performing database queries.
7619 */
7620 r = mongoc_client_command_simple (
7621 client, "admin", &ping, NULL, NULL, &error);
7622
7623 if (!r) {
7624 fprintf (stderr, "%s\n", error.message);
7625 }
7626
7627 mongoc_client_pool_push (pool, client);
7628
7629 pthread_mutex_lock (&mutex);
7630 if (in_shutdown || !r) {
7631 pthread_mutex_unlock (&mutex);
7632 break;
7633 }
7634
7635 pthread_mutex_unlock (&mutex);
7636 }
7637
7638 bson_destroy (&ping);
7639 return NULL;
7640 }
7641
7642 int
7643 main (int argc, char *argv[])
7644 {
7645 const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
7646 mongoc_uri_t *uri;
7647 bson_error_t error;
7648 mongoc_client_pool_t *pool;
7649 pthread_t threads[10];
7650 unsigned i;
7651 void *ret;
7652
7653 pthread_mutex_init (&mutex, NULL);
7654 mongoc_init ();
7655
7656 if (argc > 1) {
7657 uri_string = argv[1];
7658 }
7659
7660 uri = mongoc_uri_new_with_error (uri_string, &error);
7661 if (!uri) {
7662 fprintf (stderr,
7663 "failed to parse URI: %s\n"
7664 "error message: %s\n",
7665 uri_string,
7666 error.message);
7667 return EXIT_FAILURE;
7668 }
7669
7670 pool = mongoc_client_pool_new (uri);
7671 mongoc_client_pool_set_error_api (pool, 2);
7672
7673 for (i = 0; i < 10; i++) {
7674 pthread_create (&threads[i], NULL, worker, pool);
7675 }
7676
7677 sleep (10);
7678 pthread_mutex_lock (&mutex);
7679 in_shutdown = true;
7680 pthread_mutex_unlock (&mutex);
7681
7682 for (i = 0; i < 10; i++) {
7683 pthread_join (threads[i], &ret);
7684 }
7685
7686 mongoc_client_pool_destroy (pool);
7687 mongoc_uri_destroy (uri);
7688
7689 mongoc_cleanup ();
7690
7691 return EXIT_SUCCESS;
7692 }
7693
7694
7695 mongoc_client_session_t
7696 Use a session for a sequence of operations, optionally with causal con‐
7697 sistency. See the MongoDB Manual Entry for Causal Consistency.
7698
7699 Synopsis
7700 Start a session with mongoc_client_start_session(), use the session for
7701 a sequence of operations and multi-document transactions, then free it
7702 with mongoc_client_session_destroy(). Any mongoc_cursor_t or
7703 mongoc_change_stream_t using a session must be destroyed before the
7704 session, and a session must be destroyed before the mongoc_client_t it
7705 came from.
7706
7707 By default, sessions are causally consistent. To disable causal consis‐
7708 tency, before starting a session create a mongoc_session_opt_t with
7709 mongoc_session_opts_new() and call
7710 mongoc_session_opts_set_causal_consistency(), then free the struct with
7711 mongoc_session_opts_destroy().
7712
7713 Unacknowledged writes are prohibited with sessions.
7714
7715 A mongoc_client_session_t must be used by only one thread at a time.
7716 Due to session pooling, mongoc_client_start_session() may return a ses‐
7717 sion that has been idle for some time and is about to be closed after
7718 its idle timeout. Use the session within one minute of acquiring it to
7719 refresh the session and avoid a timeout.
7720
7721 Fork Safety
7722 A mongoc_client_session_t is only usable in the parent process after a
7723 fork. The child process must call mongoc_client_reset() on the client
7724 field.
7725
7726 Example
7727 example-session.c
7728
7729 /* gcc example-session.c -o example-session \
7730 * $(pkg-config --cflags --libs libmongoc-1.0) */
7731
7732 /* ./example-session [CONNECTION_STRING] */
7733
7734 #include <stdio.h>
7735 #include <mongoc/mongoc.h>
7736
7737
7738 int
7739 main (int argc, char *argv[])
7740 {
7741 int exit_code = EXIT_FAILURE;
7742
7743 mongoc_client_t *client = NULL;
7744 const char *uri_string = "mongodb://127.0.0.1/?appname=session-example";
7745 mongoc_uri_t *uri = NULL;
7746 mongoc_client_session_t *client_session = NULL;
7747 mongoc_collection_t *collection = NULL;
7748 bson_error_t error;
7749 bson_t *selector = NULL;
7750 bson_t *update = NULL;
7751 bson_t *update_opts = NULL;
7752 bson_t *find_opts = NULL;
7753 mongoc_read_prefs_t *secondary = NULL;
7754 mongoc_cursor_t *cursor = NULL;
7755 const bson_t *doc;
7756 char *str;
7757 bool r;
7758
7759 mongoc_init ();
7760
7761 if (argc > 1) {
7762 uri_string = argv[1];
7763 }
7764
7765 uri = mongoc_uri_new_with_error (uri_string, &error);
7766 if (!uri) {
7767 fprintf (stderr,
7768 "failed to parse URI: %s\n"
7769 "error message: %s\n",
7770 uri_string,
7771 error.message);
7772 goto done;
7773 }
7774
7775 client = mongoc_client_new_from_uri (uri);
7776 if (!client) {
7777 goto done;
7778 }
7779
7780 mongoc_client_set_error_api (client, 2);
7781
7782 /* pass NULL for options - by default the session is causally consistent */
7783 client_session = mongoc_client_start_session (client, NULL, &error);
7784 if (!client_session) {
7785 fprintf (stderr, "Failed to start session: %s\n", error.message);
7786 goto done;
7787 }
7788
7789 collection = mongoc_client_get_collection (client, "test", "collection");
7790 selector = BCON_NEW ("_id", BCON_INT32 (1));
7791 update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}");
7792 update_opts = bson_new ();
7793 if (!mongoc_client_session_append (client_session, update_opts, &error)) {
7794 fprintf (stderr, "Could not add session to opts: %s\n", error.message);
7795 goto done;
7796 }
7797
7798 r = mongoc_collection_update_one (
7799 collection, selector, update, update_opts, NULL /* reply */, &error);
7800
7801 if (!r) {
7802 fprintf (stderr, "Update failed: %s\n", error.message);
7803 goto done;
7804 }
7805
7806 bson_destroy (selector);
7807 selector = BCON_NEW ("_id", BCON_INT32 (1));
7808 secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
7809
7810 find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000));
7811 if (!mongoc_client_session_append (client_session, find_opts, &error)) {
7812 fprintf (stderr, "Could not add session to opts: %s\n", error.message);
7813 goto done;
7814 };
7815
7816 /* read from secondary. since we're in a causally consistent session, the
7817 * data is guaranteed to reflect the update we did on the primary. the query
7818 * blocks waiting for the secondary to catch up, if necessary, or times out
7819 * and fails after 2000 ms.
7820 */
7821 cursor = mongoc_collection_find_with_opts (
7822 collection, selector, find_opts, secondary);
7823
7824 while (mongoc_cursor_next (cursor, &doc)) {
7825 str = bson_as_json (doc, NULL);
7826 fprintf (stdout, "%s\n", str);
7827 bson_free (str);
7828 }
7829
7830 if (mongoc_cursor_error (cursor, &error)) {
7831 fprintf (stderr, "Cursor Failure: %s\n", error.message);
7832 goto done;
7833 }
7834
7835 exit_code = EXIT_SUCCESS;
7836
7837 done:
7838 if (find_opts) {
7839 bson_destroy (find_opts);
7840 }
7841 if (update) {
7842 bson_destroy (update);
7843 }
7844 if (selector) {
7845 bson_destroy (selector);
7846 }
7847 if (update_opts) {
7848 bson_destroy (update_opts);
7849 }
7850 if (secondary) {
7851 mongoc_read_prefs_destroy (secondary);
7852 }
7853 /* destroy cursor, collection, session before the client they came from */
7854 if (cursor) {
7855 mongoc_cursor_destroy (cursor);
7856 }
7857 if (collection) {
7858 mongoc_collection_destroy (collection);
7859 }
7860 if (client_session) {
7861 mongoc_client_session_destroy (client_session);
7862 }
7863 if (uri) {
7864 mongoc_uri_destroy (uri);
7865 }
7866 if (client) {
7867 mongoc_client_destroy (client);
7868 }
7869
7870 mongoc_cleanup ();
7871
7872 return exit_code;
7873 }
7874
7875
7876 mongoc_client_session_with_transaction_cb_t
7877 Synopsis
7878 typedef bool (*mongoc_client_session_with_transaction_cb_t) (
7879 mongoc_client_session_t *session,
7880 void *ctx,
7881 bson_t **reply,
7882 bson_error_t *error);
7883
7884 Provide this callback to mongoc_client_session_with_transaction(). The
7885 callback should run a sequence of operations meant to be contained
7886 within a transaction. The callback should not attempt to start or com‐
7887 mit transactions.
7888
7889 Parameters
7890 • session: A mongoc_client_session_t.
7891
7892 • ctx: A void* set to the the user-provided ctx passed to
7893 mongoc_client_session_with_transaction().
7894
7895 • reply: An optional location for a bson_t or NULL. The callback should
7896 set this if it runs any operations against the server and receives
7897 replies.
7898
7899 • error: A bson_error_t. The callback should set this if it receives
7900 any errors while running operations against the server.
7901
7902 Return
7903 Returns true for success and false on failure. If cb returns false then
7904 it should also set error.
7905
7906 SEE ALSO:
7907 mongoc_client_session_with_transaction()
7908
7909
7910 mongoc_client_t
7911 A single-threaded MongoDB connection. See Connection Pooling.
7912
7913 Synopsis
7914 typedef struct _mongoc_client_t mongoc_client_t;
7915
7916 typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
7917 const mongoc_uri_t *uri,
7918 const mongoc_host_list_t *host,
7919 void *user_data,
7920 bson_error_t *error);
7921
7922 mongoc_client_t is an opaque type that provides access to a MongoDB
7923 server, replica set, or sharded cluster. It maintains management of un‐
7924 derlying sockets and routing to individual nodes based on
7925 mongoc_read_prefs_t or mongoc_write_concern_t.
7926
7927 Streams
7928 The underlying transport for a given client can be customized, wrapped
7929 or replaced by any implementation that fulfills mongoc_stream_t. A cus‐
7930 tom transport can be set with mongoc_client_set_stream_initiator().
7931
7932 Thread Safety
7933 mongoc_client_t is NOT thread-safe and should only be used from one
7934 thread at a time. When used in multi-threaded scenarios, it is recom‐
7935 mended that you use the thread-safe mongoc_client_pool_t to retrieve a
7936 mongoc_client_t for your thread.
7937
7938 Fork Safety
7939 A mongoc_client_t is only usable in the parent process after a fork.
7940 The child process must call mongoc_client_reset().
7941
7942 Example
7943 example-client.c
7944
7945 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
7946 * libmongoc-1.0) */
7947
7948 /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
7949
7950 #include <mongoc/mongoc.h>
7951 #include <stdio.h>
7952 #include <stdlib.h>
7953
7954 int
7955 main (int argc, char *argv[])
7956 {
7957 mongoc_client_t *client;
7958 mongoc_collection_t *collection;
7959 mongoc_cursor_t *cursor;
7960 bson_error_t error;
7961 const bson_t *doc;
7962 const char *collection_name = "test";
7963 bson_t query;
7964 char *str;
7965 const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
7966 mongoc_uri_t *uri;
7967
7968 mongoc_init ();
7969 if (argc > 1) {
7970 uri_string = argv[1];
7971 }
7972
7973 if (argc > 2) {
7974 collection_name = argv[2];
7975 }
7976
7977 uri = mongoc_uri_new_with_error (uri_string, &error);
7978 if (!uri) {
7979 fprintf (stderr,
7980 "failed to parse URI: %s\n"
7981 "error message: %s\n",
7982 uri_string,
7983 error.message);
7984 return EXIT_FAILURE;
7985 }
7986
7987 client = mongoc_client_new_from_uri (uri);
7988 if (!client) {
7989 return EXIT_FAILURE;
7990 }
7991
7992 mongoc_client_set_error_api (client, 2);
7993
7994 bson_init (&query);
7995 collection = mongoc_client_get_collection (client, "test", collection_name);
7996 cursor = mongoc_collection_find_with_opts (
7997 collection,
7998 &query,
7999 NULL, /* additional options */
8000 NULL); /* read prefs, NULL for default */
8001
8002 while (mongoc_cursor_next (cursor, &doc)) {
8003 str = bson_as_canonical_extended_json (doc, NULL);
8004 fprintf (stdout, "%s\n", str);
8005 bson_free (str);
8006 }
8007
8008 if (mongoc_cursor_error (cursor, &error)) {
8009 fprintf (stderr, "Cursor Failure: %s\n", error.message);
8010 return EXIT_FAILURE;
8011 }
8012
8013 bson_destroy (&query);
8014 mongoc_cursor_destroy (cursor);
8015 mongoc_collection_destroy (collection);
8016 mongoc_uri_destroy (uri);
8017 mongoc_client_destroy (client);
8018 mongoc_cleanup ();
8019
8020 return EXIT_SUCCESS;
8021 }
8022
8023
8024 mongoc_collection_t
8025 Synopsis
8026 typedef struct _mongoc_collection_t mongoc_collection_t;
8027
8028 mongoc_collection_t provides access to a MongoDB collection. This han‐
8029 dle is useful for actions for most CRUD operations, I.e. insert, up‐
8030 date, delete, find, etc.
8031
8032 Read Preferences and Write Concerns
8033 Read preferences and write concerns are inherited from the parent
8034 client. They can be overridden by set_* commands if so desired.
8035
8036 mongoc_cursor_t
8037 Client-side cursor abstraction
8038
8039 Synopsis
8040 typedef struct _mongoc_cursor_t mongoc_cursor_t;
8041
8042 mongoc_cursor_t provides access to a MongoDB query cursor. It wraps up
8043 the wire protocol negotiation required to initiate a query and retrieve
8044 an unknown number of documents.
8045
8046 Common cursor operations include:
8047
8048 • Determine which host we've connected to with
8049 mongoc_cursor_get_host().
8050
8051 • Retrieve more records with repeated calls to mongoc_cursor_next().
8052
8053 • Clone a query to repeat execution at a later point with
8054 mongoc_cursor_clone().
8055
8056 • Test for errors with mongoc_cursor_error().
8057
8058 Cursors are lazy, meaning that no connection is established and no net‐
8059 work traffic occurs until the first call to mongoc_cursor_next().
8060
8061 Thread Safety
8062 mongoc_cursor_t is NOT thread safe. It may only be used from within the
8063 thread in which it was created.
8064
8065 Example
8066 Query MongoDB and iterate results
8067
8068 /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
8069 * libmongoc-1.0) */
8070
8071 /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
8072
8073 #include <mongoc/mongoc.h>
8074 #include <stdio.h>
8075 #include <stdlib.h>
8076
8077 int
8078 main (int argc, char *argv[])
8079 {
8080 mongoc_client_t *client;
8081 mongoc_collection_t *collection;
8082 mongoc_cursor_t *cursor;
8083 bson_error_t error;
8084 const bson_t *doc;
8085 const char *collection_name = "test";
8086 bson_t query;
8087 char *str;
8088 const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
8089 mongoc_uri_t *uri;
8090
8091 mongoc_init ();
8092 if (argc > 1) {
8093 uri_string = argv[1];
8094 }
8095
8096 if (argc > 2) {
8097 collection_name = argv[2];
8098 }
8099
8100 uri = mongoc_uri_new_with_error (uri_string, &error);
8101 if (!uri) {
8102 fprintf (stderr,
8103 "failed to parse URI: %s\n"
8104 "error message: %s\n",
8105 uri_string,
8106 error.message);
8107 return EXIT_FAILURE;
8108 }
8109
8110 client = mongoc_client_new_from_uri (uri);
8111 if (!client) {
8112 return EXIT_FAILURE;
8113 }
8114
8115 mongoc_client_set_error_api (client, 2);
8116
8117 bson_init (&query);
8118 collection = mongoc_client_get_collection (client, "test", collection_name);
8119 cursor = mongoc_collection_find_with_opts (
8120 collection,
8121 &query,
8122 NULL, /* additional options */
8123 NULL); /* read prefs, NULL for default */
8124
8125 while (mongoc_cursor_next (cursor, &doc)) {
8126 str = bson_as_canonical_extended_json (doc, NULL);
8127 fprintf (stdout, "%s\n", str);
8128 bson_free (str);
8129 }
8130
8131 if (mongoc_cursor_error (cursor, &error)) {
8132 fprintf (stderr, "Cursor Failure: %s\n", error.message);
8133 return EXIT_FAILURE;
8134 }
8135
8136 bson_destroy (&query);
8137 mongoc_cursor_destroy (cursor);
8138 mongoc_collection_destroy (collection);
8139 mongoc_uri_destroy (uri);
8140 mongoc_client_destroy (client);
8141 mongoc_cleanup ();
8142
8143 return EXIT_SUCCESS;
8144 }
8145
8146
8147 mongoc_database_t
8148 MongoDB Database Abstraction
8149
8150 Synopsis
8151 typedef struct _mongoc_database_t mongoc_database_t;
8152
8153 mongoc_database_t provides access to a MongoDB database. This handle is
8154 useful for actions a particular database object. It is not a container
8155 for mongoc_collection_t structures.
8156
8157 Read preferences and write concerns are inherited from the parent
8158 client. They can be overridden with mongoc_database_set_read_prefs()
8159 and mongoc_database_set_write_concern().
8160
8161 Examples
8162 #include <mongoc/mongoc.h>
8163
8164 int
8165 main (int argc, char *argv[])
8166 {
8167 mongoc_database_t *database;
8168 mongoc_client_t *client;
8169
8170 mongoc_init ();
8171
8172 client = mongoc_client_new ("mongodb://localhost/");
8173 database = mongoc_client_get_database (client, "test");
8174
8175 mongoc_database_destroy (database);
8176 mongoc_client_destroy (client);
8177
8178 mongoc_cleanup ();
8179
8180 return 0;
8181 }
8182
8183 mongoc_delete_flags_t
8184 WARNING:
8185 Deprecated since version 1.9.0: These flags are deprecated and
8186 should not be used in new code.
8187
8188 Please use mongoc_collection_delete_one() or
8189 mongoc_collection_delete_many() in new code.
8190
8191
8192 Synopsis
8193 typedef enum {
8194 MONGOC_DELETE_NONE = 0,
8195 MONGOC_DELETE_SINGLE_REMOVE = 1 << 0,
8196 } mongoc_delete_flags_t;
8197
8198 Flags for deletion operations
8199
8200 mongoc_find_and_modify_opts_t
8201 find_and_modify abstraction
8202
8203 Synopsis
8204 mongoc_find_and_modify_opts_t is a builder interface to construct the
8205 findAndModify command.
8206
8207 It was created to be able to accommodate new arguments to the findAnd‐
8208 Modify command.
8209
8210 As of MongoDB 3.2, the mongoc_write_concern_t specified on the
8211 mongoc_collection_t will be used, if any.
8212
8213 Example
8214 flags.c
8215
8216 void
8217 fam_flags (mongoc_collection_t *collection)
8218 {
8219 mongoc_find_and_modify_opts_t *opts;
8220 bson_t reply;
8221 bson_error_t error;
8222 bson_t query = BSON_INITIALIZER;
8223 bson_t *update;
8224 bool success;
8225
8226
8227 /* Find Zlatan Ibrahimovic, the striker */
8228 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
8229 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
8230 BSON_APPEND_UTF8 (&query, "profession", "Football player");
8231 BSON_APPEND_INT32 (&query, "age", 34);
8232 BSON_APPEND_INT32 (
8233 &query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62));
8234
8235 /* Add his football position */
8236 update = BCON_NEW ("$set", "{", "position", BCON_UTF8 ("striker"), "}");
8237
8238 opts = mongoc_find_and_modify_opts_new ();
8239
8240 mongoc_find_and_modify_opts_set_update (opts, update);
8241
8242 /* Create the document if it didn't exist, and return the updated document */
8243 mongoc_find_and_modify_opts_set_flags (
8244 opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW);
8245
8246 success = mongoc_collection_find_and_modify_with_opts (
8247 collection, &query, opts, &reply, &error);
8248
8249 if (success) {
8250 char *str;
8251
8252 str = bson_as_canonical_extended_json (&reply, NULL);
8253 printf ("%s\n", str);
8254 bson_free (str);
8255 } else {
8256 fprintf (
8257 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
8258 }
8259
8260 bson_destroy (&reply);
8261 bson_destroy (update);
8262 bson_destroy (&query);
8263 mongoc_find_and_modify_opts_destroy (opts);
8264 }
8265
8266
8267 bypass.c
8268
8269 void
8270 fam_bypass (mongoc_collection_t *collection)
8271 {
8272 mongoc_find_and_modify_opts_t *opts;
8273 bson_t reply;
8274 bson_t *update;
8275 bson_error_t error;
8276 bson_t query = BSON_INITIALIZER;
8277 bool success;
8278
8279
8280 /* Find Zlatan Ibrahimovic, the striker */
8281 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
8282 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
8283 BSON_APPEND_UTF8 (&query, "profession", "Football player");
8284
8285 /* Bump his age */
8286 update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
8287
8288 opts = mongoc_find_and_modify_opts_new ();
8289 mongoc_find_and_modify_opts_set_update (opts, update);
8290 /* He can still play, even though he is pretty old. */
8291 mongoc_find_and_modify_opts_set_bypass_document_validation (opts, true);
8292
8293 success = mongoc_collection_find_and_modify_with_opts (
8294 collection, &query, opts, &reply, &error);
8295
8296 if (success) {
8297 char *str;
8298
8299 str = bson_as_canonical_extended_json (&reply, NULL);
8300 printf ("%s\n", str);
8301 bson_free (str);
8302 } else {
8303 fprintf (
8304 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
8305 }
8306
8307 bson_destroy (&reply);
8308 bson_destroy (update);
8309 bson_destroy (&query);
8310 mongoc_find_and_modify_opts_destroy (opts);
8311 }
8312
8313
8314 update.c
8315
8316 void
8317 fam_update (mongoc_collection_t *collection)
8318 {
8319 mongoc_find_and_modify_opts_t *opts;
8320 bson_t *update;
8321 bson_t reply;
8322 bson_error_t error;
8323 bson_t query = BSON_INITIALIZER;
8324 bool success;
8325
8326
8327 /* Find Zlatan Ibrahimovic */
8328 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
8329 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
8330
8331 /* Make him a book author */
8332 update = BCON_NEW ("$set", "{", "author", BCON_BOOL (true), "}");
8333
8334 opts = mongoc_find_and_modify_opts_new ();
8335 /* Note that the document returned is the _previous_ version of the document
8336 * To fetch the modified new version, use
8337 * mongoc_find_and_modify_opts_set_flags (opts,
8338 * MONGOC_FIND_AND_MODIFY_RETURN_NEW);
8339 */
8340 mongoc_find_and_modify_opts_set_update (opts, update);
8341
8342 success = mongoc_collection_find_and_modify_with_opts (
8343 collection, &query, opts, &reply, &error);
8344
8345 if (success) {
8346 char *str;
8347
8348 str = bson_as_canonical_extended_json (&reply, NULL);
8349 printf ("%s\n", str);
8350 bson_free (str);
8351 } else {
8352 fprintf (
8353 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
8354 }
8355
8356 bson_destroy (&reply);
8357 bson_destroy (update);
8358 bson_destroy (&query);
8359 mongoc_find_and_modify_opts_destroy (opts);
8360 }
8361
8362
8363 fields.c
8364
8365 void
8366 fam_fields (mongoc_collection_t *collection)
8367 {
8368 mongoc_find_and_modify_opts_t *opts;
8369 bson_t fields = BSON_INITIALIZER;
8370 bson_t *update;
8371 bson_t reply;
8372 bson_error_t error;
8373 bson_t query = BSON_INITIALIZER;
8374 bool success;
8375
8376
8377 /* Find Zlatan Ibrahimovic */
8378 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
8379 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
8380
8381 /* Return his goal tally */
8382 BSON_APPEND_INT32 (&fields, "goals", 1);
8383
8384 /* Bump his goal tally */
8385 update = BCON_NEW ("$inc", "{", "goals", BCON_INT32 (1), "}");
8386
8387 opts = mongoc_find_and_modify_opts_new ();
8388 mongoc_find_and_modify_opts_set_update (opts, update);
8389 mongoc_find_and_modify_opts_set_fields (opts, &fields);
8390 /* Return the new tally */
8391 mongoc_find_and_modify_opts_set_flags (opts,
8392 MONGOC_FIND_AND_MODIFY_RETURN_NEW);
8393
8394 success = mongoc_collection_find_and_modify_with_opts (
8395 collection, &query, opts, &reply, &error);
8396
8397 if (success) {
8398 char *str;
8399
8400 str = bson_as_canonical_extended_json (&reply, NULL);
8401 printf ("%s\n", str);
8402 bson_free (str);
8403 } else {
8404 fprintf (
8405 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
8406 }
8407
8408 bson_destroy (&reply);
8409 bson_destroy (update);
8410 bson_destroy (&fields);
8411 bson_destroy (&query);
8412 mongoc_find_and_modify_opts_destroy (opts);
8413 }
8414
8415
8416 sort.c
8417
8418 void
8419 fam_sort (mongoc_collection_t *collection)
8420 {
8421 mongoc_find_and_modify_opts_t *opts;
8422 bson_t *update;
8423 bson_t sort = BSON_INITIALIZER;
8424 bson_t reply;
8425 bson_error_t error;
8426 bson_t query = BSON_INITIALIZER;
8427 bool success;
8428
8429
8430 /* Find all users with the lastname Ibrahimovic */
8431 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
8432
8433 /* Sort by age (descending) */
8434 BSON_APPEND_INT32 (&sort, "age", -1);
8435
8436 /* Bump his goal tally */
8437 update = BCON_NEW ("$set", "{", "oldest", BCON_BOOL (true), "}");
8438
8439 opts = mongoc_find_and_modify_opts_new ();
8440 mongoc_find_and_modify_opts_set_update (opts, update);
8441 mongoc_find_and_modify_opts_set_sort (opts, &sort);
8442
8443 success = mongoc_collection_find_and_modify_with_opts (
8444 collection, &query, opts, &reply, &error);
8445
8446 if (success) {
8447 char *str;
8448
8449 str = bson_as_canonical_extended_json (&reply, NULL);
8450 printf ("%s\n", str);
8451 bson_free (str);
8452 } else {
8453 fprintf (
8454 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
8455 }
8456
8457 bson_destroy (&reply);
8458 bson_destroy (update);
8459 bson_destroy (&sort);
8460 bson_destroy (&query);
8461 mongoc_find_and_modify_opts_destroy (opts);
8462 }
8463
8464
8465 opts.c
8466
8467 void
8468 fam_opts (mongoc_collection_t *collection)
8469 {
8470 mongoc_find_and_modify_opts_t *opts;
8471 bson_t reply;
8472 bson_t *update;
8473 bson_error_t error;
8474 bson_t query = BSON_INITIALIZER;
8475 mongoc_write_concern_t *wc;
8476 bson_t extra = BSON_INITIALIZER;
8477 bool success;
8478
8479
8480 /* Find Zlatan Ibrahimovic, the striker */
8481 BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
8482 BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
8483 BSON_APPEND_UTF8 (&query, "profession", "Football player");
8484
8485 /* Bump his age */
8486 update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
8487
8488 opts = mongoc_find_and_modify_opts_new ();
8489 mongoc_find_and_modify_opts_set_update (opts, update);
8490
8491 /* Abort if the operation takes too long. */
8492 mongoc_find_and_modify_opts_set_max_time_ms (opts, 100);
8493
8494 /* Set write concern w: 2 */
8495 wc = mongoc_write_concern_new ();
8496 mongoc_write_concern_set_w (wc, 2);
8497 mongoc_write_concern_append (wc, &extra);
8498
8499 /* Some future findAndModify option the driver doesn't support conveniently
8500 */
8501 BSON_APPEND_INT32 (&extra, "futureOption", 42);
8502 mongoc_find_and_modify_opts_append (opts, &extra);
8503
8504 success = mongoc_collection_find_and_modify_with_opts (
8505 collection, &query, opts, &reply, &error);
8506
8507 if (success) {
8508 char *str;
8509
8510 str = bson_as_canonical_extended_json (&reply, NULL);
8511 printf ("%s\n", str);
8512 bson_free (str);
8513 } else {
8514 fprintf (
8515 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
8516 }
8517
8518 bson_destroy (&reply);
8519 bson_destroy (&extra);
8520 bson_destroy (update);
8521 bson_destroy (&query);
8522 mongoc_write_concern_destroy (wc);
8523 mongoc_find_and_modify_opts_destroy (opts);
8524 }
8525
8526
8527 fam.c
8528
8529 int
8530 main (void)
8531 {
8532 mongoc_collection_t *collection;
8533 mongoc_database_t *database;
8534 mongoc_client_t *client;
8535 const char *uri_string =
8536 "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example";
8537 mongoc_uri_t *uri;
8538 bson_error_t error;
8539 bson_t *options;
8540
8541 mongoc_init ();
8542
8543 uri = mongoc_uri_new_with_error (uri_string, &error);
8544 if (!uri) {
8545 fprintf (stderr,
8546 "failed to parse URI: %s\n"
8547 "error message: %s\n",
8548 uri_string,
8549 error.message);
8550 return EXIT_FAILURE;
8551 }
8552
8553 client = mongoc_client_new_from_uri (uri);
8554 if (!client) {
8555 return EXIT_FAILURE;
8556 }
8557
8558 mongoc_client_set_error_api (client, 2);
8559 database = mongoc_client_get_database (client, "databaseName");
8560
8561 options = BCON_NEW ("validator",
8562 "{",
8563 "age",
8564 "{",
8565 "$lte",
8566 BCON_INT32 (34),
8567 "}",
8568 "}",
8569 "validationAction",
8570 BCON_UTF8 ("error"),
8571 "validationLevel",
8572 BCON_UTF8 ("moderate"));
8573
8574 collection = mongoc_database_create_collection (
8575 database, "collectionName", options, &error);
8576 if (!collection) {
8577 fprintf (
8578 stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
8579 return EXIT_FAILURE;
8580 }
8581
8582 fam_flags (collection);
8583 fam_bypass (collection);
8584 fam_update (collection);
8585 fam_fields (collection);
8586 fam_opts (collection);
8587 fam_sort (collection);
8588
8589 mongoc_collection_drop (collection, NULL);
8590 bson_destroy (options);
8591 mongoc_uri_destroy (uri);
8592 mongoc_database_destroy (database);
8593 mongoc_collection_destroy (collection);
8594 mongoc_client_destroy (client);
8595
8596 mongoc_cleanup ();
8597 return EXIT_SUCCESS;
8598 }
8599
8600
8601 Outputs:
8602
8603 {
8604 "lastErrorObject": {
8605 "updatedExisting": false,
8606 "n": 1,
8607 "upserted": {
8608 "$oid": "56562a99d13e6d86239c7b00"
8609 }
8610 },
8611 "value": {
8612 "_id": {
8613 "$oid": "56562a99d13e6d86239c7b00"
8614 },
8615 "age": 34,
8616 "firstname": "Zlatan",
8617 "goals": 342,
8618 "lastname": "Ibrahimovic",
8619 "profession": "Football player",
8620 "position": "striker"
8621 },
8622 "ok": 1
8623 }
8624 {
8625 "lastErrorObject": {
8626 "updatedExisting": true,
8627 "n": 1
8628 },
8629 "value": {
8630 "_id": {
8631 "$oid": "56562a99d13e6d86239c7b00"
8632 },
8633 "age": 34,
8634 "firstname": "Zlatan",
8635 "goals": 342,
8636 "lastname": "Ibrahimovic",
8637 "profession": "Football player",
8638 "position": "striker"
8639 },
8640 "ok": 1
8641 }
8642 {
8643 "lastErrorObject": {
8644 "updatedExisting": true,
8645 "n": 1
8646 },
8647 "value": {
8648 "_id": {
8649 "$oid": "56562a99d13e6d86239c7b00"
8650 },
8651 "age": 35,
8652 "firstname": "Zlatan",
8653 "goals": 342,
8654 "lastname": "Ibrahimovic",
8655 "profession": "Football player",
8656 "position": "striker"
8657 },
8658 "ok": 1
8659 }
8660 {
8661 "lastErrorObject": {
8662 "updatedExisting": true,
8663 "n": 1
8664 },
8665 "value": {
8666 "_id": {
8667 "$oid": "56562a99d13e6d86239c7b00"
8668 },
8669 "goals": 343
8670 },
8671 "ok": 1
8672 }
8673 {
8674 "lastErrorObject": {
8675 "updatedExisting": true,
8676 "n": 1
8677 },
8678 "value": {
8679 "_id": {
8680 "$oid": "56562a99d13e6d86239c7b00"
8681 },
8682 "age": 35,
8683 "firstname": "Zlatan",
8684 "goals": 343,
8685 "lastname": "Ibrahimovic",
8686 "profession": "Football player",
8687 "position": "striker",
8688 "author": true
8689 },
8690 "ok": 1
8691 }
8692
8693 mongoc_gridfs_file_list_t
8694 Synopsis
8695 #include <mongoc/mongoc.h>
8696
8697 typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t;
8698
8699 Description
8700 mongoc_gridfs_file_list_t provides a gridfs file list abstraction. It
8701 provides iteration and basic marshalling on top of a regular
8702 mongoc_collection_find_with_opts() style query. In interface, it's
8703 styled after mongoc_cursor_t.
8704
8705 Example
8706 mongoc_gridfs_file_list_t *list;
8707 mongoc_gridfs_file_t *file;
8708
8709 list = mongoc_gridfs_find (gridfs, query);
8710
8711 while ((file = mongoc_gridfs_file_list_next (list))) {
8712 do_something (file);
8713
8714 mongoc_gridfs_file_destroy (file);
8715 }
8716
8717 mongoc_gridfs_file_list_destroy (list);
8718
8719 mongoc_gridfs_file_opt_t
8720 Synopsis
8721 typedef struct {
8722 const char *md5;
8723 const char *filename;
8724 const char *content_type;
8725 const bson_t *aliases;
8726 const bson_t *metadata;
8727 uint32_t chunk_size;
8728 } mongoc_gridfs_file_opt_t;
8729
8730 Description
8731 This structure contains options that can be set on a
8732 mongoc_gridfs_file_t. It can be used by various functions when creating
8733 a new gridfs file.
8734
8735 mongoc_gridfs_file_t
8736 Synopsis
8737 typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t;
8738
8739 Description
8740 This structure provides a MongoDB GridFS file abstraction. It provides
8741 several APIs.
8742
8743 • readv, writev, seek, and tell.
8744
8745 • General file metadata such as filename and length.
8746
8747 • GridFS metadata such as md5, filename, content_type, aliases, meta‐
8748 data, chunk_size, and upload_date.
8749
8750 Thread Safety
8751 This structure is NOT thread-safe and should only be used from one
8752 thread at a time.
8753
8754 Related
8755 • mongoc_client_t
8756
8757 • mongoc_gridfs_t
8758
8759 • mongoc_gridfs_file_list_t
8760
8761 • mongoc_gridfs_file_opt_t
8762
8763 mongoc_gridfs_bucket_t
8764 Synopsis
8765 #include <mongoc/mongoc.h>
8766
8767 typedef struct _mongoc_gridfs_bucket_t mongoc_gridfs_bucket_t;
8768
8769 Description
8770 mongoc_gridfs_bucket_t provides a spec-compliant MongoDB GridFS imple‐
8771 mentation, superseding mongoc_gridfs_t. See the GridFS MongoDB documen‐
8772 tation.
8773
8774 Thread Safety
8775 mongoc_gridfs_bucket_t is NOT thread-safe and should only be used in
8776 the same thread as the owning mongoc_client_t.
8777
8778 Lifecycle
8779 It is an error to free a mongoc_gridfs_bucket_t before freeing all de‐
8780 rived instances of mongoc_stream_t. The owning mongoc_client_t must
8781 outlive the mongoc_gridfs_bucket_t.
8782
8783 Example
8784 example-gridfs-bucket.c
8785
8786 #include <stdio.h>
8787 #include <stdlib.h>
8788
8789 #include <mongoc/mongoc.h>
8790
8791 int
8792 main (int argc, char *argv[])
8793 {
8794 const char *uri_string =
8795 "mongodb://localhost:27017/?appname=new-gridfs-example";
8796 mongoc_client_t *client;
8797 mongoc_database_t *db;
8798 mongoc_stream_t *file_stream;
8799 mongoc_gridfs_bucket_t *bucket;
8800 mongoc_cursor_t *cursor;
8801 bson_t filter;
8802 bool res;
8803 bson_value_t file_id;
8804 bson_error_t error;
8805 const bson_t *doc;
8806 char *str;
8807 mongoc_init ();
8808
8809 if (argc != 3) {
8810 fprintf (stderr, "usage: %s SOURCE_FILE_PATH FILE_COPY_PATH\n", argv[0]);
8811 return EXIT_FAILURE;
8812 }
8813
8814 /* 1. Make a bucket. */
8815 client = mongoc_client_new (uri_string);
8816 db = mongoc_client_get_database (client, "test");
8817 bucket = mongoc_gridfs_bucket_new (db, NULL, NULL, &error);
8818 if (!bucket) {
8819 printf ("Error creating gridfs bucket: %s\n", error.message);
8820 return EXIT_FAILURE;
8821 }
8822
8823 /* 2. Insert a file. */
8824 file_stream = mongoc_stream_file_new_for_path (argv[1], O_RDONLY, 0);
8825 res = mongoc_gridfs_bucket_upload_from_stream (
8826 bucket, "my-file", file_stream, NULL, &file_id, &error);
8827 if (!res) {
8828 printf ("Error uploading file: %s\n", error.message);
8829 return EXIT_FAILURE;
8830 }
8831
8832 mongoc_stream_close (file_stream);
8833 mongoc_stream_destroy (file_stream);
8834
8835 /* 3. Download the file in GridFS to a local file. */
8836 file_stream = mongoc_stream_file_new_for_path (argv[2], O_CREAT | O_RDWR, 0);
8837 if (!file_stream) {
8838 perror ("Error opening file stream");
8839 return EXIT_FAILURE;
8840 }
8841
8842 res = mongoc_gridfs_bucket_download_to_stream (
8843 bucket, &file_id, file_stream, &error);
8844 if (!res) {
8845 printf ("Error downloading file to stream: %s\n", error.message);
8846 return EXIT_FAILURE;
8847 }
8848 mongoc_stream_close (file_stream);
8849 mongoc_stream_destroy (file_stream);
8850
8851 /* 4. List what files are available in GridFS. */
8852 bson_init (&filter);
8853 cursor = mongoc_gridfs_bucket_find (bucket, &filter, NULL);
8854
8855 while (mongoc_cursor_next (cursor, &doc)) {
8856 str = bson_as_canonical_extended_json (doc, NULL);
8857 printf ("%s\n", str);
8858 bson_free (str);
8859 }
8860
8861 /* 5. Delete the file that we added. */
8862 res = mongoc_gridfs_bucket_delete_by_id (bucket, &file_id, &error);
8863 if (!res) {
8864 printf ("Error deleting the file: %s\n", error.message);
8865 return EXIT_FAILURE;
8866 }
8867
8868 /* 6. Cleanup. */
8869 mongoc_stream_close (file_stream);
8870 mongoc_stream_destroy (file_stream);
8871 mongoc_cursor_destroy (cursor);
8872 bson_destroy (&filter);
8873 mongoc_gridfs_bucket_destroy (bucket);
8874 mongoc_database_destroy (db);
8875 mongoc_client_destroy (client);
8876 mongoc_cleanup ();
8877
8878 return EXIT_SUCCESS;
8879 }
8880
8881
8882 SEE ALSO:
8883 The MongoDB GridFS specification.
8884
8885 The non spec-compliant mongoc_gridfs_t.
8886
8887
8888 mongoc_gridfs_t
8889 WARNING:
8890 This GridFS implementation does not conform to the MongoDB GridFS
8891 specification. For a spec compliant implementation, use
8892 mongoc_gridfs_bucket_t.
8893
8894 Synopsis
8895 #include <mongoc/mongoc.h>
8896
8897 typedef struct _mongoc_gridfs_t mongoc_gridfs_t;
8898
8899 Description
8900 mongoc_gridfs_t provides a MongoDB gridfs implementation. The system as
8901 a whole is made up of gridfs objects, which contain gridfs_files and
8902 gridfs_file_lists. Essentially, a basic file system API.
8903
8904 There are extensive caveats about the kind of use cases gridfs is prac‐
8905 tical for. In particular, any writing after initial file creation is
8906 likely to both break any concurrent readers and be quite expensive.
8907 That said, this implementation does allow for arbitrary writes to ex‐
8908 isting gridfs object, just use them with caution.
8909
8910 mongoc_gridfs also integrates tightly with the mongoc_stream_t abstrac‐
8911 tion, which provides some convenient wrapping for file creation and
8912 reading/writing. It can be used without, but its worth looking to see
8913 if your problem can fit that model.
8914
8915 WARNING:
8916 mongoc_gridfs_t does not support read preferences. In a replica set,
8917 GridFS queries are always routed to the primary.
8918
8919 Thread Safety
8920 mongoc_gridfs_t is NOT thread-safe and should only be used in the same
8921 thread as the owning mongoc_client_t.
8922
8923 Lifecycle
8924 It is an error to free a mongoc_gridfs_t before freeing all related in‐
8925 stances of mongoc_gridfs_file_t and mongoc_gridfs_file_list_t.
8926
8927 Example
8928 example-gridfs.c
8929
8930 #include <assert.h>
8931 #include <mongoc/mongoc.h>
8932 #include <stdio.h>
8933 #include <stdlib.h>
8934 #include <fcntl.h>
8935
8936 int
8937 main (int argc, char *argv[])
8938 {
8939 mongoc_gridfs_t *gridfs;
8940 mongoc_gridfs_file_t *file;
8941 mongoc_gridfs_file_list_t *list;
8942 mongoc_gridfs_file_opt_t opt = {0};
8943 mongoc_client_t *client;
8944 const char *uri_string = "mongodb://127.0.0.1:27017/?appname=gridfs-example";
8945 mongoc_uri_t *uri;
8946 mongoc_stream_t *stream;
8947 bson_t filter;
8948 bson_t opts;
8949 bson_t child;
8950 bson_error_t error;
8951 ssize_t r;
8952 char buf[4096];
8953 mongoc_iovec_t iov;
8954 const char *filename;
8955 const char *command;
8956 bson_value_t id;
8957
8958 if (argc < 2) {
8959 fprintf (stderr, "usage - %s command ...\n", argv[0]);
8960 return EXIT_FAILURE;
8961 }
8962
8963 mongoc_init ();
8964
8965 iov.iov_base = (void *) buf;
8966 iov.iov_len = sizeof buf;
8967
8968 /* connect to localhost client */
8969 uri = mongoc_uri_new_with_error (uri_string, &error);
8970 if (!uri) {
8971 fprintf (stderr,
8972 "failed to parse URI: %s\n"
8973 "error message: %s\n",
8974 uri_string,
8975 error.message);
8976 return EXIT_FAILURE;
8977 }
8978
8979 client = mongoc_client_new_from_uri (uri);
8980 assert (client);
8981 mongoc_client_set_error_api (client, 2);
8982
8983 /* grab a gridfs handle in test prefixed by fs */
8984 gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error);
8985 assert (gridfs);
8986
8987 command = argv[1];
8988 filename = argv[2];
8989
8990 if (strcmp (command, "read") == 0) {
8991 if (argc != 3) {
8992 fprintf (stderr, "usage - %s read filename\n", argv[0]);
8993 return EXIT_FAILURE;
8994 }
8995 file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error);
8996 assert (file);
8997
8998 stream = mongoc_stream_gridfs_new (file);
8999 assert (stream);
9000
9001 for (;;) {
9002 r = mongoc_stream_readv (stream, &iov, 1, -1, 0);
9003
9004 assert (r >= 0);
9005
9006 if (r == 0) {
9007 break;
9008 }
9009
9010 if (fwrite (iov.iov_base, 1, r, stdout) != r) {
9011 MONGOC_ERROR ("Failed to write to stdout. Exiting.\n");
9012 exit (1);
9013 }
9014 }
9015
9016 mongoc_stream_destroy (stream);
9017 mongoc_gridfs_file_destroy (file);
9018 } else if (strcmp (command, "list") == 0) {
9019 bson_init (&filter);
9020
9021 bson_init (&opts);
9022 bson_append_document_begin (&opts, "sort", -1, &child);
9023 BSON_APPEND_INT32 (&child, "filename", 1);
9024 bson_append_document_end (&opts, &child);
9025
9026 list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts);
9027
9028 bson_destroy (&filter);
9029 bson_destroy (&opts);
9030
9031 while ((file = mongoc_gridfs_file_list_next (list))) {
9032 const char *name = mongoc_gridfs_file_get_filename (file);
9033 printf ("%s\n", name ? name : "?");
9034
9035 mongoc_gridfs_file_destroy (file);
9036 }
9037
9038 mongoc_gridfs_file_list_destroy (list);
9039 } else if (strcmp (command, "write") == 0) {
9040 if (argc != 4) {
9041 fprintf (stderr, "usage - %s write filename input_file\n", argv[0]);
9042 return EXIT_FAILURE;
9043 }
9044
9045 stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0);
9046 assert (stream);
9047
9048 opt.filename = filename;
9049
9050 /* the driver generates a file_id for you */
9051 file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt);
9052 assert (file);
9053
9054 id.value_type = BSON_TYPE_INT32;
9055 id.value.v_int32 = 1;
9056
9057 /* optional: the following method specifies a file_id of any
9058 BSON type */
9059 if (!mongoc_gridfs_file_set_id (file, &id, &error)) {
9060 fprintf (stderr, "%s\n", error.message);
9061 return EXIT_FAILURE;
9062 }
9063
9064 if (!mongoc_gridfs_file_save (file)) {
9065 mongoc_gridfs_file_error (file, &error);
9066 fprintf (stderr, "Could not save: %s\n", error.message);
9067 return EXIT_FAILURE;
9068 }
9069
9070 mongoc_gridfs_file_destroy (file);
9071 } else {
9072 fprintf (stderr, "Unknown command");
9073 return EXIT_FAILURE;
9074 }
9075
9076 mongoc_gridfs_destroy (gridfs);
9077 mongoc_uri_destroy (uri);
9078 mongoc_client_destroy (client);
9079
9080 mongoc_cleanup ();
9081
9082 return EXIT_SUCCESS;
9083 }
9084
9085
9086 SEE ALSO:
9087 The MongoDB GridFS specification.
9088
9089 The spec-compliant mongoc_gridfs_bucket_t.
9090
9091
9092 mongoc_host_list_t
9093 Synopsis
9094 typedef struct {
9095 mongoc_host_list_t *next;
9096 char host[BSON_HOST_NAME_MAX + 1];
9097 char host_and_port[BSON_HOST_NAME_MAX + 7];
9098 uint16_t port;
9099 int family;
9100 void *padding[4];
9101 } mongoc_host_list_t;
9102
9103 Description
9104 The host and port of a MongoDB server. Can be part of a linked list:
9105 for example the return value of mongoc_uri_get_hosts() when multiple
9106 hosts are provided in the MongoDB URI.
9107
9108 SEE ALSO:
9109 mongoc_uri_get_hosts() and mongoc_cursor_get_host().
9110
9111
9112 mongoc_index_opt_geo_t
9113 Synopsis
9114 #include <mongoc/mongoc.h>
9115
9116 typedef struct {
9117 uint8_t twod_sphere_version;
9118 uint8_t twod_bits_precision;
9119 double twod_location_min;
9120 double twod_location_max;
9121 double haystack_bucket_size;
9122 uint8_t *padding[32];
9123 } mongoc_index_opt_geo_t;
9124
9125 Description
9126 This structure contains the options that may be used for tuning a GEO
9127 index.
9128
9129 SEE ALSO:
9130 mongoc_index_opt_t
9131
9132 mongoc_index_opt_wt_t
9133
9134
9135 mongoc_index_opt_t
9136 WARNING:
9137 Deprecated since version 1.8.0: This structure is deprecated and
9138 should not be used in new code. See Manage Collection Indexes.
9139
9140
9141 Synopsis
9142 #include <mongoc/mongoc.h>
9143
9144 typedef struct {
9145 bool is_initialized;
9146 bool background;
9147 bool unique;
9148 const char *name;
9149 bool drop_dups;
9150 bool sparse;
9151 int32_t expire_after_seconds;
9152 int32_t v;
9153 const bson_t *weights;
9154 const char *default_language;
9155 const char *language_override;
9156 mongoc_index_opt_geo_t *geo_options;
9157 mongoc_index_opt_storage_t *storage_options;
9158 const bson_t *partial_filter_expression;
9159 const bson_t *collation;
9160 void *padding[4];
9161 } mongoc_index_opt_t;
9162
9163 Description
9164 This structure contains the options that may be used for tuning a spe‐
9165 cific index.
9166
9167 See the createIndexes documentations in the MongoDB manual for descrip‐
9168 tions of individual options.
9169
9170 NOTE:
9171 dropDups is deprecated as of MongoDB version 3.0.0. This option is
9172 silently ignored by the server and unique index builds using this
9173 option will fail if a duplicate value is detected.
9174
9175 Example
9176 {
9177 bson_t keys;
9178 bson_error_t error;
9179 mongoc_index_opt_t opt;
9180 mongoc_index_opt_geo_t geo_opt;
9181
9182 mongoc_index_opt_init (&opt);
9183 mongoc_index_opt_geo_init (&geo_opt);
9184
9185 bson_init (&keys);
9186 BSON_APPEND_UTF8 (&keys, "location", "2d");
9187
9188 geo_opt.twod_location_min = -123;
9189 geo_opt.twod_location_max = +123;
9190 geo_opt.twod_bits_precision = 30;
9191 opt.geo_options = &geo_opt;
9192
9193 collection = mongoc_client_get_collection (client, "test", "geo_test");
9194 if (mongoc_collection_create_index (collection, &keys, &opt, &error)) {
9195 /* Successfully created the geo index */
9196 }
9197 bson_destroy (&keys);
9198 mongoc_collection_destroy (&collection);
9199 }
9200
9201 SEE ALSO:
9202 mongoc_index_opt_geo_t
9203
9204 mongoc_index_opt_wt_t
9205
9206
9207 mongoc_index_opt_wt_t
9208 Synopsis
9209 #include <mongoc/mongoc.h>
9210
9211 typedef struct {
9212 mongoc_index_opt_storage_t base;
9213 const char *config_str;
9214 void *padding[8];
9215 } mongoc_index_opt_wt_t;
9216
9217 Description
9218 This structure contains the options that may be used for tuning a
9219 WiredTiger specific index.
9220
9221 SEE ALSO:
9222 mongoc_index_opt_t
9223
9224 mongoc_index_opt_geo_t
9225
9226
9227 mongoc_insert_flags_t
9228 Flags for insert operations
9229
9230 Synopsis
9231 typedef enum {
9232 MONGOC_INSERT_NONE = 0,
9233 MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0,
9234 } mongoc_insert_flags_t;
9235
9236 #define MONGOC_INSERT_NO_VALIDATE (1U << 31)
9237
9238 Description
9239 These flags correspond to the MongoDB wire protocol. They may be bit‐
9240 wise or'd together. They may modify how an insert happens on the Mon‐
9241 goDB server.
9242
9243 Flag Values
9244 ┌──────────────────────────┬────────────────────────────┐
9245 │MONGOC_INSERT_NONE │ Specify no insert flags. │
9246 ├──────────────────────────┼────────────────────────────┤
9247 │MONGOC_INSERT_CON‐ │ Continue inserting docu‐ │
9248 │TINUE_ON_ERROR │ ments from the insertion │
9249 │ │ set even if one insert │
9250 │ │ fails. │
9251 ├──────────────────────────┼────────────────────────────┤
9252 │MONGOC_INSERT_NO_VALIDATE │ Do not validate insertion │
9253 │ │ documents before perform‐ │
9254 │ │ ing an insert. Validation │
9255 │ │ can be expensive, so this │
9256 │ │ can save some time if you │
9257 │ │ know your documents are │
9258 │ │ already valid. │
9259 └──────────────────────────┴────────────────────────────┘
9260
9261 mongoc_iovec_t
9262 Synopsis
9263 Synopsis
9264 #include <mongoc/mongoc.h>
9265
9266 #ifdef _WIN32
9267 typedef struct {
9268 u_long iov_len;
9269 char *iov_base;
9270 } mongoc_iovec_t;
9271 #else
9272 typedef struct iovec mongoc_iovec_t;
9273 #endif
9274
9275 The mongoc_iovec_t structure is a portability abstraction for consumers
9276 of the mongoc_stream_t interfaces. It allows for scatter/gather I/O
9277 through the socket subsystem.
9278
9279 WARNING:
9280 When writing portable code, beware of the ordering of iov_len and
9281 iov_base as they are different on various platforms. Therefore, you
9282 should not use C initializers for initialization.
9283
9284 mongoc_optional_t
9285 A struct to store optional boolean values.
9286
9287 Synopsis
9288 Used to specify optional boolean flags, which may remain unset.
9289
9290 This is used within mongoc_server_api_t to track whether a flag was ex‐
9291 plicitly set.
9292
9293 mongoc_query_flags_t
9294 Flags for query operations
9295
9296 Synopsis
9297 typedef enum {
9298 MONGOC_QUERY_NONE = 0,
9299 MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1,
9300 MONGOC_QUERY_SECONDARY_OK = 1 << 2,
9301 MONGOC_QUERY_OPLOG_REPLAY = 1 << 3,
9302 MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
9303 MONGOC_QUERY_AWAIT_DATA = 1 << 5,
9304 MONGOC_QUERY_EXHAUST = 1 << 6,
9305 MONGOC_QUERY_PARTIAL = 1 << 7,
9306 } mongoc_query_flags_t;
9307
9308 Description
9309 These flags correspond to the MongoDB wire protocol. They may be bit‐
9310 wise or'd together. They may modify how a query is performed in the
9311 MongoDB server.
9312
9313 Flag Values
9314 ┌───────────────────────────┬────────────────────────────┐
9315 │MONGOC_QUERY_NONE │ Specify no query flags. │
9316 ├───────────────────────────┼────────────────────────────┤
9317 │MONGOC_QUERY_TAILABLE_CUR‐ │ Cursor will not be closed │
9318 │SOR │ when the last data is re‐ │
9319 │ │ trieved. You can resume │
9320 │ │ this cursor later. │
9321 ├───────────────────────────┼────────────────────────────┤
9322 │MONGOC_QUERY_SECONDARY_OK │ Allow query of replica set │
9323 │ │ secondaries. │
9324 ├───────────────────────────┼────────────────────────────┤
9325 │MONGOC_QUERY_OPLOG_REPLAY │ Used internally by Mon‐ │
9326 │ │ goDB. │
9327 ├───────────────────────────┼────────────────────────────┤
9328 │MONGOC_QUERY_NO_CUR‐ │ The server normally times │
9329 │SOR_TIMEOUT │ out an idle cursor after │
9330 │ │ an inactivity period (10 │
9331 │ │ minutes). This prevents │
9332 │ │ that. │
9333 ├───────────────────────────┼────────────────────────────┤
9334 │MONGOC_QUERY_AWAIT_DATA │ Use with MON‐ │
9335 │ │ GOC_QUERY_TAILABLE_CURSOR. │
9336 │ │ Block rather than return‐ │
9337 │ │ ing no data. After a pe‐ │
9338 │ │ riod, time out. │
9339 ├───────────────────────────┼────────────────────────────┤
9340 │MONGOC_QUERY_EXHAUST │ Stream the data down full │
9341 │ │ blast in multiple "reply" │
9342 │ │ packets. Faster when you │
9343 │ │ are pulling down a lot of │
9344 │ │ data and you know you want │
9345 │ │ to retrieve it all. Only │
9346 │ │ applies to cursors created │
9347 │ │ from a find operation │
9348 │ │ (i.e. │
9349 │ │ mongoc_collection_find()). │
9350 ├───────────────────────────┼────────────────────────────┤
9351 │MONGOC_QUERY_PARTIAL │ Get partial results from │
9352 │ │ mongos if some shards are │
9353 │ │ down (instead of throwing │
9354 │ │ an error). │
9355 └───────────────────────────┴────────────────────────────┘
9356
9357 mongoc_rand
9358 MongoDB Random Number Generator
9359
9360 Synopsis
9361 void
9362 mongoc_rand_add (const void *buf, int num, double entropy);
9363
9364 void
9365 mongoc_rand_seed (const void *buf, int num);
9366
9367 int
9368 mongoc_rand_status (void);
9369
9370 Description
9371 The mongoc_rand family of functions provide access to the low level
9372 randomness primitives used by the MongoDB C Driver. In particular,
9373 they control the creation of cryptographically strong pseudo-random
9374 bytes required by some security mechanisms.
9375
9376 While we can usually pull enough entropy from the environment, you may
9377 be required to seed the PRNG manually depending on your OS, hardware
9378 and other entropy consumers running on the same system.
9379
9380 Entropy
9381 mongoc_rand_add and mongoc_rand_seed allow the user to directly provide
9382 entropy. They differ insofar as mongoc_rand_seed requires that each
9383 bit provided is fully random. mongoc_rand_add allows the user to spec‐
9384 ify the degree of randomness in the provided bytes as well.
9385
9386 Status
9387 The mongoc_rand_status function allows the user to check the status of
9388 the mongoc PRNG. This can be used to guarantee sufficient entropy at
9389 program startup, rather than waiting for runtime errors to occur.
9390
9391 mongoc_read_concern_t
9392 Read Concern abstraction
9393
9394 Synopsis
9395 New in MongoDB 3.2.
9396
9397 The mongoc_read_concern_t allows clients to choose a level of isolation
9398 for their reads. The default, MONGOC_READ_CONCERN_LEVEL_LOCAL, is right
9399 for the great majority of applications.
9400
9401 You can specify a read concern on connection objects, database objects,
9402 or collection objects.
9403
9404 See readConcern on the MongoDB website for more information.
9405
9406 Read Concern is only sent to MongoDB when it has explicitly been set by
9407 mongoc_read_concern_set_level() to anything other than NULL.
9408
9409 Read Concern Levels
9410 ┌────────────────────┬─────────────────────┬─────────────────────┐
9411 │Macro │ Description │ First MongoDB ver‐ │
9412 │ │ │ sion │
9413 ├────────────────────┼─────────────────────┼─────────────────────┤
9414 │MONGOC_READ_CON‐ │ Level "local", the │ 3.2 │
9415 │CERN_LEVEL_LOCAL │ default. │ │
9416 ├────────────────────┼─────────────────────┼─────────────────────┤
9417 │MONGOC_READ_CON‐ │ Level "majority". │ 3.2 │
9418 │CERN_LEVEL_MAJORITY │ │ │
9419 ├────────────────────┼─────────────────────┼─────────────────────┤
9420 │MONGOC_READ_CON‐ │ Level "lineariz‐ │ 3.4 │
9421 │CERN_LEVEL_LIN‐ │ able". │ │
9422 │EARIZABLE │ │ │
9423 ├────────────────────┼─────────────────────┼─────────────────────┤
9424 │MONGOC_READ_CON‐ │ Level "available". │ 3.6 │
9425 │CERN_LEVEL_AVAIL‐ │ │ │
9426 │ABLE │ │ │
9427 ├────────────────────┼─────────────────────┼─────────────────────┤
9428 │MONGOC_READ_CON‐ │ Level "snapshot". │ 4.0 │
9429 │CERN_LEVEL_SNAPSHOT │ │ │
9430 └────────────────────┴─────────────────────┴─────────────────────┘
9431
9432 For the sake of compatibility with future versions of MongoDB,
9433 mongoc_read_concern_set_level() allows any string, not just this list
9434 of known read concern levels.
9435
9436 See Read Concern Levels in the MongoDB manual for more information
9437 about the individual read concern levels.
9438
9439 mongoc_read_mode_t
9440 Read Preference Modes
9441
9442 Synopsis
9443 typedef enum {
9444 MONGOC_READ_PRIMARY = (1 << 0),
9445 MONGOC_READ_SECONDARY = (1 << 1),
9446 MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
9447 MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
9448 MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
9449 } mongoc_read_mode_t;
9450
9451 Description
9452 This enum describes how reads should be dispatched. The default is MON‐
9453 GOC_READ_PRIMARY.
9454
9455 Please see the MongoDB website for a description of Read Preferences.
9456
9457 mongoc_read_prefs_t
9458 A read preference abstraction
9459
9460 Synopsis
9461 mongoc_read_prefs_t provides an abstraction on top of the MongoDB con‐
9462 nection read preferences. It allows for hinting to the driver which
9463 nodes in a replica set should be accessed first and how.
9464
9465 You can specify a read preference mode on connection objects, database
9466 objects, collection objects, or per-operation. Generally, it makes the
9467 most sense to stick with the global default mode, MONGOC_READ_PRIMARY.
9468 All of the other modes come with caveats that won't be covered in great
9469 detail here.
9470
9471 Read Modes
9472 ┌───────────────────────────┬────────────────────────────┐
9473 │MONGOC_READ_PRIMARY │ Default mode. All opera‐ │
9474 │ │ tions read from the cur‐ │
9475 │ │ rent replica set primary. │
9476 ├───────────────────────────┼────────────────────────────┤
9477 │MONGOC_READ_SECONDARY │ All operations read from │
9478 │ │ among the nearest sec‐ │
9479 │ │ ondary members of the │
9480 │ │ replica set. │
9481 ├───────────────────────────┼────────────────────────────┤
9482 │MONGOC_READ_PRIMARY_PRE‐ │ In most situations, opera‐ │
9483 │FERRED │ tions read from the pri‐ │
9484 │ │ mary but if it is unavail‐ │
9485 │ │ able, operations read from │
9486 │ │ secondary members. │
9487 ├───────────────────────────┼────────────────────────────┤
9488 │MONGOC_READ_SECONDARY_PRE‐ │ In most situations, opera‐ │
9489 │FERRED │ tions read from among the │
9490 │ │ nearest secondary members, │
9491 │ │ but if no secondaries are │
9492 │ │ available, operations read │
9493 │ │ from the primary. │
9494 ├───────────────────────────┼────────────────────────────┤
9495 │MONGOC_READ_NEAREST │ Operations read from among │
9496 │ │ the nearest members of the │
9497 │ │ replica set, irrespective │
9498 │ │ of the member's type. │
9499 └───────────────────────────┴────────────────────────────┘
9500
9501 Tag Sets
9502 Tag sets allow you to specify custom read preferences and write con‐
9503 cerns so that your application can target operations to specific mem‐
9504 bers.
9505
9506 Custom read preferences and write concerns evaluate tags sets in dif‐
9507 ferent ways: read preferences consider the value of a tag when select‐
9508 ing a member to read from, while write concerns ignore the value of a
9509 tag when selecting a member, except to consider whether or not the
9510 value is unique.
9511
9512 You can specify tag sets with the following read preference modes:
9513
9514 • primaryPreferred
9515
9516 • secondary
9517
9518 • secondaryPreferred
9519
9520 • nearest
9521
9522 Tags are not compatible with MONGOC_READ_PRIMARY and, in general, only
9523 apply when selecting a secondary member of a set for a read operation.
9524 However, the nearest read mode, when combined with a tag set, will se‐
9525 lect the nearest member that matches the specified tag set, which may
9526 be a primary or secondary.
9527
9528 Tag sets are represented as a comma-separated list of colon-separated
9529 key-value pairs when provided as a connection string, e.g.
9530 dc:ny,rack:1.
9531
9532 To specify a list of tag sets, using multiple readPreferenceTags, e.g.
9533
9534 readPreferenceTags=dc:ny,rack:1;readPreferenceTags=dc:ny;readPreferenceTags=
9535
9536 Note the empty value for the last one, which means "match any secondary
9537 as a last resort".
9538
9539 Order matters when using multiple readPreferenceTags.
9540
9541 Tag Sets can also be configured using mongoc_read_prefs_set_tags().
9542
9543 All interfaces use the same member selection logic to choose the member
9544 to which to direct read operations, basing the choice on read prefer‐
9545 ence mode and tag sets.
9546
9547 Max Staleness
9548 When connected to replica set running MongoDB 3.4 or later, the driver
9549 estimates the staleness of each secondary based on lastWriteDate values
9550 provided in server hello responses.
9551
9552 Max Staleness is the maximum replication lag in seconds (wall clock
9553 time) that a secondary can suffer and still be eligible for reads. The
9554 default is MONGOC_NO_MAX_STALENESS, which disables staleness checks.
9555 Otherwise, it must be a positive integer at least MONGOC_SMALL‐
9556 EST_MAX_STALENESS_SECONDS (90 seconds).
9557
9558 Max Staleness is also supported by sharded clusters of replica sets if
9559 all servers run MongoDB 3.4 or later.
9560
9561 Hedged Reads
9562 When connecting to a sharded cluster running MongoDB 4.4 or later,
9563 reads can be sent in parallel to the two "best" hosts. Once one result
9564 returns, any other outstanding operations that were part of the hedged
9565 read are cancelled.
9566
9567 When the read preference mode is MONGOC_READ_NEAREST and the sharded
9568 cluster is running MongoDB 4.4 or later, hedged reads are enabled by
9569 default. Additionally, hedged reads may be explicitly enabled or dis‐
9570 abled by calling mongoc_read_prefs_set_hedge() with a BSON document,
9571 e.g.
9572
9573 {
9574 enabled: true
9575 }
9576
9577 Appropriate values for the enabled key are true or false.
9578
9579 mongoc_remove_flags_t
9580 Flags for deletion operations
9581
9582 Synopsis
9583 typedef enum {
9584 MONGOC_REMOVE_NONE = 0,
9585 MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0,
9586 } mongoc_remove_flags_t;
9587
9588 Description
9589 These flags correspond to the MongoDB wire protocol. They may be bit‐
9590 wise or'd together. They may change the number of documents that are
9591 removed during a remove command.
9592
9593 Flag Values
9594 ┌─────────────────────────┬────────────────────────────┐
9595 │MONGOC_REMOVE_NONE │ Specify no removal flags. │
9596 │ │ All matching documents │
9597 │ │ will be removed. │
9598 ├─────────────────────────┼────────────────────────────┤
9599 │MONGOC_REMOVE_SINGLE_RE‐ │ Only remove the first │
9600 │MOVE │ matching document from the │
9601 │ │ selector. │
9602 └─────────────────────────┴────────────────────────────┘
9603
9604 mongoc_reply_flags_t
9605 Flags from server replies
9606
9607 Synopsis
9608 typedef enum {
9609 MONGOC_REPLY_NONE = 0,
9610 MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0,
9611 MONGOC_REPLY_QUERY_FAILURE = 1 << 1,
9612 MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2,
9613 MONGOC_REPLY_AWAIT_CAPABLE = 1 << 3,
9614 } mongoc_reply_flags_t;
9615
9616 Description
9617 These flags correspond to the wire protocol. They may be bitwise or'd
9618 together.
9619
9620 Flag Values
9621 ┌───────────────────────────┬────────────────────────────┐
9622 │MONGOC_REPLY_NONE │ No flags set. │
9623 ├───────────────────────────┼────────────────────────────┤
9624 │MONGOC_REPLY_CUR‐ │ No matching cursor was │
9625 │SOR_NOT_FOUND │ found on the server. │
9626 ├───────────────────────────┼────────────────────────────┤
9627 │MONGOC_REPLY_QUERY_FAILURE │ The query failed or was │
9628 │ │ invalid. Error document │
9629 │ │ has been provided. │
9630 ├───────────────────────────┼────────────────────────────┤
9631 │MONGOC_REPLY_SHARD_CON‐ │ Shard config is stale. │
9632 │FIG_STALE │ │
9633 ├───────────────────────────┼────────────────────────────┤
9634 │MONGOC_REPLY_AWAIT_CAPABLE │ If the returned cursor is │
9635 │ │ capable of MON‐ │
9636 │ │ GOC_QUERY_AWAIT_DATA. │
9637 └───────────────────────────┴────────────────────────────┘
9638
9639 mongoc_server_api_t
9640 A versioned API to use for connections.
9641
9642 Synopsis
9643 Used to specify which version of the MongoDB server's API to use for
9644 driver connections.
9645
9646 The server API type takes a mongoc_server_api_version_t. It can option‐
9647 ally be strict about the list of allowed commands in that API version,
9648 and can also optionally provide errors for deprecated commands in that
9649 API version.
9650
9651 A mongoc_server_api_t can be set on a client, and will then be sent to
9652 MongoDB for most commands run using that client.
9653
9654 mongoc_server_api_version_t
9655 A representation of server API version numbers.
9656
9657 Synopsis
9658 Used to specify which version of the MongoDB server's API to use for
9659 driver connections.
9660
9661 Supported API Versions
9662 The driver currently supports the following MongoDB API versions:
9663
9664 ┌─────────────────────┬────────────────────────┐
9665 │Enum value │ MongoDB version string │
9666 ├─────────────────────┼────────────────────────┤
9667 │MONGOC_SERVER_API_V1 │ "1" │
9668 └─────────────────────┴────────────────────────┘
9669
9670 mongoc_server_description_t
9671 Server description
9672
9673 Synopsis
9674 #include <mongoc/mongoc.h>
9675 typedef struct _mongoc_server_description_t mongoc_server_description_t
9676
9677 mongoc_server_description_t holds information about a mongod or mongos
9678 the driver is connected to.
9679
9680 Lifecycle
9681 Clean up a mongoc_server_description_t with
9682 mongoc_server_description_destroy() when necessary.
9683
9684 Applications receive a temporary reference to a mongoc_server_descrip‐
9685 tion_t as a parameter to an SDAM Monitoring callback that must not be
9686 destroyed. See Introduction to Application Performance Monitoring.
9687
9688 SEE ALSO:
9689 mongoc_client_get_server_descriptions().
9690
9691
9692 mongoc_session_opt_t
9693 #include <mongoc/mongoc.h>
9694
9695 typedef struct _mongoc_session_opt_t mongoc_session_opt_t;
9696
9697 Synopsis
9698 Start a session with mongoc_client_start_session(), use the session for
9699 a sequence of operations and multi-document transactions, then free it
9700 with mongoc_client_session_destroy(). Any mongoc_cursor_t or
9701 mongoc_change_stream_t using a session must be destroyed before the
9702 session, and a session must be destroyed before the mongoc_client_t it
9703 came from.
9704
9705 By default, sessions are causally consistent. To disable causal consis‐
9706 tency, before starting a session create a mongoc_session_opt_t with
9707 mongoc_session_opts_new() and call
9708 mongoc_session_opts_set_causal_consistency(), then free the struct with
9709 mongoc_session_opts_destroy().
9710
9711 Unacknowledged writes are prohibited with sessions.
9712
9713 A mongoc_client_session_t must be used by only one thread at a time.
9714 Due to session pooling, mongoc_client_start_session() may return a ses‐
9715 sion that has been idle for some time and is about to be closed after
9716 its idle timeout. Use the session within one minute of acquiring it to
9717 refresh the session and avoid a timeout.
9718
9719 See the example code for mongoc_session_opts_set_causal_consistency().
9720
9721 mongoc_socket_t
9722 Portable socket abstraction
9723
9724 Synopsis
9725 #include <mongoc/mongoc.h>
9726
9727 typedef struct _mongoc_socket_t mongoc_socket_t
9728
9729 Synopsis
9730 This structure provides a socket abstraction that is friendlier for
9731 portability than BSD sockets directly. Inconsistencies between Linux,
9732 various BSDs, Solaris, and Windows are handled here.
9733
9734 mongoc_ssl_opt_t
9735 Synopsis
9736 typedef struct {
9737 const char *pem_file;
9738 const char *pem_pwd;
9739 const char *ca_file;
9740 const char *ca_dir;
9741 const char *crl_file;
9742 bool weak_cert_validation;
9743 bool allow_invalid_hostname;
9744 void *internal;
9745 void *padding[6];
9746 } mongoc_ssl_opt_t;
9747
9748 Description
9749 This structure is used to set the TLS options for a mongoc_client_t or
9750 mongoc_client_pool_t.
9751
9752 Beginning in version 1.2.0, once a pool or client has any TLS options
9753 set, all connections use TLS, even if ssl=true is omitted from the Mon‐
9754 goDB URI. Before, TLS options were ignored unless tls=true was included
9755 in the URI.
9756
9757 As of 1.4.0, the mongoc_client_pool_set_ssl_opts() and
9758 mongoc_client_set_ssl_opts() will not only shallow copy the struct, but
9759 will also copy the const char*. It is therefore no longer needed to
9760 make sure the values remain valid after setting them.
9761
9762 SEE ALSO:
9763 Configuring TLS
9764
9765 mongoc_client_set_ssl_opts()
9766
9767 mongoc_client_pool_set_ssl_opts()
9768
9769
9770 mongoc_stream_buffered_t
9771 Synopsis
9772 typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t;
9773
9774 Description
9775 mongoc_stream_buffered_t should be considered a subclass of
9776 mongoc_stream_t. It performs buffering on an underlying stream.
9777
9778 SEE ALSO:
9779 mongoc_stream_buffered_new()
9780
9781 mongoc_stream_destroy()
9782
9783
9784 mongoc_stream_file_t
9785 Synopsis
9786 typedef struct _mongoc_stream_file_t mongoc_stream_file_t
9787
9788 mongoc_stream_file_t is a mongoc_stream_t subclass for working with
9789 standard UNIX style file-descriptors.
9790
9791 mongoc_stream_socket_t
9792 Synopsis
9793 typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t
9794
9795 mongoc_stream_socket_t should be considered a subclass of
9796 mongoc_stream_t that works upon socket streams.
9797
9798 mongoc_stream_t
9799 Synopsis
9800 typedef struct _mongoc_stream_t mongoc_stream_t
9801
9802 mongoc_stream_t provides a generic streaming IO abstraction based on a
9803 struct of pointers interface. The idea is to allow wrappers, perhaps
9804 other language drivers, to easily shim their IO system on top of mon‐
9805 goc_stream_t.
9806
9807 The API for the stream abstraction is currently private and non-exten‐
9808 sible.
9809
9810 Stream Types
9811 There are a number of built in stream types that come with mongoc. The
9812 default configuration is a buffered unix stream. If TLS is in use, that
9813 in turn is wrapped in a tls stream.
9814
9815 SEE ALSO:
9816 mongoc_stream_buffered_t
9817
9818 mongoc_stream_file_t
9819
9820 mongoc_stream_socket_t
9821
9822 mongoc_stream_tls_t
9823
9824
9825 mongoc_stream_tls_t
9826 Synopsis
9827 typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t
9828
9829 mongoc_stream_tls_t is a mongoc_stream_t subclass for working with TLS
9830 streams.
9831
9832 mongoc_topology_description_t
9833 Status of MongoDB Servers
9834
9835 Synopsis
9836 typedef struct _mongoc_topology_description_t mongoc_topology_description_t;
9837
9838 mongoc_topology_description_t is an opaque type representing the
9839 driver's knowledge of the MongoDB server or servers it is connected to.
9840 Its API conforms to the SDAM Monitoring Specification.
9841
9842 Applications receive a temporary reference to a mongoc_topology_de‐
9843 scription_t as a parameter to an SDAM Monitoring callback that must not
9844 be destroyed. See Introduction to Application Performance Monitoring.
9845
9846 mongoc_transaction_opt_t
9847 #include <mongoc/mongoc.h>
9848
9849 typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;
9850
9851 Synopsis
9852 Options for starting a multi-document transaction.
9853
9854 When a session is first created with mongoc_client_start_session(), it
9855 inherits from the client the read concern, write concern, and read
9856 preference with which to start transactions. Each of these fields can
9857 be overridden independently. Create a mongoc_transaction_opt_t with
9858 mongoc_transaction_opts_new(), and pass a non-NULL option to any of the
9859 mongoc_transaction_opt_t setter functions:
9860
9861 • mongoc_transaction_opts_set_read_concern()
9862
9863 • mongoc_transaction_opts_set_write_concern()
9864
9865 • mongoc_transaction_opts_set_read_prefs()
9866
9867 Pass the resulting transaction options to
9868 mongoc_client_session_start_transaction(). Each field set in the trans‐
9869 action options overrides the inherited client configuration.
9870
9871 Example
9872 example-transaction.c
9873
9874 /* gcc example-transaction.c -o example-transaction \
9875 * $(pkg-config --cflags --libs libmongoc-1.0) */
9876
9877 /* ./example-transaction [CONNECTION_STRING] */
9878
9879 #include <stdio.h>
9880 #include <mongoc/mongoc.h>
9881
9882
9883 int
9884 main (int argc, char *argv[])
9885 {
9886 int exit_code = EXIT_FAILURE;
9887
9888 mongoc_client_t *client = NULL;
9889 mongoc_database_t *database = NULL;
9890 mongoc_collection_t *collection = NULL;
9891 mongoc_client_session_t *session = NULL;
9892 mongoc_session_opt_t *session_opts = NULL;
9893 mongoc_transaction_opt_t *default_txn_opts = NULL;
9894 mongoc_transaction_opt_t *txn_opts = NULL;
9895 mongoc_read_concern_t *read_concern = NULL;
9896 mongoc_write_concern_t *write_concern = NULL;
9897 const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
9898 mongoc_uri_t *uri;
9899 bson_error_t error;
9900 bson_t *doc = NULL;
9901 bson_t *insert_opts = NULL;
9902 int32_t i;
9903 int64_t start;
9904 bson_t reply = BSON_INITIALIZER;
9905 char *reply_json;
9906 bool r;
9907
9908 mongoc_init ();
9909
9910 if (argc > 1) {
9911 uri_string = argv[1];
9912 }
9913
9914 uri = mongoc_uri_new_with_error (uri_string, &error);
9915 if (!uri) {
9916 MONGOC_ERROR ("failed to parse URI: %s\n"
9917 "error message: %s\n",
9918 uri_string,
9919 error.message);
9920 goto done;
9921 }
9922
9923 client = mongoc_client_new_from_uri (uri);
9924 if (!client) {
9925 goto done;
9926 }
9927
9928 mongoc_client_set_error_api (client, 2);
9929 database = mongoc_client_get_database (client, "example-transaction");
9930
9931 /* inserting into a nonexistent collection normally creates it, but a
9932 * collection can't be created in a transaction; create it now */
9933 collection =
9934 mongoc_database_create_collection (database, "collection", NULL, &error);
9935
9936 if (!collection) {
9937 /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
9938 if (error.code == 48) {
9939 collection = mongoc_database_get_collection (database, "collection");
9940 } else {
9941 MONGOC_ERROR ("Failed to create collection: %s", error.message);
9942 goto done;
9943 }
9944 }
9945
9946 /* a transaction's read preferences, read concern, and write concern can be
9947 * set on the client, on the default transaction options, or when starting
9948 * the transaction. for the sake of this example, set read concern on the
9949 * default transaction options. */
9950 default_txn_opts = mongoc_transaction_opts_new ();
9951 read_concern = mongoc_read_concern_new ();
9952 mongoc_read_concern_set_level (read_concern, "snapshot");
9953 mongoc_transaction_opts_set_read_concern (default_txn_opts, read_concern);
9954 session_opts = mongoc_session_opts_new ();
9955 mongoc_session_opts_set_default_transaction_opts (session_opts,
9956 default_txn_opts);
9957
9958 session = mongoc_client_start_session (client, session_opts, &error);
9959 if (!session) {
9960 MONGOC_ERROR ("Failed to start session: %s", error.message);
9961 goto done;
9962 }
9963
9964 /* in this example, set write concern when starting the transaction */
9965 txn_opts = mongoc_transaction_opts_new ();
9966 write_concern = mongoc_write_concern_new ();
9967 mongoc_write_concern_set_wmajority (write_concern, 1000 /* wtimeout */);
9968 mongoc_transaction_opts_set_write_concern (txn_opts, write_concern);
9969
9970 insert_opts = bson_new ();
9971 if (!mongoc_client_session_append (session, insert_opts, &error)) {
9972 MONGOC_ERROR ("Could not add session to opts: %s", error.message);
9973 goto done;
9974 }
9975
9976 retry_transaction:
9977 r = mongoc_client_session_start_transaction (session, txn_opts, &error);
9978 if (!r) {
9979 MONGOC_ERROR ("Failed to start transaction: %s", error.message);
9980 goto done;
9981 }
9982
9983 /* insert two documents - on error, retry the whole transaction */
9984 for (i = 0; i < 2; i++) {
9985 doc = BCON_NEW ("_id", BCON_INT32 (i));
9986 bson_destroy (&reply);
9987 r = mongoc_collection_insert_one (
9988 collection, doc, insert_opts, &reply, &error);
9989
9990 bson_destroy (doc);
9991
9992 if (!r) {
9993 MONGOC_ERROR ("Insert failed: %s", error.message);
9994 mongoc_client_session_abort_transaction (session, NULL);
9995
9996 /* a network error, primary failover, or other temporary error in a
9997 * transaction includes {"errorLabels": ["TransientTransactionError"]},
9998 * meaning that trying the entire transaction again may succeed
9999 */
10000 if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
10001 goto retry_transaction;
10002 }
10003
10004 goto done;
10005 }
10006
10007 reply_json = bson_as_json (&reply, NULL);
10008 printf ("%s\n", reply_json);
10009 bson_free (reply_json);
10010 }
10011
10012 /* in case of transient errors, retry for 5 seconds to commit transaction */
10013 start = bson_get_monotonic_time ();
10014 while (bson_get_monotonic_time () - start < 5 * 1000 * 1000) {
10015 bson_destroy (&reply);
10016 r = mongoc_client_session_commit_transaction (session, &reply, &error);
10017 if (r) {
10018 /* success */
10019 break;
10020 } else {
10021 MONGOC_ERROR ("Warning: commit failed: %s", error.message);
10022 if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
10023 goto retry_transaction;
10024 } else if (mongoc_error_has_label (&reply,
10025 "UnknownTransactionCommitResult")) {
10026 /* try again to commit */
10027 continue;
10028 }
10029
10030 /* unrecoverable error trying to commit */
10031 break;
10032 }
10033 }
10034
10035 exit_code = EXIT_SUCCESS;
10036
10037 done:
10038 bson_destroy (&reply);
10039 bson_destroy (insert_opts);
10040 mongoc_write_concern_destroy (write_concern);
10041 mongoc_read_concern_destroy (read_concern);
10042 mongoc_transaction_opts_destroy (txn_opts);
10043 mongoc_transaction_opts_destroy (default_txn_opts);
10044 mongoc_client_session_destroy (session);
10045 mongoc_collection_destroy (collection);
10046 mongoc_database_destroy (database);
10047 mongoc_uri_destroy (uri);
10048 mongoc_client_destroy (client);
10049
10050 mongoc_cleanup ();
10051
10052 return exit_code;
10053 }
10054
10055
10056 mongoc_transaction_state_t
10057 Constants for transaction states
10058
10059 Synopsis
10060 typedef enum {
10061 MONGOC_TRANSACTION_NONE = 0,
10062 MONGOC_TRANSACTION_STARTING = 1,
10063 MONGOC_TRANSACTION_IN_PROGRESS = 2,
10064 MONGOC_TRANSACTION_COMMITTED = 3,
10065 MONGOC_TRANSACTION_ABORTED = 4,
10066 } mongoc_transaction_state_t;
10067
10068 Description
10069 These constants describe the current transaction state of a session.
10070
10071 Flag Values
10072 ┌───────────────────────────┬────────────────────────────┐
10073 │MONGOC_TRANSACTION_NONE │ There is no transaction in │
10074 │ │ progress. │
10075 ├───────────────────────────┼────────────────────────────┤
10076 │MONGOC_TRANSACTION_START‐ │ A transaction has been │
10077 │ING │ started, but no operation │
10078 │ │ has been sent to the │
10079 │ │ server. │
10080 ├───────────────────────────┼────────────────────────────┤
10081 │MONGOC_TRANSAC‐ │ A transaction is in │
10082 │TION_IN_PROGRESS │ progress. │
10083 ├───────────────────────────┼────────────────────────────┤
10084 │MONGOC_TRANSACTION_COMMIT‐ │ The transaction was com‐ │
10085 │TED │ mitted. │
10086 ├───────────────────────────┼────────────────────────────┤
10087 │MONGOC_TRANSACTION_ABORTED │ The transaction was │
10088 │ │ aborted. │
10089 └───────────────────────────┴────────────────────────────┘
10090
10091 mongoc_update_flags_t
10092 Flags for update operations
10093
10094 Synopsis
10095 typedef enum {
10096 MONGOC_UPDATE_NONE = 0,
10097 MONGOC_UPDATE_UPSERT = 1 << 0,
10098 MONGOC_UPDATE_MULTI_UPDATE = 1 << 1,
10099 } mongoc_update_flags_t;
10100
10101 #define MONGOC_UPDATE_NO_VALIDATE (1U << 31)
10102
10103 Description
10104 These flags correspond to the MongoDB wire protocol. They may be bit‐
10105 wise or'd together. The allow for modifying the way an update is per‐
10106 formed in the MongoDB server.
10107
10108 Flag Values
10109 ┌───────────────────────────┬────────────────────────────┐
10110 │MONGOC_UPDATE_NONE │ No update flags set. │
10111 ├───────────────────────────┼────────────────────────────┤
10112 │MONGOC_UPDATE_UPSERT │ If an upsert should be │
10113 │ │ performed. │
10114 ├───────────────────────────┼────────────────────────────┤
10115 │MONGOC_UPDATE_MULTI_UPDATE │ If more than a single │
10116 │ │ matching document should │
10117 │ │ be updated. By default │
10118 │ │ only the first document is │
10119 │ │ updated. │
10120 ├───────────────────────────┼────────────────────────────┤
10121 │MONGOC_UPDATE_NO_VALIDATE │ Do not perform client side │
10122 │ │ BSON validations when per‐ │
10123 │ │ forming an update. This is │
10124 │ │ useful if you already know │
10125 │ │ your BSON documents are │
10126 │ │ valid. │
10127 └───────────────────────────┴────────────────────────────┘
10128
10129 mongoc_uri_t
10130 Synopsis
10131 typedef struct _mongoc_uri_t mongoc_uri_t;
10132
10133 Description
10134 mongoc_uri_t provides an abstraction on top of the MongoDB connection
10135 URI format. It provides standardized parsing as well as convenience
10136 methods for extracting useful information such as replica hosts or au‐
10137 thorization information.
10138
10139 See Connection String URI Reference on the MongoDB website for more in‐
10140 formation.
10141
10142 Format
10143 mongodb[+srv]:// <1>
10144 [username:password@] <2>
10145 host1 <3>
10146 [:port1] <4>
10147 [,host2[:port2],...[,hostN[:portN]]] <5>
10148 [/[database] <6>
10149 [?options]] <7>
10150
10151 1. "mongodb" is the specifier of the MongoDB protocol. Use "mon‐
10152 godb+srv" with a single service name in place of "host1" to specify
10153 the initial list of servers with an SRV record.
10154
10155 2. An optional username and password.
10156
10157 3. The only required part of the uri. This specifies either a host‐
10158 name, IPv4 address, IPv6 address enclosed in "[" and "]", or UNIX
10159 domain socket.
10160
10161 4. An optional port number. Defaults to :27017.
10162
10163 5. Extra optional hosts and ports. You would specify multiple hosts,
10164 for example, for connections to replica sets.
10165
10166 6. The name of the database to authenticate if the connection string
10167 includes authentication credentials. If /database is not specified
10168 and the connection string includes credentials, defaults to the 'ad‐
10169 min' database.
10170
10171 7. Connection specific options.
10172
10173 NOTE:
10174 Option names are case-insensitive. Do not repeat the same option
10175 (e.g. "mongodb://localhost/db?opt=value1&OPT=value2") since this may
10176 have unexpected results.
10177
10178 The MongoDB C Driver exposes constants for each supported connection
10179 option. These constants make it easier to discover connection options,
10180 but their string values can be used as well.
10181
10182 For example, the following calls are equal.
10183
10184 uri = mongoc_uri_new ("mongodb://localhost/?" MONGOC_URI_APPNAME "=applicationName");
10185 uri = mongoc_uri_new ("mongodb://localhost/?appname=applicationName");
10186 uri = mongoc_uri_new ("mongodb://localhost/?appName=applicationName");
10187
10188 Replica Set Example
10189 To describe a connection to a replica set named 'test' with the follow‐
10190 ing mongod hosts:
10191
10192 • db1.example.com on port 27017
10193
10194 • db2.example.com on port 2500
10195
10196 You would use a connection string that resembles the following.
10197
10198 mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test
10199
10200 SRV Example
10201 If you have configured an SRV record with a name like "_mon‐
10202 godb._tcp.server.example.com" whose records are a list of one or more
10203 MongoDB server hostnames, use a connection string like this:
10204
10205 uri = mongoc_uri_new ("mongodb+srv://server.example.com/?replicaSet=rs&appName=applicationName");
10206
10207 The driver prefixes the service name with "_mongodb._tcp.", then per‐
10208 forms a DNS SRV query to resolve the service name to one or more host‐
10209 names. If this query succeeds, the driver performs a DNS TXT query on
10210 the service name (without the "_mongodb._tcp" prefix) for additional
10211 URI options configured as TXT records.
10212
10213 On Unix, the MongoDB C Driver relies on libresolv to look up SRV and
10214 TXT records. If libresolv is unavailable, then using a "mongodb+srv"
10215 URI will cause an error. If your libresolv lacks res_nsearch then the
10216 driver will fall back to res_search, which is not thread-safe.
10217
10218 IPv4 and IPv6
10219 If connecting to a hostname that has both IPv4 and IPv6 DNS records,
10220 the behavior follows RFC-6555. A connection to the IPv6 address is at‐
10221 tempted first. If IPv6 fails, then a connection is attempted to the
10222 IPv4 address. If the connection attempt to IPv6 does not complete
10223 within 250ms, then IPv4 is tried in parallel. Whichever succeeds con‐
10224 nection first cancels the other. The successful DNS result is cached
10225 for 10 minutes.
10226
10227 As a consequence, attempts to connect to a mongod only listening on
10228 IPv4 may be delayed if there are both A (IPv4) and AAAA (IPv6) DNS
10229 records associated with the host.
10230
10231 To avoid a delay, configure hostnames to match the MongoDB configura‐
10232 tion. That is, only create an A record if the mongod is only listening
10233 on IPv4.
10234
10235 Connection Options
10236┌───────────────────┬──────────────────┬──────────────────┬─────────────────────────────────────┐
10237│Constant │ Key │ Default │ Description │
10238├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10239│MON‐ │ retryreads │ true │ If "true" and │
10240│GOC_URI_RETRYREADS │ │ │ the server is a │
10241│ │ │ │ MongoDB 3.6+ │
10242│ │ │ │ standalone, │
10243│ │ │ │ replica set, or │
10244│ │ │ │ sharded cluster, │
10245│ │ │ │ the driver │
10246│ │ │ │ safely retries a │
10247│ │ │ │ read that failed │
10248│ │ │ │ due to a network │
10249│ │ │ │ error or replica │
10250│ │ │ │ set failover. │
10251└───────────────────┴──────────────────┴──────────────────┴─────────────────────────────────────┘
10252
10253
10254
10255
10256
10257
10258
10259
10260│MONGOC_URI_RETRY‐ │ retrywrites │ true if driver │ If "true" and │
10261│WRITES │ │ built w/ TLS │ the server is a │
10262│ │ │ │ MongoDB 3.6+ │
10263│ │ │ │ replica set or │
10264│ │ │ │ sharded cluster, │
10265│ │ │ │ the driver │
10266│ │ │ │ safely retries a │
10267│ │ │ │ write that │
10268│ │ │ │ failed due to a │
10269│ │ │ │ network error or │
10270│ │ │ │ replica set │
10271│ │ │ │ failover. Only │
10272│ │ │ │ inserts, updates │
10273│ │ │ │ of single docu‐ │
10274│ │ │ │ ments, or │
10275│ │ │ │ deletes of sin‐ │
10276│ │ │ │ gle documents │
10277│ │ │ │ are retried. │
10278├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10279│MONGOC_URI_APPNAME │ appname │ Empty (no app‐ │ The client ap‐ │
10280│ │ │ name) │ plication name. │
10281│ │ │ │ This value is │
10282│ │ │ │ used by MongoDB │
10283│ │ │ │ when it logs │
10284│ │ │ │ connection in‐ │
10285│ │ │ │ formation and │
10286│ │ │ │ profile informa‐ │
10287│ │ │ │ tion, such as │
10288│ │ │ │ slow queries. │
10289├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10290│MONGOC_URI_TLS │ tls │ Empty (not set, │ {true|false}, │
10291│ │ │ same as false) │ indicating if │
10292│ │ │ │ TLS must be │
10293│ │ │ │ used. (See also │
10294│ │ │ │ mongoc_client_set_ssl_opts() │
10295│ │ │ │ and │
10296│ │ │ │ mongoc_client_pool_set_ssl_opts().) │
10297├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10298│MONGOC_URI_COM‐ │ compressors │ Empty (no com‐ │ Comma separated list of compres‐ │
10299│PRESSORS │ │ pressors) │ sors, if any, to use to compress │
10300│ │ │ │ the wire protocol messages. Snappy, │
10301│ │ │ │ zlib, and zstd are optional build │
10302│ │ │ │ time dependencies, and enable the │
10303│ │ │ │ "snappy", "zlib", and "zstd" values │
10304│ │ │ │ respectively. │
10305├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10306│MONGOC_URI_CON‐ │ connecttimeoutms │ 10,000 ms (10 │ This setting applies to new server │
10307│NECTTIMEOUTMS │ │ seconds) │ connections. It is also used as the │
10308│ │ │ │ socket timeout for server discovery │
10309│ │ │ │ and monitoring operations. │
10310├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10311│MONGOC_URI_SOCKET‐ │ sockettimeoutms │ 300,000 ms (5 │ The time in milliseconds to attempt │
10312│TIMEOUTMS │ │ minutes) │ to send or receive on a socket be‐ │
10313│ │ │ │ fore the attempt times out. │
10314├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10315│MONGOC_URI_REPLI‐ │ replicaset │ Empty (no repli‐ │ The name of the Replica Set that │
10316│CASET │ │ caset) │ the driver should connect to. │
10317├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10318│MONGOC_URI_ZLIB‐ │ zlibcompression‐ │ -1 │ When the MONGOC_URI_COMPRESSORS in‐ │
10319│COMPRESSIONLEVEL │ level │ │ cludes "zlib" this options config‐ │
10320│ │ │ │ ures the zlib compression level, │
10321│ │ │ │ when the zlib compressor is used to │
10322│ │ │ │ compress client data. │
10323├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10324│MONGOC_URI_LOAD‐ │ loadbalanced │ false │ If true, this indicates the driver │
10325│BALANCED │ │ │ is connecting to a MongoDB cluster │
10326│ │ │ │ behind a load balancer. │
10327├───────────────────┼──────────────────┼──────────────────┼─────────────────────────────────────┤
10328│MONGOC_URI_SRVMAX‐ │ srvmaxhosts │ 0 │ If zero, the number of hosts in DNS │
10329│HOSTS │ │ │ results is unlimited. If greater │
10330│ │ │ │ than zero, the number of hosts in │
10331│ │ │ │ DNS results is limited to being │
10332│ │ │ │ less than or equal to the given │
10333│ │ │ │ value. │
10334└───────────────────┴──────────────────┴──────────────────┴─────────────────────────────────────┘
10335
10336 Setting any of the *timeoutMS options above to 0 will be interpreted as
10337 "use the default value".
10338
10339 Authentication Options
10340 ─────────────────────────────────────────────────────────────────
10341 Constant Key Description
10342 ─────────────────────────────────────────────────────────────────
10343 MONGOC_URI_AUTH‐ authmechanism Specifies the mech‐
10344 MECHANISM anism to use when
10345 authenticating as
10346 the provided user.
10347 See Authentication
10348 for supported val‐
10349 ues.
10350 ─────────────────────────────────────────────────────────────────
10351 MONGOC_URI_AUTH‐ authmechanismprop‐ Certain authentica‐
10352 MECHANISMPROPERTIES erties tion mechanisms
10353 have additional op‐
10354 tions that can be
10355 configured. These
10356 options should be
10357 provided as comma
10358 separated op‐
10359 tion_key:op‐
10360 tion_value pair and
10361 provided as auth‐
10362 MechanismProper‐
10363 ties. Specifying
10364 the same option_key
10365 multiple times has
10366 undefined behavior.
10367 ─────────────────────────────────────────────────────────────────
10368 MONGOC_URI_AUTH‐ authsource The authSource de‐
10369 SOURCE fines the database
10370 that should be used
10371 to authenticate to.
10372 It is unnecessary
10373 to provide this op‐
10374 tion the database
10375 name is the same as
10376 the database used
10377 in the URI.
10378 ┌────────────────────┬────────────────────┬─────────────────────┐
10379 │ │ │ │
10380 Mechani│sm Properties │ │ │
10381 │┌───────────────────┼┬───────────────────┼─────────────────────┤
10382 ││Constant ││ Key │ Description │
10383 │├───────────────────┼┼───────────────────┼─────────────────────┤
10384 ││MONGOC_URI_CANONI‐ ││ canonicalizehost‐ │ Use the canonical │
10385 ││CALIZEHOSTNAME ││ name │ hostname of the │
10386 ││ ││ │ service, rather │
10387 ││ ││ │ than its configured │
10388 ││ ││ │ alias, when authen‐ │
10389 ││ ││ │ ticating with │
10390 ││ ││ │ Cyrus-SASL Ker‐ │
10391 ││ ││ │ beros. │
10392 │├───────────────────┼┼───────────────────┼─────────────────────┤
10393 ││MONGOC_URI_GSSAPIS‐││ gssapiservicename │ Use alternative │
10394 ││ERVICENAME ││ │ service name. The │
10395 ││ ││ │ default is mongodb. │
10396 │└───────────────────┼┴───────────────────┼─────────────────────┤
10397 │ │ │ │
10398 TLS Opt│ions │ │ │
10399 ├────────────────────┼────────────────────┼┬────────────────────┼┐
10400 │Constant │ Key ││ Description ││
10401 ├────────────────────┼────────────────────┼┼────────────────────┼┤
10402 │MONGOC_URI_TLS │ tls ││ {true|false}, indi‐││
10403 │ │ ││ cating if TLS must││
10404 │ │ ││ be used. ││
10405 ├────────────────────┼────────────────────┼┼────────────────────┼┤
10406 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ ││ Path to PEM format‐││
10407 │TIFICATEKEYFILE │ file ││ ted Private Key,││
10408 │ │ ││ with its Public││
10409 │ │ ││ Certificate con‐││
10410 │ │ ││ catenated at the││
10411 │ │ ││ end. ││
10412 ├────────────────────┼────────────────────┼┼────────────────────┼┤
10413 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ ││ The password, if││
10414 │TIFICATEKEY‐ │ password ││ any, to use to un‐││
10415 │FILEPASSWORD │ ││ lock encrypted Pri‐││
10416 │ │ ││ vate Key. ││
10417 ├────────────────────┼────────────────────┼┴────────────────────┼┘
10418 │ │ │ │
10419 │ │ │ │
10420 │ │ │ │
10421 │ │ │ │
10422 │ │ │ │
10423
10424 │MON‐ │ tlscafile │ One, or a bundle │
10425 │GOC_URI_TLSCAFILE │ │ of, Certificate Au‐ │
10426 │ │ │ thorities whom │
10427 │ │ │ should be consid‐ │
10428 │ │ │ ered to be trusted. │
10429 ├────────────────────┼─────────────────────┼─────────────────────┤
10430 │MONGOC_URI_TLSAL‐ │ tlsallowinvalidcer‐ │ Accept and ignore │
10431 │LOWINVALIDCERTIFI‐ │ tificates │ certificate verifi‐ │
10432 │CATES │ │ cation errors (e.g. │
10433 │ │ │ untrusted issuer, │
10434 │ │ │ expired, etc.) │
10435 ├────────────────────┼─────────────────────┼─────────────────────┤
10436 │MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │ Ignore hostname │
10437 │LOWINVALIDHOSTNAMES │ hostnames │ verification of the │
10438 │ │ │ certificate (e.g. │
10439 │ │ │ Man In The Middle, │
10440 │ │ │ using valid cer‐ │
10441 │ │ │ tificate, but is‐ │
10442 │ │ │ sued for another │
10443 │ │ │ hostname) │
10444 ├────────────────────┼─────────────────────┼─────────────────────┤
10445 │MONGOC_URI_TLSINSE‐ │ tlsinsecure │ {true|false}, indi‐ │
10446 │CURE │ │ cating if insecure │
10447 │ │ │ TLS options should │
10448 │ │ │ be used. Currently │
10449 │ │ │ this implies MON‐ │
10450 │ │ │ GOC_URI_TLSALLOWIN‐ │
10451 │ │ │ VALIDCERTIFICATES │
10452 │ │ │ and MONGOC_URI_TL‐ │
10453 │ │ │ SALLOWINVALIDHOST‐ │
10454 │ │ │ NAMES. │
10455 ├────────────────────┼─────────────────────┼─────────────────────┤
10456 │MONGOC_URI_TLSDIS‐ │ tlsdisablecertifi‐ │ {true|false}, indi‐ │
10457 │ABLECERTIFICATERE‐ │ caterevocationcheck │ cates if revocation │
10458 │VOCATIONCHECK │ │ checking (CRL / │
10459 │ │ │ OCSP) should be │
10460 │ │ │ disabled. │
10461 ├────────────────────┼─────────────────────┼─────────────────────┤
10462 │MONGOC_URI_TLSDIS‐ │ tlsdisableocspend‐ │ {true|false}, indi‐ │
10463 │ABLEOCSPEND‐ │ pointcheck │ cates if OCSP re‐ │
10464 │POINTCHECK │ │ sponder endpoints │
10465 │ │ │ should not be re‐ │
10466 │ │ │ quested when an │
10467 │ │ │ OCSP response is │
10468 │ │ │ not stapled. │
10469 └────────────────────┴─────────────────────┴─────────────────────┘
10470
10471 See Configuring TLS for details about these options and about building
10472 libmongoc with TLS support.
10473
10474 Deprecated SSL Options
10475 The following options have been deprecated and may be removed from fu‐
10476 ture releases of libmongoc.
10477
10478 ┌──────────────────────┬──────────────────┬───────────────────┬──────────────────┐
10479 │Constant │ Key │ Deprecated For │ Key │
10480 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
10481 │MONGOC_URI_SSL │ ssl │ MONGOC_URI_TLS │ tls │
10482 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
10483 │MON‐ │ sslclientcer‐ │ MON‐ │ tlscertifi‐ │
10484 │GOC_URI_SSLCLIENTCER‐ │ tificatekeyfile │ GOC_URI_TLSCER‐ │ catekeyfile │
10485 │TIFICATEKEYFILE │ │ TIFICATEKEYFILE │ │
10486 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
10487 │MON‐ │ sslclientcer‐ │ MON‐ │ tlscertifi‐ │
10488 │GOC_URI_SSLCLIENTCER‐ │ tificatekeypass‐ │ GOC_URI_TLSCER‐ │ catekeypassword │
10489 │TIFICATEKEYPASSWORD │ word │ TIFICATEKEY‐ │ │
10490 │ │ │ FILEPASSWORD │ │
10491 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
10492 │MONGOC_URI_SSLCER‐ │ sslcertifi‐ │ MON‐ │ tlscafile │
10493 │TIFICATEAUTHORITYFILE │ cateauthority‐ │ GOC_URI_TLSCAFILE │ │
10494 │ │ file │ │ │
10495 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
10496 │MONGOC_URI_SSLALLOW‐ │ sslallowinvalid‐ │ MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │
10497 │INVALIDCERTIFICATES │ certificates │ LOWINVALIDCER‐ │ certificates │
10498 │ │ │ TIFICATES │ │
10499 ├──────────────────────┼──────────────────┼───────────────────┼──────────────────┤
10500 │MONGOC_URI_SSLALLOW‐ │ sslallowinvalid‐ │ MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │
10501 │INVALIDHOSTNAMES │ hostnames │ LOWINVALIDHOST‐ │ hostnames │
10502 │ │ │ NAMES │ │
10503 └──────────────────────┴──────────────────┴───────────────────┴──────────────────┘
10504
10505 Server Discovery, Monitoring, and Selection Options
10506 Clients in a mongoc_client_pool_t share a topology scanner that runs on
10507 a background thread. The thread wakes every heartbeatFrequencyMS (de‐
10508 fault 10 seconds) to scan all MongoDB servers in parallel. Whenever an
10509 application operation requires a server that is not known--for example,
10510 if there is no known primary and your application attempts an in‐
10511 sert--the thread rescans all servers every half-second. In this situa‐
10512 tion the pooled client waits up to serverSelectionTimeoutMS (default 30
10513 seconds) for the thread to find a server suitable for the operation,
10514 then returns an error with domain MONGOC_ERROR_SERVER_SELECTION.
10515
10516 Technically, the total time an operation may wait while a pooled client
10517 scans the topology is controlled both by serverSelectionTimeoutMS and
10518 connectTimeoutMS. The longest wait occurs if the last scan begins just
10519 at the end of the selection timeout, and a slow or down server requires
10520 the full connection timeout before the client gives up.
10521
10522 A non-pooled client is single-threaded. Every heartbeatFrequencyMS, it
10523 blocks the next application operation while it does a parallel scan.
10524 This scan takes as long as needed to check the slowest server: roughly
10525 connectTimeoutMS. Therefore the default heartbeatFrequencyMS for sin‐
10526 gle-threaded clients is greater than for pooled clients: 60 seconds.
10527
10528 By default, single-threaded (non-pooled) clients scan only once when an
10529 operation requires a server that is not known. If you attempt an insert
10530 and there is no known primary, the client checks all servers once try‐
10531 ing to find it, then succeeds or returns an error with domain MON‐
10532 GOC_ERROR_SERVER_SELECTION. But if you set serverSelectionTryOnce to
10533 "false", the single-threaded client loops, checking all servers every
10534 half-second, until serverSelectionTimeoutMS.
10535
10536 The total time an operation may wait for a single-threaded client to
10537 scan the topology is determined by connectTimeoutMS in the try-once
10538 case, or serverSelectionTimeoutMS and connectTimeoutMS if serverSelec‐
10539 tionTryOnce is set "false".
10540
10541 ┌────────────────────┬─────────────────────┬─────────────────────┐
10542 │Constant │ Key │ Description │
10543 ├────────────────────┼─────────────────────┼─────────────────────┤
10544 │MONGOC_URI_HEART‐ │ heartbeatfrequen‐ │ The interval be‐ │
10545 │BEATFREQUENCYMS │ cyms │ tween server moni‐ │
10546 │ │ │ toring checks. De‐ │
10547 │ │ │ faults to 10,000ms │
10548 │ │ │ (10 seconds) in │
10549 │ │ │ pooled │
10550 │ │ │ (multi-threaded) │
10551 │ │ │ mode, 60,000ms (60 │
10552 │ │ │ seconds) in │
10553 │ │ │ non-pooled mode │
10554 │ │ │ (single-threaded). │
10555 ├────────────────────┼─────────────────────┼─────────────────────┤
10556 │MONGOC_URI_SERVERS‐ │ serverselection‐ │ A timeout in mil‐ │
10557 │ELECTIONTIMEOUTMS │ timeoutms │ liseconds to block │
10558 │ │ │ for server selec‐ │
10559 │ │ │ tion before throw‐ │
10560 │ │ │ ing an exception. │
10561 │ │ │ The default is │
10562 │ │ │ 30,0000ms (30 sec‐ │
10563 │ │ │ onds). │
10564 └────────────────────┴─────────────────────┴─────────────────────┘
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592 │MONGOC_URI_SERVERS‐ │ serverselectiontry‐ │ If "true", the │
10593 │ELECTIONTRYONCE │ once │ driver scans the │
10594 │ │ │ topology exactly │
10595 │ │ │ once after server │
10596 │ │ │ selection fails, │
10597 │ │ │ then either selects │
10598 │ │ │ a server or returns │
10599 │ │ │ an error. If it is │
10600 │ │ │ false, then the │
10601 │ │ │ driver repeatedly │
10602 │ │ │ searches for a │
10603 │ │ │ suitable server for │
10604 │ │ │ up to serverSelec‐ │
10605 │ │ │ tionTimeoutMS mil‐ │
10606 │ │ │ liseconds (pausing │
10607 │ │ │ a half second be‐ │
10608 │ │ │ tween attempts). │
10609 │ │ │ The default for │
10610 │ │ │ serverSelectionTry‐ │
10611 │ │ │ Once is "false" for │
10612 │ │ │ pooled clients, │
10613 │ │ │ otherwise "true". │
10614 │ │ │ Pooled clients ig‐ │
10615 │ │ │ nore serverSelec‐ │
10616 │ │ │ tionTryOnce; they │
10617 │ │ │ signal the thread │
10618 │ │ │ to rescan the │
10619 │ │ │ topology every │
10620 │ │ │ half-second until │
10621 │ │ │ serverSelection‐ │
10622 │ │ │ TimeoutMS expires. │
10623 ├────────────────────┼─────────────────────┼─────────────────────┤
10624 │MONGOC_URI_SOCK‐ │ socketcheckinter‐ │ Only applies to │
10625 │ETCHECKINTERVALMS │ valms │ single threaded │
10626 │ │ │ clients. If a │
10627 │ │ │ socket has not been │
10628 │ │ │ used within this │
10629 │ │ │ time, its connec‐ │
10630 │ │ │ tion is checked │
10631 │ │ │ with a quick │
10632 │ │ │ "hello" call before │
10633 │ │ │ it is used again. │
10634 │ │ │ Defaults to 5,000ms │
10635 │ │ │ (5 seconds). │
10636 ├────────────────────┼─────────────────────┼─────────────────────┤
10637 │MONGOC_URI_DIRECT‐ │ directconnection │ If "true", the │
10638 │CONNECTION │ │ driver connects to │
10639 │ │ │ a single server di‐ │
10640 │ │ │ rectly and will not │
10641 │ │ │ monitor additional │
10642 │ │ │ servers. If │
10643 │ │ │ "false", the driver │
10644 │ │ │ connects based on │
10645 │ │ │ the presence and │
10646 │ │ │ value of the repli‐ │
10647 │ │ │ caSet option. │
10648 └────────────────────┴─────────────────────┴─────────────────────┘
10649
10650 Setting any of the *TimeoutMS options above to 0 will be interpreted as
10651 "use the default value".
10652
10653 Connection Pool Options
10654 These options govern the behavior of a mongoc_client_pool_t. They are
10655 ignored by a non-pooled mongoc_client_t.
10656
10657 ┌────────────────────┬────────────────────┬──────────────────────────┐
10658 │Constant │ Key │ Description │
10659 ├────────────────────┼────────────────────┼──────────────────────────┤
10660 │MONGOC_URI_MAXPOOL‐ │ maxpoolsize │ The maximum number │
10661 │SIZE │ │ of clients created │
10662 │ │ │ by a │
10663 │ │ │ mongoc_client_pool_t │
10664 │ │ │ total (both in the │
10665 │ │ │ pool and checked │
10666 │ │ │ out). The default │
10667 │ │ │ value is 100. Once │
10668 │ │ │ it is reached, │
10669 │ │ │ mongoc_client_pool_pop() │
10670 │ │ │ blocks until an‐ │
10671 │ │ │ other thread pushes │
10672 │ │ │ a client. │
10673 └────────────────────┴────────────────────┴──────────────────────────┘
10674
10675
10676 │MONGOC_URI_MINPOOL‐ │ minpoolsize │ Deprecated. This op‐ │
10677 │SIZE │ │ tion's behavior does not │
10678 │ │ │ match its name, and its │
10679 │ │ │ actual behavior will │
10680 │ │ │ likely hurt performance. │
10681 ├────────────────────┼────────────────────┼──────────────────────────┤
10682 │MONGOC_URI_MAXIDLE‐ │ maxidletimems │ Not implemented. │
10683 │TIMEMS │ │ │
10684 ├────────────────────┼────────────────────┼──────────────────────────┤
10685 │MONGOC_URI_WAIT‐ │ waitqueuemultiple │ Not implemented. │
10686 │QUEUEMULTIPLE │ │ │
10687 ├────────────────────┼────────────────────┼──────────────────────────┤
10688 │MONGOC_URI_WAIT‐ │ waitqueuetimeoutms │ The maximum time to wait │
10689 │QUEUETIMEOUTMS │ │ for a client to become │
10690 │ │ │ available from the pool. │
10691 └────────────────────┴────────────────────┴──────────────────────────┘
10692
10693 Write Concern Options
10694 ┌───────────────────┬────────────┬─────────────────────┐
10695 │Constant │ Key │ Description │
10696 └───────────────────┴────────────┴─────────────────────┘
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749
10750
10751
10752
10753
10754
10755
10756
10757
10758
10759
10760 MONGOC_URI_W w Determines the
10761 write concern
10762 (guarantee). Valid
10763 values:
10764
10765 • 0 = The
10766 driver
10767 will not
10768 acknowl‐
10769 edge write
10770 operations
10771 but will
10772 pass or
10773 handle any
10774 network
10775 and socket
10776 errors
10777 that it
10778 receives
10779 to the
10780 client. If
10781 you dis‐
10782 able write
10783 concern
10784 but enable
10785 the get‐
10786 LastError
10787 command’s
10788 w option,
10789 w over‐
10790 rides the
10791 w option.
10792
10793 • 1 = Pro‐
10794 vides ba‐
10795 sic ac‐
10796 knowledge‐
10797 ment of
10798 write op‐
10799 erations.
10800 By speci‐
10801 fying 1,
10802 you re‐
10803 quire that
10804 a stand‐
10805 alone mon‐
10806 god in‐
10807 stance, or
10808 the pri‐
10809 mary for
10810 replica
10811 sets, ac‐
10812 knowledge
10813 all write
10814 opera‐
10815 tions. For
10816 drivers
10817 released
10818 after the
10819 default
10820 write con‐
10821 cern
10822 change,
10823 this is
10824 the de‐
10825 fault
10826 write con‐
10827 cern set‐
10828 ting.
10829
10830 • majority =
10831 For
10832 replica
10833 sets, if
10834 you spec‐
10835 ify the
10836 special
10837 majority
10838 value to w
10839 option,
10840 write op‐
10841 erations
10842 will only
10843 return
10844 success‐
10845 fully af‐
10846 ter a ma‐
10847 jority of
10848 the con‐
10849 figured
10850 replica
10851 set mem‐
10852 bers have
10853 acknowl‐
10854 edged the
10855 write op‐
10856 eration.
10857
10858 • n = For
10859 replica
10860 sets, if
10861 you spec‐
10862 ify a num‐
10863 ber n
10864 greater
10865 than 1,
10866 operations
10867 with this
10868 write con‐
10869 cern re‐
10870 turn only
10871 after n
10872 members of
10873 the set
10874 have ac‐
10875 knowledged
10876 the write.
10877 If you set
10878 n to a
10879 number
10880 that is
10881 greater
10882 than the
10883 number of
10884 available
10885 set mem‐
10886 bers or
10887 members
10888 that hold
10889 data, Mon‐
10890 goDB will
10891 wait, po‐
10892 tentially
10893 indefi‐
10894 nitely,
10895 for these
10896 members to
10897 become
10898 available.
10899
10900 • tags = For
10901 replica
10902 sets, you
10903 can spec‐
10904 ify a tag
10905 set to re‐
10906 quire that
10907 all mem‐
10908 bers of
10909 the set
10910 that have
10911 these tags
10912 configured
10913 return
10914 confirma‐
10915 tion of
10916 the write
10917 operation.
10918 ├───────────────────┼────────────┼─────────────────────┤
10919 │MONGOC_URI_WTIME‐ │ wtimeoutms │ The time in mil‐ │
10920 │OUTMS │ │ liseconds to wait │
10921 │ │ │ for replication to │
10922 │ │ │ succeed, as speci‐ │
10923 │ │ │ fied in the w op‐ │
10924 │ │ │ tion, before timing │
10925 │ │ │ out. When wtime‐ │
10926 │ │ │ outMS is 0, write │
10927 │ │ │ operations will │
10928 │ │ │ never time out. │
10929 ├───────────────────┼────────────┼─────────────────────┤
10930 │MONGOC_URI_JOURNAL │ journal │ Controls whether │
10931 │ │ │ write operations │
10932 │ │ │ will wait until the │
10933 │ │ │ mongod acknowledges │
10934 │ │ │ the write opera‐ │
10935 │ │ │ tions and commits │
10936 │ │ │ the data to the on │
10937 │ │ │ disk journal. │
10938 │ │ │ │
10939 │ │ │ • true = │
10940 │ │ │ Enables │
10941 │ │ │ journal │
10942 │ │ │ commit ac‐ │
10943 │ │ │ knowledge‐ │
10944 │ │ │ ment write │
10945 │ │ │ concern. │
10946 │ │ │ Equivalent │
10947 │ │ │ to speci‐ │
10948 │ │ │ fying the │
10949 │ │ │ getLastEr‐ │
10950 │ │ │ ror com‐ │
10951 │ │ │ mand with │
10952 │ │ │ the j op‐ │
10953 │ │ │ tion en‐ │
10954 │ │ │ abled. │
10955 │ │ │ │
10956 │ │ │ • false = │
10957 │ │ │ Does not │
10958 │ │ │ require │
10959 │ │ │ that mon‐ │
10960 │ │ │ god commit │
10961 │ │ │ write op‐ │
10962 │ │ │ erations │
10963 │ │ │ to the │
10964 │ │ │ journal │
10965 │ │ │ before ac‐ │
10966 │ │ │ knowledg‐ │
10967 │ │ │ ing the │
10968 │ │ │ write op‐ │
10969 │ │ │ eration. │
10970 │ │ │ This is │
10971 │ │ │ the de‐ │
10972 │ │ │ fault op‐ │
10973 │ │ │ tion for │
10974 │ │ │ the jour‐ │
10975 │ │ │ nal param‐ │
10976 │ │ │ eter. │
10977 └───────────────────┴────────────┴─────────────────────┘
10978
10979 Read Concern Options
10980 ┌────────────────────┬──────────────────┬─────────────────────┐
10981 │Constant │ Key │ Description │
10982 ├────────────────────┼──────────────────┼─────────────────────┤
10983 │MONGOC_URI_READCON‐ │ readconcernlevel │ The level of isola‐ │
10984 │CERNLEVEL │ │ tion for read oper‐ │
10985 │ │ │ ations. If the │
10986 │ │ │ level is left un‐ │
10987 │ │ │ specified, the │
10988 │ │ │ server default will │
10989 │ │ │ be used. See │
10990 │ │ │ readConcern in the │
10991 │ │ │ MongoDB Manual for │
10992 │ │ │ details. │
10993 └────────────────────┴──────────────────┴─────────────────────┘
10994
10995 Read Preference Options
10996 When connected to a replica set, the driver chooses which member to
10997 query using the read preference:
10998
10999 1. Choose members whose type matches "readPreference".
11000
11001 2. From these, if there are any tags sets configured, choose members
11002 matching the first tag set. If there are none, fall back to the next
11003 tag set and so on, until some members are chosen or the tag sets are
11004 exhausted.
11005
11006 3. From the chosen servers, distribute queries randomly among the
11007 server with the fastest round-trip times. These include the server
11008 with the fastest time and any whose round-trip time is no more than
11009 "localThresholdMS" slower.
11010
11011 ┌────────────────────┬─────────────────────┬─────────────────────┐
11012 │Constant │ Key │ Description │
11013 ├────────────────────┼─────────────────────┼─────────────────────┤
11014 │MONGOC_URI_READ‐ │ readpreference │ Specifies the │
11015 │PREFERENCE │ │ replica set read │
11016 │ │ │ preference for this │
11017 │ │ │ connection. This │
11018 │ │ │ setting overrides │
11019 │ │ │ any secondaryOk │
11020 │ │ │ value. The read │
11021 │ │ │ preference values │
11022 │ │ │ are the following: │
11023 │ │ │ │
11024 │ │ │ • primary │
11025 │ │ │ (default) │
11026 │ │ │ │
11027 │ │ │ • prima‐ │
11028 │ │ │ ryPre‐ │
11029 │ │ │ ferred │
11030 │ │ │ │
11031 │ │ │ • secondary │
11032 │ │ │ │
11033 │ │ │ • sec‐ │
11034 │ │ │ ondaryPre‐ │
11035 │ │ │ ferred │
11036 │ │ │ │
11037 │ │ │ • nearest │
11038 ├────────────────────┼─────────────────────┼─────────────────────┤
11039 │MONGOC_URI_READ‐ │ readpreferencetags │ A representation of │
11040 │PREFERENCETAGS │ │ a tag set. See also │
11041 │ │ │ Tag Sets. │
11042 ├────────────────────┼─────────────────────┼─────────────────────┤
11043 │MONGOC_URI_LO‐ │ localthresholdms │ How far to distrib‐ │
11044 │CALTHRESHOLDMS │ │ ute queries, beyond │
11045 │ │ │ the server with the │
11046 │ │ │ fastest round-trip │
11047 │ │ │ time. By default, │
11048 │ │ │ only servers within │
11049 │ │ │ 15ms of the fastest │
11050 │ │ │ round-trip time re‐ │
11051 │ │ │ ceive queries. │
11052 ├────────────────────┼─────────────────────┼─────────────────────┤
11053 │MONGOC_URI_MAXSTAL‐ │ maxstalenessseconds │ The maximum repli‐ │
11054 │ENESSSECONDS │ │ cation lag, in wall │
11055 │ │ │ clock time, that a │
11056 │ │ │ secondary can suf‐ │
11057 │ │ │ fer and still be │
11058 │ │ │ eligible. The │
11059 │ │ │ smallest allowed │
11060 │ │ │ value for maxStale‐ │
11061 │ │ │ nessSeconds is 90 │
11062 │ │ │ seconds. │
11063 └────────────────────┴─────────────────────┴─────────────────────┘
11064
11065 NOTE:
11066 When connecting to more than one mongos, libmongoc's localThresh‐
11067 oldMS applies only to the selection of mongos servers. The threshold
11068 for selecting among replica set members in shards is controlled by
11069 the mongos's localThreshold command line option.
11070
11071 Legacy Options
11072 For historical reasons, the following options are available. They
11073 should however not be used.
11074
11075 ┌────────────────┬──────┬─────────────────────┐
11076 │Constant │ Key │ Description │
11077 ├────────────────┼──────┼─────────────────────┤
11078 │MONGOC_URI_SAFE │ safe │ {true|false} Same │
11079 │ │ │ as w={1|0} │
11080 └────────────────┴──────┴─────────────────────┘
11081
11082 Version Checks
11083 Conditional compilation based on mongoc version
11084
11085 Description
11086 The following preprocessor macros can be used to perform various checks
11087 based on the version of the library you are compiling against. This
11088 may be useful if you only want to enable a feature on a certain version
11089 of the library.
11090
11091 #include <mongoc/mongoc.h>
11092
11093 #define MONGOC_MAJOR_VERSION (x)
11094 #define MONGOC_MINOR_VERSION (y)
11095 #define MONGOC_MICRO_VERSION (z)
11096 #define MONGOC_VERSION_S "x.y.z"
11097 #define MONGOC_VERSION_HEX ((1 << 24) | (0 << 16) | (0 << 8) | 0)
11098 #define MONGOC_CHECK_VERSION(major, minor, micro)
11099
11100 Only compile a block on MongoDB C Driver 1.1.0 and newer.
11101
11102 #if MONGOC_CHECK_VERSION(1, 1, 0)
11103 static void
11104 do_something (void)
11105 {
11106 }
11107 #endif
11108
11109 mongoc_write_concern_t
11110 Write Concern abstraction
11111
11112 Synopsis
11113 mongoc_write_concern_t tells the driver what level of acknowledgement
11114 to await from the server. The default, MONGOC_WRITE_CONCERN_W_DEFAULT,
11115 is right for the great majority of applications.
11116
11117 You can specify a write concern on connection objects, database ob‐
11118 jects, collection objects, or per-operation. Data-modifying operations
11119 typically use the write concern of the object they operate on, and
11120 check the server response for a write concern error or write concern
11121 timeout. For example, mongoc_collection_drop_index() uses the collec‐
11122 tion's write concern, and a write concern error or timeout in the re‐
11123 sponse is considered a failure.
11124
11125 Exceptions to this principle are the generic command functions:
11126
11127 • mongoc_client_command()
11128
11129 • mongoc_client_command_simple()
11130
11131 • mongoc_database_command()
11132
11133 • mongoc_database_command_simple()
11134
11135 • mongoc_collection_command()
11136
11137 • mongoc_collection_command_simple()
11138
11139 These generic command functions do not automatically apply a write con‐
11140 cern, and they do not check the server response for a write concern er‐
11141 ror or write concern timeout.
11142
11143 See Write Concern on the MongoDB website for more information.
11144
11145 Write Concern Levels
11146 Set the write concern level with mongoc_write_concern_set_w().
11147
11148 ┌───────────────────────────┬────────────────────────────┐
11149 │MONGOC_WRITE_CONCERN_W_DE‐ │ By default, writes block │
11150 │FAULT (1) │ awaiting acknowledgement │
11151 │ │ from MongoDB. Acknowledged │
11152 │ │ write concern allows │
11153 │ │ clients to catch network, │
11154 │ │ duplicate key, and other │
11155 │ │ errors. │
11156 ├───────────────────────────┼────────────────────────────┤
11157 │MONGOC_WRITE_CONCERN_W_UN‐ │ With this write concern, │
11158 │ACKNOWLEDGED (0) │ MongoDB does not acknowl‐ │
11159 │ │ edge the receipt of write │
11160 │ │ operation. Unacknowledged │
11161 │ │ is similar to errors ig‐ │
11162 │ │ nored; however, mongoc at‐ │
11163 │ │ tempts to receive and han‐ │
11164 │ │ dle network errors when │
11165 │ │ possible. │
11166 ├───────────────────────────┼────────────────────────────┤
11167 │MONGOC_WRITE_CONCERN_W_MA‐ │ Block until a write has │
11168 │JORITY (majority) │ been propagated to a ma‐ │
11169 │ │ jority of the nodes in the │
11170 │ │ replica set. │
11171 └───────────────────────────┴────────────────────────────┘
11172
11173 │n │ Block until a write has │
11174 │ │ been propagated to at │
11175 │ │ least n nodes in the │
11176 │ │ replica set. │
11177 └───────────────────────────┴────────────────────────────┘
11178
11179 Deprecations
11180 The write concern MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED (value -1) is a
11181 deprecated synonym for MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (value 0),
11182 and will be removed in the next major release.
11183
11184 mongoc_write_concern_set_fsync() is deprecated.
11185
11186 Application Performance Monitoring (APM)
11187 The MongoDB C Driver allows you to monitor all the MongoDB operations
11188 the driver executes. This event-notification system conforms to two
11189 MongoDB driver specs:
11190
11191 • Command Logging and Monitoring: events related to all application op‐
11192 erations.
11193
11194 • SDAM Monitoring: events related to the driver's Server Discovery And
11195 Monitoring logic.
11196
11197 To receive notifications, create a mongoc_apm_callbacks_t with
11198 mongoc_apm_callbacks_new(), set callbacks on it, then pass it to
11199 mongoc_client_set_apm_callbacks() or
11200 mongoc_client_pool_set_apm_callbacks().
11201
11202 Command-Monitoring Example
11203 example-command-monitoring.c
11204
11205 /* gcc example-command-monitoring.c -o example-command-monitoring \
11206 * $(pkg-config --cflags --libs libmongoc-1.0) */
11207
11208 /* ./example-command-monitoring [CONNECTION_STRING] */
11209
11210 #include <mongoc/mongoc.h>
11211 #include <stdio.h>
11212
11213
11214 typedef struct {
11215 int started;
11216 int succeeded;
11217 int failed;
11218 } stats_t;
11219
11220
11221 void
11222 command_started (const mongoc_apm_command_started_t *event)
11223 {
11224 char *s;
11225
11226 s = bson_as_relaxed_extended_json (
11227 mongoc_apm_command_started_get_command (event), NULL);
11228 printf ("Command %s started on %s:\n%s\n\n",
11229 mongoc_apm_command_started_get_command_name (event),
11230 mongoc_apm_command_started_get_host (event)->host,
11231 s);
11232
11233 ((stats_t *) mongoc_apm_command_started_get_context (event))->started++;
11234
11235 bson_free (s);
11236 }
11237
11238
11239 void
11240 command_succeeded (const mongoc_apm_command_succeeded_t *event)
11241 {
11242 char *s;
11243
11244 s = bson_as_relaxed_extended_json (
11245 mongoc_apm_command_succeeded_get_reply (event), NULL);
11246 printf ("Command %s succeeded:\n%s\n\n",
11247 mongoc_apm_command_succeeded_get_command_name (event),
11248 s);
11249
11250 ((stats_t *) mongoc_apm_command_succeeded_get_context (event))->succeeded++;
11251
11252 bson_free (s);
11253 }
11254
11255
11256 void
11257 command_failed (const mongoc_apm_command_failed_t *event)
11258 {
11259 bson_error_t error;
11260
11261 mongoc_apm_command_failed_get_error (event, &error);
11262 printf ("Command %s failed:\n\"%s\"\n\n",
11263 mongoc_apm_command_failed_get_command_name (event),
11264 error.message);
11265
11266 ((stats_t *) mongoc_apm_command_failed_get_context (event))->failed++;
11267 }
11268
11269
11270 int
11271 main (int argc, char *argv[])
11272 {
11273 mongoc_client_t *client;
11274 mongoc_apm_callbacks_t *callbacks;
11275 stats_t stats = {0};
11276 mongoc_collection_t *collection;
11277 bson_error_t error;
11278 const char *uri_string =
11279 "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
11280 mongoc_uri_t *uri;
11281 const char *collection_name = "test";
11282 bson_t *docs[2];
11283
11284 mongoc_init ();
11285
11286 if (argc > 1) {
11287 uri_string = argv[1];
11288 }
11289
11290 uri = mongoc_uri_new_with_error (uri_string, &error);
11291 if (!uri) {
11292 fprintf (stderr,
11293 "failed to parse URI: %s\n"
11294 "error message: %s\n",
11295 uri_string,
11296 error.message);
11297 return EXIT_FAILURE;
11298 }
11299
11300 client = mongoc_client_new_from_uri (uri);
11301 if (!client) {
11302 return EXIT_FAILURE;
11303 }
11304
11305 mongoc_client_set_error_api (client, 2);
11306 callbacks = mongoc_apm_callbacks_new ();
11307 mongoc_apm_set_command_started_cb (callbacks, command_started);
11308 mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
11309 mongoc_apm_set_command_failed_cb (callbacks, command_failed);
11310 mongoc_client_set_apm_callbacks (
11311 client, callbacks, (void *) &stats /* context pointer */);
11312
11313 collection = mongoc_client_get_collection (client, "test", collection_name);
11314 mongoc_collection_drop (collection, NULL);
11315
11316 docs[0] = BCON_NEW ("_id", BCON_INT32 (0));
11317 docs[1] = BCON_NEW ("_id", BCON_INT32 (1));
11318 mongoc_collection_insert_many (
11319 collection, (const bson_t **) docs, 2, NULL, NULL, NULL);
11320
11321 /* duplicate key error on the second insert */
11322 mongoc_collection_insert_one (collection, docs[0], NULL, NULL, NULL);
11323
11324 mongoc_collection_destroy (collection);
11325 mongoc_apm_callbacks_destroy (callbacks);
11326 mongoc_uri_destroy (uri);
11327 mongoc_client_destroy (client);
11328
11329 printf ("started: %d\nsucceeded: %d\nfailed: %d\n",
11330 stats.started,
11331 stats.succeeded,
11332 stats.failed);
11333
11334 bson_destroy (docs[0]);
11335 bson_destroy (docs[1]);
11336
11337 mongoc_cleanup ();
11338
11339 return EXIT_SUCCESS;
11340 }
11341
11342
11343 This example program prints:
11344
11345 Command drop started on 127.0.0.1:
11346 { "drop" : "test" }
11347
11348 Command drop succeeded:
11349 { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }
11350
11351 Command insert started on 127.0.0.1:
11352 {
11353 "insert" : "test",
11354 "ordered" : true,
11355 "documents" : [
11356 { "_id" : 0 }, { "_id" : 1 }
11357 ]
11358 }
11359
11360 Command insert succeeded:
11361 { "n" : 2, "ok" : 1.0 }
11362
11363 Command insert started on 127.0.0.1:
11364 {
11365 "insert" : "test",
11366 "ordered" : true,
11367 "documents" : [
11368 { "_id" : 0 }
11369 ]
11370 }
11371
11372 Command insert succeeded:
11373 {
11374 "n" : 0,
11375 "writeErrors" : [
11376 { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
11377 ],
11378 "ok" : 1.0
11379 }
11380
11381 started: 3
11382 succeeded: 3
11383 failed: 0
11384
11385 The output has been edited and formatted for clarity. Depending on your
11386 server configuration, messages may include metadata like database name,
11387 logical session ids, or cluster times that are not shown here.
11388
11389 The final "insert" command is considered successful, despite the
11390 writeError, because the server replied to the overall command with
11391 "ok": 1.
11392
11393 SDAM Monitoring Example
11394 example-sdam-monitoring.c
11395
11396 /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
11397 * $(pkg-config --cflags --libs libmongoc-1.0) */
11398
11399 /* ./example-sdam-monitoring [CONNECTION_STRING] */
11400
11401 #include <mongoc/mongoc.h>
11402 #include <stdio.h>
11403
11404
11405 typedef struct {
11406 int server_changed_events;
11407 int server_opening_events;
11408 int server_closed_events;
11409 int topology_changed_events;
11410 int topology_opening_events;
11411 int topology_closed_events;
11412 int heartbeat_started_events;
11413 int heartbeat_succeeded_events;
11414 int heartbeat_failed_events;
11415 } stats_t;
11416
11417
11418 static void
11419 server_changed (const mongoc_apm_server_changed_t *event)
11420 {
11421 stats_t *context;
11422 const mongoc_server_description_t *prev_sd, *new_sd;
11423
11424 context = (stats_t *) mongoc_apm_server_changed_get_context (event);
11425 context->server_changed_events++;
11426
11427 prev_sd = mongoc_apm_server_changed_get_previous_description (event);
11428 new_sd = mongoc_apm_server_changed_get_new_description (event);
11429
11430 printf ("server changed: %s %s -> %s\n",
11431 mongoc_apm_server_changed_get_host (event)->host_and_port,
11432 mongoc_server_description_type (prev_sd),
11433 mongoc_server_description_type (new_sd));
11434 }
11435
11436
11437 static void
11438 server_opening (const mongoc_apm_server_opening_t *event)
11439 {
11440 stats_t *context;
11441
11442 context = (stats_t *) mongoc_apm_server_opening_get_context (event);
11443 context->server_opening_events++;
11444
11445 printf ("server opening: %s\n",
11446 mongoc_apm_server_opening_get_host (event)->host_and_port);
11447 }
11448
11449
11450 static void
11451 server_closed (const mongoc_apm_server_closed_t *event)
11452 {
11453 stats_t *context;
11454
11455 context = (stats_t *) mongoc_apm_server_closed_get_context (event);
11456 context->server_closed_events++;
11457
11458 printf ("server closed: %s\n",
11459 mongoc_apm_server_closed_get_host (event)->host_and_port);
11460 }
11461
11462
11463 static void
11464 topology_changed (const mongoc_apm_topology_changed_t *event)
11465 {
11466 stats_t *context;
11467 const mongoc_topology_description_t *prev_td;
11468 const mongoc_topology_description_t *new_td;
11469 mongoc_server_description_t **prev_sds;
11470 size_t n_prev_sds;
11471 mongoc_server_description_t **new_sds;
11472 size_t n_new_sds;
11473 size_t i;
11474 mongoc_read_prefs_t *prefs;
11475
11476 context = (stats_t *) mongoc_apm_topology_changed_get_context (event);
11477 context->topology_changed_events++;
11478
11479 prev_td = mongoc_apm_topology_changed_get_previous_description (event);
11480 prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds);
11481 new_td = mongoc_apm_topology_changed_get_new_description (event);
11482 new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds);
11483
11484 printf ("topology changed: %s -> %s\n",
11485 mongoc_topology_description_type (prev_td),
11486 mongoc_topology_description_type (new_td));
11487
11488 if (n_prev_sds) {
11489 printf (" previous servers:\n");
11490 for (i = 0; i < n_prev_sds; i++) {
11491 printf (" %s %s\n",
11492 mongoc_server_description_type (prev_sds[i]),
11493 mongoc_server_description_host (prev_sds[i])->host_and_port);
11494 }
11495 }
11496
11497 if (n_new_sds) {
11498 printf (" new servers:\n");
11499 for (i = 0; i < n_new_sds; i++) {
11500 printf (" %s %s\n",
11501 mongoc_server_description_type (new_sds[i]),
11502 mongoc_server_description_host (new_sds[i])->host_and_port);
11503 }
11504 }
11505
11506 prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
11507
11508 /* it is safe, and unfortunately necessary, to cast away const here */
11509 if (mongoc_topology_description_has_readable_server (
11510 (mongoc_topology_description_t *) new_td, prefs)) {
11511 printf (" secondary AVAILABLE\n");
11512 } else {
11513 printf (" secondary UNAVAILABLE\n");
11514 }
11515
11516 if (mongoc_topology_description_has_writable_server (
11517 (mongoc_topology_description_t *) new_td)) {
11518 printf (" primary AVAILABLE\n");
11519 } else {
11520 printf (" primary UNAVAILABLE\n");
11521 }
11522
11523 mongoc_read_prefs_destroy (prefs);
11524 mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds);
11525 mongoc_server_descriptions_destroy_all (new_sds, n_new_sds);
11526 }
11527
11528
11529 static void
11530 topology_opening (const mongoc_apm_topology_opening_t *event)
11531 {
11532 stats_t *context;
11533
11534 context = (stats_t *) mongoc_apm_topology_opening_get_context (event);
11535 context->topology_opening_events++;
11536
11537 printf ("topology opening\n");
11538 }
11539
11540
11541 static void
11542 topology_closed (const mongoc_apm_topology_closed_t *event)
11543 {
11544 stats_t *context;
11545
11546 context = (stats_t *) mongoc_apm_topology_closed_get_context (event);
11547 context->topology_closed_events++;
11548
11549 printf ("topology closed\n");
11550 }
11551
11552
11553 static void
11554 server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event)
11555 {
11556 stats_t *context;
11557
11558 context =
11559 (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event);
11560 context->heartbeat_started_events++;
11561
11562 printf ("%s heartbeat started\n",
11563 mongoc_apm_server_heartbeat_started_get_host (event)->host_and_port);
11564 }
11565
11566
11567 static void
11568 server_heartbeat_succeeded (
11569 const mongoc_apm_server_heartbeat_succeeded_t *event)
11570 {
11571 stats_t *context;
11572 char *reply;
11573
11574 context =
11575 (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event);
11576 context->heartbeat_succeeded_events++;
11577
11578 reply = bson_as_canonical_extended_json (
11579 mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL);
11580
11581 printf (
11582 "%s heartbeat succeeded: %s\n",
11583 mongoc_apm_server_heartbeat_succeeded_get_host (event)->host_and_port,
11584 reply);
11585
11586 bson_free (reply);
11587 }
11588
11589
11590 static void
11591 server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event)
11592 {
11593 stats_t *context;
11594 bson_error_t error;
11595
11596 context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event);
11597 context->heartbeat_failed_events++;
11598 mongoc_apm_server_heartbeat_failed_get_error (event, &error);
11599
11600 printf ("%s heartbeat failed: %s\n",
11601 mongoc_apm_server_heartbeat_failed_get_host (event)->host_and_port,
11602 error.message);
11603 }
11604
11605
11606 int
11607 main (int argc, char *argv[])
11608 {
11609 mongoc_client_t *client;
11610 mongoc_apm_callbacks_t *cbs;
11611 stats_t stats = {0};
11612 const char *uri_string =
11613 "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
11614 mongoc_uri_t *uri;
11615 bson_t cmd = BSON_INITIALIZER;
11616 bson_t reply;
11617 bson_error_t error;
11618
11619 mongoc_init ();
11620
11621 if (argc > 1) {
11622 uri_string = argv[1];
11623 }
11624
11625 uri = mongoc_uri_new_with_error (uri_string, &error);
11626 if (!uri) {
11627 fprintf (stderr,
11628 "failed to parse URI: %s\n"
11629 "error message: %s\n",
11630 uri_string,
11631 error.message);
11632 return EXIT_FAILURE;
11633 }
11634
11635 client = mongoc_client_new_from_uri (uri);
11636 if (!client) {
11637 return EXIT_FAILURE;
11638 }
11639
11640 mongoc_client_set_error_api (client, 2);
11641 cbs = mongoc_apm_callbacks_new ();
11642 mongoc_apm_set_server_changed_cb (cbs, server_changed);
11643 mongoc_apm_set_server_opening_cb (cbs, server_opening);
11644 mongoc_apm_set_server_closed_cb (cbs, server_closed);
11645 mongoc_apm_set_topology_changed_cb (cbs, topology_changed);
11646 mongoc_apm_set_topology_opening_cb (cbs, topology_opening);
11647 mongoc_apm_set_topology_closed_cb (cbs, topology_closed);
11648 mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started);
11649 mongoc_apm_set_server_heartbeat_succeeded_cb (cbs,
11650 server_heartbeat_succeeded);
11651 mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed);
11652 mongoc_client_set_apm_callbacks (
11653 client, cbs, (void *) &stats /* context pointer */);
11654
11655 /* the driver connects on demand to perform first operation */
11656 BSON_APPEND_INT32 (&cmd, "buildinfo", 1);
11657 mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error);
11658 mongoc_uri_destroy (uri);
11659 mongoc_client_destroy (client);
11660
11661 printf ("Events:\n"
11662 " server changed: %d\n"
11663 " server opening: %d\n"
11664 " server closed: %d\n"
11665 " topology changed: %d\n"
11666 " topology opening: %d\n"
11667 " topology closed: %d\n"
11668 " heartbeat started: %d\n"
11669 " heartbeat succeeded: %d\n"
11670 " heartbeat failed: %d\n",
11671 stats.server_changed_events,
11672 stats.server_opening_events,
11673 stats.server_closed_events,
11674 stats.topology_changed_events,
11675 stats.topology_opening_events,
11676 stats.topology_closed_events,
11677 stats.heartbeat_started_events,
11678 stats.heartbeat_succeeded_events,
11679 stats.heartbeat_failed_events);
11680
11681 bson_destroy (&cmd);
11682 bson_destroy (&reply);
11683 mongoc_apm_callbacks_destroy (cbs);
11684
11685 mongoc_cleanup ();
11686
11687 return EXIT_SUCCESS;
11688 }
11689
11690
11691 Start a 3-node replica set on localhost with set name "rs" and start
11692 the program:
11693
11694 ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"
11695
11696 This example program prints something like:
11697
11698 topology opening
11699 topology changed: Unknown -> ReplicaSetNoPrimary
11700 secondary UNAVAILABLE
11701 primary UNAVAILABLE
11702 server opening: localhost:27017
11703 server opening: localhost:27018
11704 localhost:27017 heartbeat started
11705 localhost:27018 heartbeat started
11706 localhost:27017 heartbeat succeeded: { ... reply ... }
11707 server changed: localhost:27017 Unknown -> RSPrimary
11708 server opening: localhost:27019
11709 topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
11710 new servers:
11711 RSPrimary localhost:27017
11712 secondary UNAVAILABLE
11713 primary AVAILABLE
11714 localhost:27019 heartbeat started
11715 localhost:27018 heartbeat succeeded: { ... reply ... }
11716 server changed: localhost:27018 Unknown -> RSSecondary
11717 topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
11718 previous servers:
11719 RSPrimary localhost:27017
11720 new servers:
11721 RSPrimary localhost:27017
11722 RSSecondary localhost:27018
11723 secondary AVAILABLE
11724 primary AVAILABLE
11725 localhost:27019 heartbeat succeeded: { ... reply ... }
11726 server changed: localhost:27019 Unknown -> RSSecondary
11727 topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
11728 previous servers:
11729 RSPrimary localhost:27017
11730 RSSecondary localhost:27018
11731 new servers:
11732 RSPrimary localhost:27017
11733 RSSecondary localhost:27018
11734 RSSecondary localhost:27019
11735 secondary AVAILABLE
11736 primary AVAILABLE
11737 topology closed
11738
11739 Events:
11740 server changed: 3
11741 server opening: 3
11742 server closed: 0
11743 topology changed: 4
11744 topology opening: 1
11745 topology closed: 1
11746 heartbeat started: 3
11747 heartbeat succeeded: 3
11748 heartbeat failed: 0
11749
11750 The driver connects to the mongods on ports 27017 and 27018, which were
11751 specified in the URI, and determines which is primary. It also discov‐
11752 ers the third member, "localhost:27019", and adds it to the topology.
11753
11754 • Index
11755
11757 MongoDB, Inc
11758
11760 2017-present, MongoDB, Inc
11761
11762
11763
11764
117651.25.1 Nov 08, 2023 MONGOC_REFERENCE(3)