1MONGOC_GUIDES(3) libmongoc MONGOC_GUIDES(3)
2
3
4
6 mongoc_guides - Guides
7
9 Configuration with URI options
10 Enable TLS by including tls=true in the URI.
11
12 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/");
13 mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
14
15 mongoc_client_t *client = mongoc_client_new_from_uri (uri);
16
17 The following URI options may be used to further configure TLS:
18
19 ┌────────────────────┬─────────────────────┬─────────────────────┐
20 │Constant │ Key │ Description │
21 ├────────────────────┼─────────────────────┼─────────────────────┤
22 │MONGOC_URI_TLS │ tls │ {true|false}, indi‐ │
23 │ │ │ cating if TLS must │
24 │ │ │ be used. │
25 ├────────────────────┼─────────────────────┼─────────────────────┤
26 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ Path to PEM format‐ │
27 │TIFICATEKEYFILE │ file │ ted Private Key, │
28 │ │ │ with its Public │
29 │ │ │ Certificate con‐ │
30 │ │ │ catenated at the │
31 │ │ │ end. │
32 ├────────────────────┼─────────────────────┼─────────────────────┤
33 │MONGOC_URI_TLSCER‐ │ tlscertificatekey‐ │ The password, if │
34 │TIFICATEKEY‐ │ password │ any, to use to un‐ │
35 │FILEPASSWORD │ │ lock encrypted Pri‐ │
36 │ │ │ vate Key. │
37 ├────────────────────┼─────────────────────┼─────────────────────┤
38 │MON‐ │ tlscafile │ One, or a bundle │
39 │GOC_URI_TLSCAFILE │ │ of, Certificate Au‐ │
40 │ │ │ thorities whom │
41 │ │ │ should be consid‐ │
42 │ │ │ ered to be trusted. │
43 ├────────────────────┼─────────────────────┼─────────────────────┤
44 │MONGOC_URI_TLSAL‐ │ tlsallowinvalidcer‐ │ Accept and ignore │
45 │LOWINVALIDCERTIFI‐ │ tificates │ certificate verifi‐ │
46 │CATES │ │ cation errors (e.g. │
47 │ │ │ untrusted issuer, │
48 │ │ │ expired, etc.) │
49 ├────────────────────┼─────────────────────┼─────────────────────┤
50 │MONGOC_URI_TLSAL‐ │ tlsallowinvalid‐ │ Ignore hostname │
51 │LOWINVALIDHOSTNAMES │ hostnames │ verification of the │
52 │ │ │ certificate (e.g. │
53 │ │ │ Man In The Middle, │
54 │ │ │ using valid cer‐ │
55 │ │ │ tificate, but is‐ │
56 │ │ │ sued for another │
57 │ │ │ hostname) │
58 └────────────────────┴─────────────────────┴─────────────────────┘
59
60
61
62
63
64
65
66
67 │MONGOC_URI_TLSINSE‐ │ tlsinsecure │ {true|false}, indi‐ │
68 │CURE │ │ cating if insecure │
69 │ │ │ TLS options should │
70 │ │ │ be used. Currently │
71 │ │ │ this implies MON‐ │
72 │ │ │ GOC_URI_TLSALLOWIN‐ │
73 │ │ │ VALIDCERTIFICATES │
74 │ │ │ and MONGOC_URI_TL‐ │
75 │ │ │ SALLOWINVALIDHOST‐ │
76 │ │ │ NAMES. │
77 ├────────────────────┼─────────────────────┼─────────────────────┤
78 │MONGOC_URI_TLSDIS‐ │ tlsdisablecertifi‐ │ {true|false}, indi‐ │
79 │ABLECERTIFICATERE‐ │ caterevocationcheck │ cates if revocation │
80 │VOCATIONCHECK │ │ checking (CRL / │
81 │ │ │ OCSP) should be │
82 │ │ │ disabled. │
83 ├────────────────────┼─────────────────────┼─────────────────────┤
84 │MONGOC_URI_TLSDIS‐ │ tlsdisableocspend‐ │ {true|false}, indi‐ │
85 │ABLEOCSPEND‐ │ pointcheck │ cates if OCSP re‐ │
86 │POINTCHECK │ │ sponder endpoints │
87 │ │ │ should not be re‐ │
88 │ │ │ quested when an │
89 │ │ │ OCSP response is │
90 │ │ │ not stapled. │
91 └────────────────────┴─────────────────────┴─────────────────────┘
92
93 Configuration with mongoc_ssl_opt_t
94 Alternatively, the mongoc_ssl_opt_t struct may be used to configure TLS
95 with mongoc_client_set_ssl_opts() or mongoc_client_pool_set_ssl_opts().
96 Most of the configurable options can be set using the Connection String
97 URI.
98
99 ┌───────────────────────┬──────────────────────────┐
100 │mongoc_ssl_opt_t key │ URI key │
101 ├───────────────────────┼──────────────────────────┤
102 │pem_file │ tlsClientCertificateKey‐ │
103 │ │ File │
104 ├───────────────────────┼──────────────────────────┤
105 │pem_pwd │ tlsClientCertificateKey‐ │
106 │ │ Password │
107 ├───────────────────────┼──────────────────────────┤
108 │ca_file │ tlsCAFile │
109 ├───────────────────────┼──────────────────────────┤
110 │weak_cert_validation │ tlsAllowInvalidCertifi‐ │
111 │ │ cates │
112 ├───────────────────────┼──────────────────────────┤
113 │allow_invalid_hostname │ tlsAllowInvalidHostnames │
114 └───────────────────────┴──────────────────────────┘
115
116 The only exclusions are crl_file and ca_dir. Those may only be set with
117 mongoc_ssl_opt_t.
118
119 Client Authentication
120 When MongoDB is started with TLS enabled, it will by default require
121 the client to provide a client certificate issued by a certificate au‐
122 thority specified by --tlsCAFile, or an authority trusted by the native
123 certificate store in use on the server.
124
125 To provide the client certificate, set the tlsCertificateKeyFile in the
126 URI to a PEM armored certificate file.
127
128 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/");
129 mongoc_uri_set_option_as_bool (uri, MONGOC_URI_TLS, true);
130 mongoc_uri_set_option_as_utf8 (uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, "/path/to/client-certificate.pem");
131
132 mongoc_client_t *client = mongoc_client_new_from_uri (uri);
133
134 Server Certificate Verification
135 The MongoDB C Driver will automatically verify the validity of the
136 server certificate, such as issued by configured Certificate Authority,
137 hostname validation, and expiration.
138
139 To overwrite this behavior, it is possible to disable hostname valida‐
140 tion, OCSP endpoint revocation checking, revocation checking entirely,
141 and allow invalid certificates.
142
143 This behavior is controlled using the tlsAllowInvalidHostnames, tlsDis‐
144 ableOCSPEndpointCheck, tlsDisableCertificateRevocationCheck, and tlsAl‐
145 lowInvalidCertificates options respectively. By default, all are set to
146 false.
147
148 It is not recommended to change these defaults as it exposes the client
149 to Man In The Middle attacks (when tlsAllowInvalidHostnames is set),
150 invalid certificates (when tlsAllowInvalidCertificates is set), or po‐
151 tentially revoked certificates (when tlsDisableOCSPEndpointCheck or
152 tlsDisableCertificateRevocationCheck are set).
153
154 Supported Libraries
155 By default, libmongoc will attempt to find a supported TLS library and
156 enable TLS support. This is controlled by the cmake flag ENABLE_SSL,
157 which is set to AUTO by default. Valid values are:
158
159 • AUTO the default behavior. Link to the system's native TLS library,
160 or attempt to find OpenSSL.
161
162 • DARWIN link to Secure Transport, the native TLS library on macOS.
163
164 • WINDOWS link to Secure Channel, the native TLS library on Windows.
165
166 • OPENSSL link to OpenSSL (libssl). An optional install path may be
167 specified with OPENSSL_ROOT.
168
169 • LIBRESSL link to LibreSSL's libtls. (LibreSSL's compatible libssl may
170 be linked to by setting OPENSSL).
171
172 • OFF disable TLS support.
173
174 OpenSSL
175 The MongoDB C Driver uses OpenSSL, if available, on Linux and Unix
176 platforms (besides macOS). Industry best practices and some regulations
177 require the use of TLS 1.1 or newer, which requires at least OpenSSL
178 1.0.1. Check your OpenSSL version like so:
179
180 $ openssl version
181
182 Ensure your system's OpenSSL is a recent version (at least 1.0.1), or
183 install a recent version in a non-system path and build against it
184 with:
185
186 cmake -DOPENSSL_ROOT_DIR=/absolute/path/to/openssl
187
188 When compiled against OpenSSL, the driver will attempt to load the sys‐
189 tem default certificate store, as configured by the distribution. That
190 can be overridden by setting the tlsCAFile URI option or with the
191 fields ca_file and ca_dir in the mongoc_ssl_opt_t.
192
193 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is fully
194 supported when using OpenSSL 1.0.1+ with the following notes:
195
196 • When a crl_file is set with mongoc_ssl_opt_t, and the crl_file re‐
197 vokes the server's certificate, the certificate is considered revoked
198 (even if the certificate has a valid stapled OCSP response)
199
200 LibreSSL / libtls
201 The MongoDB C Driver supports LibreSSL through the use of OpenSSL com‐
202 patibility checks when configured to compile against openssl. It also
203 supports the new libtls library when configured to build against li‐
204 bressl.
205
206 When compiled against the Windows native libraries, the crl_file option
207 of a mongoc_ssl_opt_t is not supported, and will issue an error if
208 used.
209
210 Setting tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevoca‐
211 tionCheck has no effect.
212
213 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
214 tially supported with the following notes:
215
216 • The Must-Staple extension (see RFC 7633) is ignored. Connection may
217 continue if a Must-Staple certificate is presented with no stapled
218 response (unless the client receives a revoked response from an OCSP
219 responder).
220
221 • Connection will continue if a Must-Staple certificate is presented
222 without a stapled response and the OCSP responder is down.
223
224 Native TLS Support on Windows (Secure Channel)
225 The MongoDB C Driver supports the Windows native TLS library (Secure
226 Channel, or SChannel), and its native crypto library (Cryptography API:
227 Next Generation, or CNG).
228
229 When compiled against the Windows native libraries, the ca_dir option
230 of a mongoc_ssl_opt_t is not supported, and will issue an error if
231 used.
232
233 Encrypted PEM files (e.g., setting tlsCertificateKeyPassword) are also
234 not supported, and will result in error when attempting to load them.
235
236 When tlsCAFile is set, the driver will only allow server certificates
237 issued by the authority (or authorities) provided. When no tlsCAFile is
238 set, the driver will look up the Certificate Authority using the System
239 Local Machine Root certificate store to confirm the provided certifi‐
240 cate.
241
242 When crl_file is set with mongoc_ssl_opt_t, the driver will import the
243 revocation list to the System Local Machine Root certificate store.
244
245 Setting tlsDisableOCSPEndpointCheck has no effect.
246
247 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
248 tially supported with the following notes:
249
250 • The Must-Staple extension (see RFC 7633) is ignored. Connection may
251 continue if a Must-Staple certificate is presented with no stapled
252 response (unless the client receives a revoked response from an OCSP
253 responder).
254
255 • When a crl_file is set with mongoc_ssl_opt_t, and the crl_file re‐
256 vokes the server's certificate, the OCSP response takes precedence.
257 E.g. if the server presents a certificate with a valid stapled OCSP
258 response, the certificate is considered valid even if the crl_file
259 marks it as revoked.
260
261 • Connection will continue if a Must-Staple certificate is presented
262 without a stapled response and the OCSP responder is down.
263
264 Native TLS Support on macOS / Darwin (Secure Transport)
265 The MongoDB C Driver supports the Darwin (OS X, macOS, iOS, etc.) na‐
266 tive TLS library (Secure Transport), and its native crypto library
267 (Common Crypto, or CC).
268
269 When compiled against Secure Transport, the ca_dir and crl_file options
270 of a mongoc_ssl_opt_t are not supported. An error is issued if either
271 are used.
272
273 When tlsCAFile is set, the driver will only allow server certificates
274 issued by the authority (or authorities) provided. When no tlsCAFile is
275 set, the driver will use the Certificate Authorities in the currently
276 unlocked keychains.
277
278 Setting tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevoca‐
279 tionCheck has no effect.
280
281 The Online Certificate Status Protocol (OCSP) (see RFC 6960) is par‐
282 tially supported with the following notes.
283
284 • The Must-Staple extension (see RFC 7633) is ignored. Connection may
285 continue if a Must-Staple certificate is presented with no stapled
286 response (unless the client receives a revoked response from an OCSP
287 responder).
288
289 • Connection will continue if a Must-Staple certificate is presented
290 without a stapled response and the OCSP responder is down.
291
293 Drivers for some other languages provide helper functions to perform
294 certain common tasks. In the C Driver we must explicitly build commands
295 to send to the server.
296
297 Setup
298 First we'll write some code to insert sample data:
299
300 doc-common-insert.c
301
302 /* Don't try to compile this file on its own. It's meant to be #included
303 by example code */
304
305 /* Insert some sample data */
306 bool
307 insert_data (mongoc_collection_t *collection)
308 {
309 mongoc_bulk_operation_t *bulk;
310 enum N { ndocs = 4 };
311 bson_t *docs[ndocs];
312 bson_error_t error;
313 int i = 0;
314 bool ret;
315
316 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
317
318 docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
319 docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
320 docs[2] = BCON_NEW (
321 "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
322 docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
323
324 for (i = 0; i < ndocs; i++) {
325 mongoc_bulk_operation_insert (bulk, docs[i]);
326 bson_destroy (docs[i]);
327 docs[i] = NULL;
328 }
329
330 ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
331
332 if (!ret) {
333 fprintf (stderr, "Error inserting data: %s\n", error.message);
334 }
335
336 mongoc_bulk_operation_destroy (bulk);
337 return ret;
338 }
339
340 /* A helper which we'll use a lot later on */
341 void
342 print_res (const bson_t *reply)
343 {
344 char *str;
345 BSON_ASSERT (reply);
346 str = bson_as_canonical_extended_json (reply, NULL);
347 printf ("%s\n", str);
348 bson_free (str);
349 }
350
351
352 "explain" Command
353 This is how to use the explain command in MongoDB 3.2+:
354
355 explain.c
356
357 bool
358 explain (mongoc_collection_t *collection)
359 {
360 bson_t *command;
361 bson_t reply;
362 bson_error_t error;
363 bool res;
364
365 command = BCON_NEW ("explain",
366 "{",
367 "find",
368 BCON_UTF8 (COLLECTION_NAME),
369 "filter",
370 "{",
371 "x",
372 BCON_INT32 (1),
373 "}",
374 "}");
375 res = mongoc_collection_command_simple (
376 collection, command, NULL, &reply, &error);
377 if (!res) {
378 fprintf (stderr, "Error with explain: %s\n", error.message);
379 goto cleanup;
380 }
381
382 /* Do something with the reply */
383 print_res (&reply);
384
385 cleanup:
386 bson_destroy (&reply);
387 bson_destroy (command);
388 return res;
389 }
390
391
392 Running the Examples
393 common-operations.c
394
395 /*
396 * Copyright 2016 MongoDB, Inc.
397 *
398 * Licensed under the Apache License, Version 2.0 (the "License");
399 * you may not use this file except in compliance with the License.
400 * You may obtain a copy of the License at
401 *
402 * http://www.apache.org/licenses/LICENSE-2.0
403 *
404 * Unless required by applicable law or agreed to in writing, software
405 * distributed under the License is distributed on an "AS IS" BASIS,
406 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
407 * See the License for the specific language governing permissions and
408 * limitations under the License.
409 */
410
411
412 #include <mongoc/mongoc.h>
413 #include <stdio.h>
414
415
416 const char *COLLECTION_NAME = "things";
417
418 #include "../doc-common-insert.c"
419 #include "explain.c"
420
421
422 int
423 main (int argc, char *argv[])
424 {
425 mongoc_database_t *database = NULL;
426 mongoc_client_t *client = NULL;
427 mongoc_collection_t *collection = NULL;
428 mongoc_uri_t *uri = NULL;
429 bson_error_t error;
430 char *host_and_port;
431 int res = 0;
432
433 if (argc < 2 || argc > 3) {
434 fprintf (stderr,
435 "usage: %s MONGOD-1-CONNECTION-STRING "
436 "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
437 argv[0]);
438 fprintf (stderr,
439 "MONGOD-1-CONNECTION-STRING can be "
440 "of the following forms:\n");
441 fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
442 fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
443 fprintf (stderr,
444 "mongodb://user:pass@localhost:27017\t"
445 "local machine on port 27017, and authenticate with username "
446 "user and password pass\n");
447 return EXIT_FAILURE;
448 }
449
450 mongoc_init ();
451
452 if (strncmp (argv[1], "mongodb://", 10) == 0) {
453 host_and_port = bson_strdup (argv[1]);
454 } else {
455 host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
456 }
457
458 uri = mongoc_uri_new_with_error (host_and_port, &error);
459 if (!uri) {
460 fprintf (stderr,
461 "failed to parse URI: %s\n"
462 "error message: %s\n",
463 host_and_port,
464 error.message);
465 res = EXIT_FAILURE;
466 goto cleanup;
467 }
468
469 client = mongoc_client_new_from_uri (uri);
470 if (!client) {
471 res = EXIT_FAILURE;
472 goto cleanup;
473 }
474
475 mongoc_client_set_error_api (client, 2);
476 database = mongoc_client_get_database (client, "test");
477 collection = mongoc_database_get_collection (database, COLLECTION_NAME);
478
479 printf ("Inserting data\n");
480 if (!insert_data (collection)) {
481 res = EXIT_FAILURE;
482 goto cleanup;
483 }
484
485 printf ("explain\n");
486 if (!explain (collection)) {
487 res = EXIT_FAILURE;
488 goto cleanup;
489 }
490
491 cleanup:
492 if (collection) {
493 mongoc_collection_destroy (collection);
494 }
495
496 if (database) {
497 mongoc_database_destroy (database);
498 }
499
500 if (client) {
501 mongoc_client_destroy (client);
502 }
503
504 if (uri) {
505 mongoc_uri_destroy (uri);
506 }
507
508 bson_free (host_and_port);
509 mongoc_cleanup ();
510 return res;
511 }
512
513
514 First launch two separate instances of mongod (must be done from sepa‐
515 rate shells):
516
517 $ mongod
518
519 $ mkdir /tmp/db2
520 $ mongod --dbpath /tmp/db2 --port 27018 # second instance
521
522 Now compile and run the example program:
523
524 $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
525 Inserting data
526 explain
527 {
528 "executionStats" : {
529 "allPlansExecution" : [],
530 "executionStages" : {
531 "advanced" : 19,
532 "direction" : "forward" ,
533 "docsExamined" : 76,
534 "executionTimeMillisEstimate" : 0,
535 "filter" : {
536 "x" : {
537 "$eq" : 1
538 }
539 },
540 "invalidates" : 0,
541 "isEOF" : 1,
542 "nReturned" : 19,
543 "needTime" : 58,
544 "needYield" : 0,
545 "restoreState" : 0,
546 "saveState" : 0,
547 "stage" : "COLLSCAN" ,
548 "works" : 78
549 },
550 "executionSuccess" : true,
551 "executionTimeMillis" : 0,
552 "nReturned" : 19,
553 "totalDocsExamined" : 76,
554 "totalKeysExamined" : 0
555 },
556 "ok" : 1,
557 "queryPlanner" : {
558 "indexFilterSet" : false,
559 "namespace" : "test.things",
560 "parsedQuery" : {
561 "x" : {
562 "$eq" : 1
563 }
564 },
565 "plannerVersion" : 1,
566 "rejectedPlans" : [],
567 "winningPlan" : {
568 "direction" : "forward" ,
569 "filter" : {
570 "x" : {
571 "$eq" : 1
572 }
573 },
574 "stage" : "COLLSCAN"
575 }
576 },
577 "serverInfo" : {
578 "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
579 "host" : "MacBook-Pro-57.local",
580 "port" : 27017,
581 "version" : "3.2.6"
582 }
583 }
584
586 The following guide contains information specific to certain types of
587 MongoDB configurations.
588
589 For an example of connecting to a simple standalone server, see the
590 Tutorial. To establish a connection with authentication options en‐
591 abled, see the Authentication page.
592
593 Connecting to a Replica Set
594 Connecting to a replica set is much like connecting to a standalone
595 MongoDB server. Simply specify the replica set name using the ?repli‐
596 caSet=myreplset URI option.
597
598 #include <bson/bson.h>
599 #include <mongoc/mongoc.h>
600
601 int
602 main (int argc, char *argv[])
603 {
604 mongoc_client_t *client;
605
606 mongoc_init ();
607
608 /* Create our MongoDB Client */
609 client = mongoc_client_new (
610 "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");
611
612 /* Do some work */
613 /* TODO */
614
615 /* Clean up */
616 mongoc_client_destroy (client);
617 mongoc_cleanup ();
618
619 return 0;
620 }
621
622 TIP:
623 Multiple hostnames can be specified in the MongoDB connection string
624 URI, with a comma separating hosts in the seed list.
625
626 It is recommended to use a seed list of members of the replica set
627 to allow the driver to connect to any node.
628
629 Connecting to a Sharded Cluster
630 To connect to a sharded cluster, specify the mongos nodes the client
631 should connect to. The C Driver will automatically detect that it has
632 connected to a mongos sharding server.
633
634 If more than one hostname is specified, a seed list will be created to
635 attempt failover between the mongos instances.
636
637 WARNING:
638 Specifying the replicaSet parameter when connecting to a mongos
639 sharding server is invalid.
640
641 #include <bson/bson.h>
642 #include <mongoc/mongoc.h>
643
644 int
645 main (int argc, char *argv[])
646 {
647 mongoc_client_t *client;
648
649 mongoc_init ();
650
651 /* Create our MongoDB Client */
652 client = mongoc_client_new ("mongodb://myshard01:27017/");
653
654 /* Do something with client ... */
655
656 /* Free the client */
657 mongoc_client_destroy (client);
658
659 mongoc_cleanup ();
660
661 return 0;
662 }
663
664 Connecting to an IPv6 Address
665 The MongoDB C Driver will automatically resolve IPv6 addresses from
666 host names. However, to specify an IPv6 address directly, wrap the ad‐
667 dress in [].
668
669 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");
670
671 Connecting with IPv4 and IPv6
672 If connecting to a hostname that has both IPv4 and IPv6 DNS records,
673 the behavior follows RFC-6555. A connection to the IPv6 address is at‐
674 tempted first. If IPv6 fails, then a connection is attempted to the
675 IPv4 address. If the connection attempt to IPv6 does not complete
676 within 250ms, then IPv4 is tried in parallel. Whichever succeeds con‐
677 nection first cancels the other. The successful DNS result is cached
678 for 10 minutes.
679
680 As a consequence, attempts to connect to a mongod only listening on
681 IPv4 may be delayed if there are both A (IPv4) and AAAA (IPv6) DNS
682 records associated with the host.
683
684 To avoid a delay, configure hostnames to match the MongoDB configura‐
685 tion. That is, only create an A record if the mongod is only listening
686 on IPv4.
687
688 Connecting to a UNIX Domain Socket
689 On UNIX-like systems, the C Driver can connect directly to a MongoDB
690 server using a UNIX domain socket. Pass the URL-encoded path to the
691 socket, which must be suffixed with .sock. For example, to connect to a
692 domain socket at /tmp/mongodb-27017.sock:
693
694 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");
695
696 Include username and password like so:
697
698 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");
699
700 Connecting to a server over TLS
701 These are instructions for configuring TLS/SSL connections.
702
703 To run a server locally (on port 27017, for example):
704
705 $ mongod --port 27017 --tlsMode requireTLS --tlsCertificateKeyFile server.pem --tlsCAFile ca.pem
706
707 Add /?tls=true to the end of a client URI.
708
709 mongoc_client_t *client = NULL;
710 client = mongoc_client_new ("mongodb://localhost:27017/?tls=true");
711
712 MongoDB requires client certificates by default, unless the --tlsAllow‐
713 ConnectionsWithoutCertificates is provided. The C Driver can be config‐
714 ured to present a client certificate using the URI option tlsCertifi‐
715 cateKeyFile, which may be referenced through the constant MON‐
716 GOC_URI_TLSCERTIFICATEKEYFILE.
717
718 mongoc_client_t *client = NULL;
719 mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost:27017/?tls=true");
720 mongoc_uri_set_option_as_utf8 (uri, MONGOC_URI_TLSCERTIFICATEKEYFILE, "client.pem");
721
722 client = mongoc_client_new_from_uri (uri);
723
724 The client certificate provided by tlsCertificateKeyFile must be issued
725 by one of the server trusted Certificate Authorities listed in
726 --tlsCAFile, or issued by a CA in the native certificate store on the
727 server when omitted.
728
729 See Configuring TLS for more information on the various TLS related op‐
730 tions.
731
732 Compressing data to and from MongoDB
733 MongoDB 3.4 added Snappy compression support, zlib compression in 3.6,
734 and zstd compression in 4.2. To enable compression support the client
735 must be configured with which compressors to use:
736
737 mongoc_client_t *client = NULL;
738 client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib,zstd");
739
740 The compressors option specifies the priority order of compressors the
741 client wants to use. Messages are compressed if the client and server
742 share any compressors in common.
743
744 Note that the compressor used by the server might not be the same com‐
745 pressor as the client used. For example, if the client uses the con‐
746 nection string compressors=zlib,snappy the client will use zlib com‐
747 pression to send data (if possible), but the server might still reply
748 using snappy, depending on how the server was configured.
749
750 The driver must be built with zlib and/or snappy and/or zstd support to
751 enable compression support, any unknown (or not compiled in) compressor
752 value will be ignored. Note: to build with zstd requires cmake 3.12 or
753 higher.
754
755 Additional Connection Options
756 The full list of connection options can be found in the mongoc_uri_t
757 docs.
758
759 Certain socket/connection related options are not configurable:
760
761 ┌──────────────┬─────────────────────┬─────────────────────┐
762 │Option │ Description │ Value │
763 ├──────────────┼─────────────────────┼─────────────────────┤
764 │SO_KEEPALIVE │ TCP Keep Alive │ Enabled │
765 ├──────────────┼─────────────────────┼─────────────────────┤
766 │TCP_KEEPIDLE │ How long a connec‐ │ 120 seconds │
767 │ │ tion needs to re‐ │ │
768 │ │ main idle before │ │
769 │ │ TCP starts sending │ │
770 │ │ keepalive probes │ │
771 ├──────────────┼─────────────────────┼─────────────────────┤
772 │TCP_KEEPINTVL │ The time in seconds │ 10 seconds │
773 │ │ between TCP probes │ │
774 ├──────────────┼─────────────────────┼─────────────────────┤
775 │TCP_KEEPCNT │ How many probes to │ 9 probes │
776 │ │ send, without ac‐ │ │
777 │ │ knowledgement, be‐ │ │
778 │ │ fore dropping the │ │
779 │ │ connection │ │
780 ├──────────────┼─────────────────────┼─────────────────────┤
781 │TCP_NODELAY │ Send packets as │ Enabled (no buffer‐ │
782 │ │ soon as possible or │ ing) │
783 │ │ buffer small pack‐ │ │
784 │ │ ets (Nagle algo‐ │ │
785 │ │ rithm) │ │
786 └──────────────┴─────────────────────┴─────────────────────┘
787
789 The MongoDB C driver has two connection modes: single-threaded and
790 pooled. Single-threaded mode is optimized for embedding the driver
791 within languages like PHP. Multi-threaded programs should use pooled
792 mode: this mode minimizes the total connection count, and in pooled
793 mode background threads monitor the MongoDB server topology, so the
794 program need not block to scan it.
795
796 Single Mode
797 In single mode, your program creates a mongoc_client_t directly:
798
799 mongoc_client_t *client = mongoc_client_new (
800 "mongodb://hostA,hostB/?replicaSet=my_rs");
801
802 The client connects on demand when your program first uses it for a
803 MongoDB operation. Using a non-blocking socket per server, it begins a
804 check on each server concurrently, and uses the asynchronous poll or
805 select function to receive events from the sockets, until all have re‐
806 sponded or timed out. Put another way, in single-threaded mode the C
807 Driver fans out to begin all checks concurrently, then fans in once all
808 checks have completed or timed out. Once the scan completes, the client
809 executes your program's operation and returns.
810
811 In single mode, the client re-scans the server topology roughly once
812 per minute. If more than a minute has elapsed since the previous scan,
813 the next operation on the client will block while the client completes
814 its scan. This interval is configurable with heartbeatFrequencyMS in
815 the connection string. (See mongoc_uri_t.)
816
817 A single client opens one connection per server in your topology: these
818 connections are used both for scanning the topology and performing nor‐
819 mal operations.
820
821 Pooled Mode
822 To activate pooled mode, create a mongoc_client_pool_t:
823
824 mongoc_uri_t *uri = mongoc_uri_new (
825 "mongodb://hostA,hostB/?replicaSet=my_rs");
826
827 mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
828
829 When your program first calls mongoc_client_pool_pop(), the pool
830 launches monitoring threads in the background. Monitoring threads inde‐
831 pendently connect to all servers in the connection string. As monitor‐
832 ing threads receive hello responses from the servers, they update the
833 shared view of the server topology. Additional monitoring threads and
834 connections are created as new servers are discovered. Monitoring
835 threads are terminated when servers are removed from the shared view of
836 the server topology.
837
838 Each thread that executes MongoDB operations must check out a client
839 from the pool:
840
841 mongoc_client_t *client = mongoc_client_pool_pop (pool);
842
843 /* use the client for operations ... */
844
845 mongoc_client_pool_push (pool, client);
846
847 The mongoc_client_t object is not thread-safe, only the
848 mongoc_client_pool_t is.
849
850 When the driver is in pooled mode, your program's operations are un‐
851 blocked as soon as monitoring discovers a usable server. For example,
852 if a thread in your program is waiting to execute an "insert" on the
853 primary, it is unblocked as soon as the primary is discovered, rather
854 than waiting for all secondaries to be checked as well.
855
856 The pool opens one connection per server for monitoring, and each
857 client opens its own connection to each server it uses for application
858 operations. Background monitoring threads re-scan servers independently
859 roughly every 10 seconds. This interval is configurable with heartbeat‐
860 FrequencyMS in the connection string. (See mongoc_uri_t.)
861
862 The connection string can also specify waitQueueTimeoutMS to limit the
863 time that mongoc_client_pool_pop() will wait for a client from the
864 pool. (See mongoc_uri_t.) If waitQueueTimeoutMS is specified, then it
865 is necessary to confirm that a client was actually returned:
866
867 mongoc_uri_t *uri = mongoc_uri_new (
868 "mongodb://hostA,hostB/?replicaSet=my_rs&waitQueueTimeoutMS=1000");
869
870 mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
871
872 mongoc_client_t *client = mongoc_client_pool_pop (pool);
873
874 if (client) {
875 /* use the client for operations ... */
876
877 mongoc_client_pool_push (pool, client);
878 } else {
879 /* take appropriate action for a timeout */
880 }
881
882 See Connection Pool Options to configure pool size and behavior, and
883 see mongoc_client_pool_t for an extended example of a multi-threaded
884 program that uses the driver in pooled mode.
885
887 Handling Cursor Failures
888 Cursors exist on a MongoDB server. However, the mongoc_cursor_t struc‐
889 ture gives the local process a handle to the cursor. It is possible for
890 errors to occur on the server while iterating a cursor on the client.
891 Even a network partition may occur. This means that applications should
892 be robust in handling cursor failures.
893
894 While iterating cursors, you should check to see if an error has oc‐
895 curred. See the following example for how to robustly check for errors.
896
897 static void
898 print_all_documents (mongoc_collection_t *collection)
899 {
900 mongoc_cursor_t *cursor;
901 const bson_t *doc;
902 bson_error_t error;
903 bson_t query = BSON_INITIALIZER;
904 char *str;
905
906 cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
907
908 while (mongoc_cursor_next (cursor, &doc)) {
909 str = bson_as_canonical_extended_json (doc, NULL);
910 printf ("%s\n", str);
911 bson_free (str);
912 }
913
914 if (mongoc_cursor_error (cursor, &error)) {
915 fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
916 }
917
918 mongoc_cursor_destroy (cursor);
919 }
920
921 Destroying Server-Side Cursors
922 The MongoDB C driver will automatically destroy a server-side cursor
923 when mongoc_cursor_destroy() is called. Failure to call this function
924 when done with a cursor will leak memory client side as well as consume
925 extra memory server side. If the cursor was configured to never time‐
926 out, it will become a memory leak on the server.
927
928 Tailable Cursors
929 Tailable cursors are cursors that remain open even after they've re‐
930 turned a final result. This way, if more documents are added to a col‐
931 lection (i.e., to the cursor's result set), then you can continue to
932 call mongoc_cursor_next() to retrieve those additional results.
933
934 Here's a complete test case that demonstrates the use of tailable cur‐
935 sors.
936
937 NOTE:
938 Tailable cursors are for capped collections only.
939
940 An example to tail the oplog from a replica set.
941
942 mongoc-tail.c
943
944 #include <bson/bson.h>
945 #include <mongoc/mongoc.h>
946 #include <stdio.h>
947 #include <stdlib.h>
948
949 #ifdef _WIN32
950 #define sleep(_n) Sleep ((_n) *1000)
951 #endif
952
953
954 static void
955 print_bson (const bson_t *b)
956 {
957 char *str;
958
959 str = bson_as_canonical_extended_json (b, NULL);
960 fprintf (stdout, "%s\n", str);
961 bson_free (str);
962 }
963
964
965 static mongoc_cursor_t *
966 query_collection (mongoc_collection_t *collection, uint32_t last_time)
967 {
968 mongoc_cursor_t *cursor;
969 bson_t query;
970 bson_t gt;
971 bson_t opts;
972
973 BSON_ASSERT (collection);
974
975 bson_init (&query);
976 BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", >);
977 BSON_APPEND_TIMESTAMP (>, "$gt", last_time, 0);
978 bson_append_document_end (&query, >);
979
980 bson_init (&opts);
981 BSON_APPEND_BOOL (&opts, "tailable", true);
982 BSON_APPEND_BOOL (&opts, "awaitData", true);
983
984 cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
985
986 bson_destroy (&query);
987 bson_destroy (&opts);
988
989 return cursor;
990 }
991
992
993 static void
994 tail_collection (mongoc_collection_t *collection)
995 {
996 mongoc_cursor_t *cursor;
997 uint32_t last_time;
998 const bson_t *doc;
999 bson_error_t error;
1000 bson_iter_t iter;
1001
1002 BSON_ASSERT (collection);
1003
1004 last_time = (uint32_t) time (NULL);
1005
1006 while (true) {
1007 cursor = query_collection (collection, last_time);
1008 while (!mongoc_cursor_error (cursor, &error) &&
1009 mongoc_cursor_more (cursor)) {
1010 if (mongoc_cursor_next (cursor, &doc)) {
1011 if (bson_iter_init_find (&iter, doc, "ts") &&
1012 BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
1013 bson_iter_timestamp (&iter, &last_time, NULL);
1014 }
1015 print_bson (doc);
1016 }
1017 }
1018 if (mongoc_cursor_error (cursor, &error)) {
1019 if (error.domain == MONGOC_ERROR_SERVER) {
1020 fprintf (stderr, "%s\n", error.message);
1021 exit (1);
1022 }
1023 }
1024
1025 mongoc_cursor_destroy (cursor);
1026 sleep (1);
1027 }
1028 }
1029
1030
1031 int
1032 main (int argc, char *argv[])
1033 {
1034 mongoc_collection_t *collection;
1035 mongoc_client_t *client;
1036 mongoc_uri_t *uri;
1037 bson_error_t error;
1038
1039 if (argc != 2) {
1040 fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
1041 return EXIT_FAILURE;
1042 }
1043
1044 mongoc_init ();
1045
1046 uri = mongoc_uri_new_with_error (argv[1], &error);
1047 if (!uri) {
1048 fprintf (stderr,
1049 "failed to parse URI: %s\n"
1050 "error message: %s\n",
1051 argv[1],
1052 error.message);
1053 return EXIT_FAILURE;
1054 }
1055
1056 client = mongoc_client_new_from_uri (uri);
1057 if (!client) {
1058 return EXIT_FAILURE;
1059 }
1060
1061 mongoc_client_set_error_api (client, 2);
1062
1063 collection = mongoc_client_get_collection (client, "local", "oplog.rs");
1064
1065 tail_collection (collection);
1066
1067 mongoc_collection_destroy (collection);
1068 mongoc_uri_destroy (uri);
1069 mongoc_client_destroy (client);
1070
1071 return EXIT_SUCCESS;
1072 }
1073
1074
1075 Let's compile and run this example against a replica set to see updates
1076 as they are made.
1077
1078 $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
1079 $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
1080 {
1081 "h" : -8458503739429355503,
1082 "ns" : "test.test",
1083 "o" : {
1084 "_id" : {
1085 "$oid" : "5372ab0a25164be923d10d50"
1086 }
1087 },
1088 "op" : "i",
1089 "ts" : {
1090 "$timestamp" : {
1091 "i" : 1,
1092 "t" : 1400023818
1093 }
1094 },
1095 "v" : 2
1096 }
1097
1098 The line of output is a sample from performing db.test.insert({}) from
1099 the mongo shell on the replica set.
1100
1101 SEE ALSO:
1102 mongoc_cursor_set_max_await_time_ms().
1103
1104
1106 This tutorial explains how to take advantage of MongoDB C driver bulk
1107 write operation features. Executing write operations in batches reduces
1108 the number of network round trips, increasing write throughput.
1109
1110 Bulk Insert
1111 First we need to fetch a bulk operation handle from the
1112 mongoc_collection_t.
1113
1114 mongoc_bulk_operation_t *bulk =
1115 mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1116
1117 We can now start inserting documents to the bulk operation. These will
1118 be buffered until we execute the operation.
1119
1120 The bulk operation will coalesce insertions as a single batch for each
1121 consecutive call to mongoc_bulk_operation_insert(). This creates a
1122 pipelined effect when possible.
1123
1124 To execute the bulk operation and receive the result we call
1125 mongoc_bulk_operation_execute().
1126
1127 bulk1.c
1128
1129 #include <assert.h>
1130 #include <mongoc/mongoc.h>
1131 #include <stdio.h>
1132
1133 static void
1134 bulk1 (mongoc_collection_t *collection)
1135 {
1136 mongoc_bulk_operation_t *bulk;
1137 bson_error_t error;
1138 bson_t *doc;
1139 bson_t reply;
1140 char *str;
1141 bool ret;
1142 int i;
1143
1144 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1145
1146 for (i = 0; i < 10000; i++) {
1147 doc = BCON_NEW ("i", BCON_INT32 (i));
1148 mongoc_bulk_operation_insert (bulk, doc);
1149 bson_destroy (doc);
1150 }
1151
1152 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1153
1154 str = bson_as_canonical_extended_json (&reply, NULL);
1155 printf ("%s\n", str);
1156 bson_free (str);
1157
1158 if (!ret) {
1159 fprintf (stderr, "Error: %s\n", error.message);
1160 }
1161
1162 bson_destroy (&reply);
1163 mongoc_bulk_operation_destroy (bulk);
1164 }
1165
1166 int
1167 main (void)
1168 {
1169 mongoc_client_t *client;
1170 mongoc_collection_t *collection;
1171 const char *uri_string = "mongodb://localhost/?appname=bulk1-example";
1172 mongoc_uri_t *uri;
1173 bson_error_t error;
1174
1175 mongoc_init ();
1176
1177 uri = mongoc_uri_new_with_error (uri_string, &error);
1178 if (!uri) {
1179 fprintf (stderr,
1180 "failed to parse URI: %s\n"
1181 "error message: %s\n",
1182 uri_string,
1183 error.message);
1184 return EXIT_FAILURE;
1185 }
1186
1187 client = mongoc_client_new_from_uri (uri);
1188 if (!client) {
1189 return EXIT_FAILURE;
1190 }
1191
1192 mongoc_client_set_error_api (client, 2);
1193 collection = mongoc_client_get_collection (client, "test", "test");
1194
1195 bulk1 (collection);
1196
1197 mongoc_uri_destroy (uri);
1198 mongoc_collection_destroy (collection);
1199 mongoc_client_destroy (client);
1200
1201 mongoc_cleanup ();
1202
1203 return EXIT_SUCCESS;
1204 }
1205
1206
1207 Example reply document:
1208
1209 {"nInserted" : 10000,
1210 "nMatched" : 0,
1211 "nModified" : 0,
1212 "nRemoved" : 0,
1213 "nUpserted" : 0,
1214 "writeErrors" : []
1215 "writeConcernErrors" : [] }
1216
1217 Mixed Bulk Write Operations
1218 MongoDB C driver also supports executing mixed bulk write operations. A
1219 batch of insert, update, and remove operations can be executed together
1220 using the bulk write operations API.
1221
1222 Ordered Bulk Write Operations
1223 Ordered bulk write operations are batched and sent to the server in the
1224 order provided for serial execution. The reply document describes the
1225 type and count of operations performed.
1226
1227 bulk2.c
1228
1229 #include <assert.h>
1230 #include <mongoc/mongoc.h>
1231 #include <stdio.h>
1232
1233 static void
1234 bulk2 (mongoc_collection_t *collection)
1235 {
1236 mongoc_bulk_operation_t *bulk;
1237 bson_error_t error;
1238 bson_t *query;
1239 bson_t *doc;
1240 bson_t *opts;
1241 bson_t reply;
1242 char *str;
1243 bool ret;
1244 int i;
1245
1246 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1247
1248 /* Remove everything */
1249 query = bson_new ();
1250 mongoc_bulk_operation_remove (bulk, query);
1251 bson_destroy (query);
1252
1253 /* Add a few documents */
1254 for (i = 1; i < 4; i++) {
1255 doc = BCON_NEW ("_id", BCON_INT32 (i));
1256 mongoc_bulk_operation_insert (bulk, doc);
1257 bson_destroy (doc);
1258 }
1259
1260 /* {_id: 1} => {$set: {foo: "bar"}} */
1261 query = BCON_NEW ("_id", BCON_INT32 (1));
1262 doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
1263 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
1264 bson_destroy (query);
1265 bson_destroy (doc);
1266
1267 /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
1268 opts = BCON_NEW ("upsert", BCON_BOOL (true));
1269 query = BCON_NEW ("_id", BCON_INT32 (4));
1270 doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
1271 mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
1272 bson_destroy (query);
1273 bson_destroy (doc);
1274 bson_destroy (opts);
1275
1276 /* replace {j:1} with {j:2} */
1277 query = BCON_NEW ("j", BCON_INT32 (1));
1278 doc = BCON_NEW ("j", BCON_INT32 (2));
1279 mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
1280 bson_destroy (query);
1281 bson_destroy (doc);
1282
1283 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1284
1285 str = bson_as_canonical_extended_json (&reply, NULL);
1286 printf ("%s\n", str);
1287 bson_free (str);
1288
1289 if (!ret) {
1290 printf ("Error: %s\n", error.message);
1291 }
1292
1293 bson_destroy (&reply);
1294 mongoc_bulk_operation_destroy (bulk);
1295 }
1296
1297 int
1298 main (void)
1299 {
1300 mongoc_client_t *client;
1301 mongoc_collection_t *collection;
1302 const char *uri_string = "mongodb://localhost/?appname=bulk2-example";
1303 mongoc_uri_t *uri;
1304 bson_error_t error;
1305
1306 mongoc_init ();
1307
1308 uri = mongoc_uri_new_with_error (uri_string, &error);
1309 if (!uri) {
1310 fprintf (stderr,
1311 "failed to parse URI: %s\n"
1312 "error message: %s\n",
1313 uri_string,
1314 error.message);
1315 return EXIT_FAILURE;
1316 }
1317
1318 client = mongoc_client_new_from_uri (uri);
1319 if (!client) {
1320 return EXIT_FAILURE;
1321 }
1322
1323 mongoc_client_set_error_api (client, 2);
1324 collection = mongoc_client_get_collection (client, "test", "test");
1325
1326 bulk2 (collection);
1327
1328 mongoc_uri_destroy (uri);
1329 mongoc_collection_destroy (collection);
1330 mongoc_client_destroy (client);
1331
1332 mongoc_cleanup ();
1333
1334 return EXIT_SUCCESS;
1335 }
1336
1337
1338 Example reply document:
1339
1340 { "nInserted" : 3,
1341 "nMatched" : 2,
1342 "nModified" : 2,
1343 "nRemoved" : 10000,
1344 "nUpserted" : 1,
1345 "upserted" : [{"index" : 5, "_id" : 4}],
1346 "writeErrors" : []
1347 "writeConcernErrors" : [] }
1348
1349 The index field in the upserted array is the 0-based index of the up‐
1350 sert operation; in this example, the sixth operation of the overall
1351 bulk operation was an upsert, so its index is 5.
1352
1353 Unordered Bulk Write Operations
1354 Unordered bulk write operations are batched and sent to the server in
1355 arbitrary order where they may be executed in parallel. Any errors that
1356 occur are reported after all operations are attempted.
1357
1358 In the next example the first and third operations fail due to the
1359 unique constraint on _id. Since we are doing unordered execution the
1360 second and fourth operations succeed.
1361
1362 bulk3.c
1363
1364 #include <assert.h>
1365 #include <mongoc/mongoc.h>
1366 #include <stdio.h>
1367
1368 static void
1369 bulk3 (mongoc_collection_t *collection)
1370 {
1371 bson_t opts = BSON_INITIALIZER;
1372 mongoc_bulk_operation_t *bulk;
1373 bson_error_t error;
1374 bson_t *query;
1375 bson_t *doc;
1376 bson_t reply;
1377 char *str;
1378 bool ret;
1379
1380 /* false indicates unordered */
1381 BSON_APPEND_BOOL (&opts, "ordered", false);
1382 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
1383 bson_destroy (&opts);
1384
1385 /* Add a document */
1386 doc = BCON_NEW ("_id", BCON_INT32 (1));
1387 mongoc_bulk_operation_insert (bulk, doc);
1388 bson_destroy (doc);
1389
1390 /* remove {_id: 2} */
1391 query = BCON_NEW ("_id", BCON_INT32 (2));
1392 mongoc_bulk_operation_remove_one (bulk, query);
1393 bson_destroy (query);
1394
1395 /* insert {_id: 3} */
1396 doc = BCON_NEW ("_id", BCON_INT32 (3));
1397 mongoc_bulk_operation_insert (bulk, doc);
1398 bson_destroy (doc);
1399
1400 /* replace {_id:4} {'i': 1} */
1401 query = BCON_NEW ("_id", BCON_INT32 (4));
1402 doc = BCON_NEW ("i", BCON_INT32 (1));
1403 mongoc_bulk_operation_replace_one (bulk, query, doc, false);
1404 bson_destroy (query);
1405 bson_destroy (doc);
1406
1407 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1408
1409 str = bson_as_canonical_extended_json (&reply, NULL);
1410 printf ("%s\n", str);
1411 bson_free (str);
1412
1413 if (!ret) {
1414 printf ("Error: %s\n", error.message);
1415 }
1416
1417 bson_destroy (&reply);
1418 mongoc_bulk_operation_destroy (bulk);
1419 bson_destroy (&opts);
1420 }
1421
1422 int
1423 main (void)
1424 {
1425 mongoc_client_t *client;
1426 mongoc_collection_t *collection;
1427 const char *uri_string = "mongodb://localhost/?appname=bulk3-example";
1428 mongoc_uri_t *uri;
1429 bson_error_t error;
1430
1431 mongoc_init ();
1432
1433 uri = mongoc_uri_new_with_error (uri_string, &error);
1434 if (!uri) {
1435 fprintf (stderr,
1436 "failed to parse URI: %s\n"
1437 "error message: %s\n",
1438 uri_string,
1439 error.message);
1440 return EXIT_FAILURE;
1441 }
1442
1443 client = mongoc_client_new_from_uri (uri);
1444 if (!client) {
1445 return EXIT_FAILURE;
1446 }
1447
1448 mongoc_client_set_error_api (client, 2);
1449 collection = mongoc_client_get_collection (client, "test", "test");
1450
1451 bulk3 (collection);
1452
1453 mongoc_uri_destroy (uri);
1454 mongoc_collection_destroy (collection);
1455 mongoc_client_destroy (client);
1456
1457 mongoc_cleanup ();
1458
1459 return EXIT_SUCCESS;
1460 }
1461
1462
1463 Example reply document:
1464
1465 { "nInserted" : 0,
1466 "nMatched" : 1,
1467 "nModified" : 1,
1468 "nRemoved" : 1,
1469 "nUpserted" : 0,
1470 "writeErrors" : [
1471 { "index" : 0,
1472 "code" : 11000,
1473 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
1474 { "index" : 2,
1475 "code" : 11000,
1476 "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
1477 "writeConcernErrors" : [] }
1478
1479 Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }
1480
1481 The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.
1482
1483 Bulk Operation Bypassing Document Validation
1484 This feature is only available when using MongoDB 3.2 and later.
1485
1486 By default bulk operations are validated against the schema, if any is
1487 defined. In certain cases however it may be necessary to bypass the
1488 document validation.
1489
1490 bulk5.c
1491
1492 #include <assert.h>
1493 #include <mongoc/mongoc.h>
1494 #include <stdio.h>
1495
1496 static void
1497 bulk5_fail (mongoc_collection_t *collection)
1498 {
1499 mongoc_bulk_operation_t *bulk;
1500 bson_error_t error;
1501 bson_t *doc;
1502 bson_t reply;
1503 char *str;
1504 bool ret;
1505
1506 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1507
1508 /* Two inserts */
1509 doc = BCON_NEW ("_id", BCON_INT32 (31));
1510 mongoc_bulk_operation_insert (bulk, doc);
1511 bson_destroy (doc);
1512
1513 doc = BCON_NEW ("_id", BCON_INT32 (32));
1514 mongoc_bulk_operation_insert (bulk, doc);
1515 bson_destroy (doc);
1516
1517 /* The above documents do not comply to the schema validation rules
1518 * we created previously, so this will result in an error */
1519 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1520
1521 str = bson_as_canonical_extended_json (&reply, NULL);
1522 printf ("%s\n", str);
1523 bson_free (str);
1524
1525 if (!ret) {
1526 printf ("Error: %s\n", error.message);
1527 }
1528
1529 bson_destroy (&reply);
1530 mongoc_bulk_operation_destroy (bulk);
1531 }
1532
1533 static void
1534 bulk5_success (mongoc_collection_t *collection)
1535 {
1536 mongoc_bulk_operation_t *bulk;
1537 bson_error_t error;
1538 bson_t *doc;
1539 bson_t reply;
1540 char *str;
1541 bool ret;
1542
1543 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1544
1545 /* Allow this document to bypass document validation.
1546 * NOTE: When authentication is enabled, the authenticated user must have
1547 * either the "dbadmin" or "restore" roles to bypass document validation */
1548 mongoc_bulk_operation_set_bypass_document_validation (bulk, true);
1549
1550 /* Two inserts */
1551 doc = BCON_NEW ("_id", BCON_INT32 (31));
1552 mongoc_bulk_operation_insert (bulk, doc);
1553 bson_destroy (doc);
1554
1555 doc = BCON_NEW ("_id", BCON_INT32 (32));
1556 mongoc_bulk_operation_insert (bulk, doc);
1557 bson_destroy (doc);
1558
1559 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1560
1561 str = bson_as_canonical_extended_json (&reply, NULL);
1562 printf ("%s\n", str);
1563 bson_free (str);
1564
1565 if (!ret) {
1566 printf ("Error: %s\n", error.message);
1567 }
1568
1569 bson_destroy (&reply);
1570 mongoc_bulk_operation_destroy (bulk);
1571 }
1572
1573 int
1574 main (void)
1575 {
1576 bson_t *options;
1577 bson_error_t error;
1578 mongoc_client_t *client;
1579 mongoc_collection_t *collection;
1580 mongoc_database_t *database;
1581 const char *uri_string = "mongodb://localhost/?appname=bulk5-example";
1582 mongoc_uri_t *uri;
1583
1584 mongoc_init ();
1585
1586 uri = mongoc_uri_new_with_error (uri_string, &error);
1587 if (!uri) {
1588 fprintf (stderr,
1589 "failed to parse URI: %s\n"
1590 "error message: %s\n",
1591 uri_string,
1592 error.message);
1593 return EXIT_FAILURE;
1594 }
1595
1596 client = mongoc_client_new_from_uri (uri);
1597 if (!client) {
1598 return EXIT_FAILURE;
1599 }
1600
1601 mongoc_client_set_error_api (client, 2);
1602 database = mongoc_client_get_database (client, "testasdf");
1603
1604 /* Create schema validator */
1605 options = BCON_NEW (
1606 "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
1607 collection =
1608 mongoc_database_create_collection (database, "collname", options, &error);
1609
1610 if (collection) {
1611 bulk5_fail (collection);
1612 bulk5_success (collection);
1613 mongoc_collection_destroy (collection);
1614 } else {
1615 fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
1616 }
1617
1618 bson_free (options);
1619 mongoc_uri_destroy (uri);
1620 mongoc_database_destroy (database);
1621 mongoc_client_destroy (client);
1622
1623 mongoc_cleanup ();
1624
1625 return EXIT_SUCCESS;
1626 }
1627
1628
1629 Running the above example will result in:
1630
1631 { "nInserted" : 0,
1632 "nMatched" : 0,
1633 "nModified" : 0,
1634 "nRemoved" : 0,
1635 "nUpserted" : 0,
1636 "writeErrors" : [
1637 { "index" : 0,
1638 "code" : 121,
1639 "errmsg" : "Document failed validation" } ] }
1640
1641 Error: Document failed validation
1642
1643 { "nInserted" : 2,
1644 "nMatched" : 0,
1645 "nModified" : 0,
1646 "nRemoved" : 0,
1647 "nUpserted" : 0,
1648 "writeErrors" : [] }
1649
1650 The bson_error_t domain is MONGOC_ERROR_COMMAND.
1651
1652 Bulk Operation Write Concerns
1653 By default bulk operations are executed with the write_concern of the
1654 collection they are executed against. A custom write concern can be
1655 passed to the mongoc_collection_create_bulk_operation_with_opts()
1656 method. Write concern errors (e.g. wtimeout) will be reported after all
1657 operations are attempted, regardless of execution order.
1658
1659 bulk4.c
1660
1661 #include <assert.h>
1662 #include <mongoc/mongoc.h>
1663 #include <stdio.h>
1664
1665 static void
1666 bulk4 (mongoc_collection_t *collection)
1667 {
1668 bson_t opts = BSON_INITIALIZER;
1669 mongoc_write_concern_t *wc;
1670 mongoc_bulk_operation_t *bulk;
1671 bson_error_t error;
1672 bson_t *doc;
1673 bson_t reply;
1674 char *str;
1675 bool ret;
1676
1677 wc = mongoc_write_concern_new ();
1678 mongoc_write_concern_set_w (wc, 4);
1679 mongoc_write_concern_set_wtimeout_int64 (wc, 100); /* milliseconds */
1680 mongoc_write_concern_append (wc, &opts);
1681
1682 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
1683
1684 /* Two inserts */
1685 doc = BCON_NEW ("_id", BCON_INT32 (10));
1686 mongoc_bulk_operation_insert (bulk, doc);
1687 bson_destroy (doc);
1688
1689 doc = BCON_NEW ("_id", BCON_INT32 (11));
1690 mongoc_bulk_operation_insert (bulk, doc);
1691 bson_destroy (doc);
1692
1693 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1694
1695 str = bson_as_canonical_extended_json (&reply, NULL);
1696 printf ("%s\n", str);
1697 bson_free (str);
1698
1699 if (!ret) {
1700 printf ("Error: %s\n", error.message);
1701 }
1702
1703 bson_destroy (&reply);
1704 mongoc_bulk_operation_destroy (bulk);
1705 mongoc_write_concern_destroy (wc);
1706 bson_destroy (&opts);
1707 }
1708
1709 int
1710 main (void)
1711 {
1712 mongoc_client_t *client;
1713 mongoc_collection_t *collection;
1714 const char *uri_string = "mongodb://localhost/?appname=bulk4-example";
1715 mongoc_uri_t *uri;
1716 bson_error_t error;
1717
1718 mongoc_init ();
1719
1720 uri = mongoc_uri_new_with_error (uri_string, &error);
1721 if (!uri) {
1722 fprintf (stderr,
1723 "failed to parse URI: %s\n"
1724 "error message: %s\n",
1725 uri_string,
1726 error.message);
1727 return EXIT_FAILURE;
1728 }
1729
1730 client = mongoc_client_new_from_uri (uri);
1731 if (!client) {
1732 return EXIT_FAILURE;
1733 }
1734
1735 mongoc_client_set_error_api (client, 2);
1736 collection = mongoc_client_get_collection (client, "test", "test");
1737
1738 bulk4 (collection);
1739
1740 mongoc_uri_destroy (uri);
1741 mongoc_collection_destroy (collection);
1742 mongoc_client_destroy (client);
1743
1744 mongoc_cleanup ();
1745
1746 return EXIT_SUCCESS;
1747 }
1748
1749
1750 Example reply document and error message:
1751
1752 { "nInserted" : 2,
1753 "nMatched" : 0,
1754 "nModified" : 0,
1755 "nRemoved" : 0,
1756 "nUpserted" : 0,
1757 "writeErrors" : [],
1758 "writeConcernErrors" : [
1759 { "code" : 64,
1760 "errmsg" : "waiting for replication timed out" }
1761 ] }
1762
1763 Error: waiting for replication timed out
1764
1765 The bson_error_t domain is MONGOC_ERROR_WRITE_CONCERN if there are
1766 write concern errors and no write errors. Write errors indicate failed
1767 operations, so they take precedence over write concern errors, which
1768 mean merely that the write concern is not satisfied yet.
1769
1770 Setting Collation Order
1771 This feature is only available when using MongoDB 3.4 and later.
1772
1773 bulk-collation.c
1774
1775 #include <mongoc/mongoc.h>
1776 #include <stdio.h>
1777
1778 static void
1779 bulk_collation (mongoc_collection_t *collection)
1780 {
1781 mongoc_bulk_operation_t *bulk;
1782 bson_t *opts;
1783 bson_t *doc;
1784 bson_t *selector;
1785 bson_t *update;
1786 bson_error_t error;
1787 bson_t reply;
1788 char *str;
1789 uint32_t ret;
1790
1791 /* insert {_id: "one"} and {_id: "One"} */
1792 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1793 doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
1794 mongoc_bulk_operation_insert (bulk, doc);
1795 bson_destroy (doc);
1796
1797 doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
1798 mongoc_bulk_operation_insert (bulk, doc);
1799 bson_destroy (doc);
1800
1801 /* "One" normally sorts before "one"; make "one" come first */
1802 opts = BCON_NEW ("collation",
1803 "{",
1804 "locale",
1805 BCON_UTF8 ("en_US"),
1806 "caseFirst",
1807 BCON_UTF8 ("lower"),
1808 "}");
1809
1810 /* set x=1 on the document with _id "One", which now sorts after "one" */
1811 update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
1812 selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
1813 mongoc_bulk_operation_update_one_with_opts (
1814 bulk, selector, update, opts, &error);
1815
1816 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1817
1818 str = bson_as_canonical_extended_json (&reply, NULL);
1819 printf ("%s\n", str);
1820 bson_free (str);
1821
1822 if (!ret) {
1823 printf ("Error: %s\n", error.message);
1824 }
1825
1826 bson_destroy (&reply);
1827 bson_destroy (update);
1828 bson_destroy (selector);
1829 bson_destroy (opts);
1830 mongoc_bulk_operation_destroy (bulk);
1831 }
1832
1833 int
1834 main (void)
1835 {
1836 mongoc_client_t *client;
1837 mongoc_collection_t *collection;
1838 const char *uri_string = "mongodb://localhost/?appname=bulk-collation";
1839 mongoc_uri_t *uri;
1840 bson_error_t error;
1841
1842 mongoc_init ();
1843
1844 uri = mongoc_uri_new_with_error (uri_string, &error);
1845 if (!uri) {
1846 fprintf (stderr,
1847 "failed to parse URI: %s\n"
1848 "error message: %s\n",
1849 uri_string,
1850 error.message);
1851 return EXIT_FAILURE;
1852 }
1853
1854 client = mongoc_client_new_from_uri (uri);
1855 if (!client) {
1856 return EXIT_FAILURE;
1857 }
1858
1859 mongoc_client_set_error_api (client, 2);
1860 collection = mongoc_client_get_collection (client, "db", "collection");
1861 bulk_collation (collection);
1862
1863 mongoc_uri_destroy (uri);
1864 mongoc_collection_destroy (collection);
1865 mongoc_client_destroy (client);
1866
1867 mongoc_cleanup ();
1868
1869 return EXIT_SUCCESS;
1870 }
1871
1872
1873 Running the above example will result in:
1874
1875 { "nInserted" : 2,
1876 "nMatched" : 1,
1877 "nModified" : 1,
1878 "nRemoved" : 0,
1879 "nUpserted" : 0,
1880 "writeErrors" : [ ]
1881 }
1882
1883 Unacknowledged Bulk Writes
1884 Set "w" to zero for an unacknowledged write. The driver sends unac‐
1885 knowledged writes using the legacy opcodes OP_INSERT, OP_UPDATE, and
1886 OP_DELETE.
1887
1888 bulk6.c
1889
1890 #include <mongoc/mongoc.h>
1891 #include <stdio.h>
1892
1893 static void
1894 bulk6 (mongoc_collection_t *collection)
1895 {
1896 bson_t opts = BSON_INITIALIZER;
1897 mongoc_write_concern_t *wc;
1898 mongoc_bulk_operation_t *bulk;
1899 bson_error_t error;
1900 bson_t *doc;
1901 bson_t *selector;
1902 bson_t reply;
1903 char *str;
1904 bool ret;
1905
1906 wc = mongoc_write_concern_new ();
1907 mongoc_write_concern_set_w (wc, 0);
1908 mongoc_write_concern_append (wc, &opts);
1909
1910 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
1911
1912 doc = BCON_NEW ("_id", BCON_INT32 (10));
1913 mongoc_bulk_operation_insert (bulk, doc);
1914 bson_destroy (doc);
1915
1916 selector = BCON_NEW ("_id", BCON_INT32 (11));
1917 mongoc_bulk_operation_remove_one (bulk, selector);
1918 bson_destroy (selector);
1919
1920 ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1921
1922 str = bson_as_canonical_extended_json (&reply, NULL);
1923 printf ("%s\n", str);
1924 bson_free (str);
1925
1926 if (!ret) {
1927 printf ("Error: %s\n", error.message);
1928 }
1929
1930 bson_destroy (&reply);
1931 mongoc_bulk_operation_destroy (bulk);
1932 mongoc_write_concern_destroy (wc);
1933 bson_destroy (&opts);
1934 }
1935
1936 int
1937 main (void)
1938 {
1939 mongoc_client_t *client;
1940 mongoc_collection_t *collection;
1941 const char *uri_string = "mongodb://localhost/?appname=bulk6-example";
1942 mongoc_uri_t *uri;
1943 bson_error_t error;
1944
1945 mongoc_init ();
1946
1947 uri = mongoc_uri_new_with_error (uri_string, &error);
1948 if (!uri) {
1949 fprintf (stderr,
1950 "failed to parse URI: %s\n"
1951 "error message: %s\n",
1952 uri_string,
1953 error.message);
1954 return EXIT_FAILURE;
1955 }
1956
1957 client = mongoc_client_new_from_uri (uri);
1958 if (!client) {
1959 return EXIT_FAILURE;
1960 }
1961
1962 mongoc_client_set_error_api (client, 2);
1963 collection = mongoc_client_get_collection (client, "test", "test");
1964
1965 bulk6 (collection);
1966
1967 mongoc_uri_destroy (uri);
1968 mongoc_collection_destroy (collection);
1969 mongoc_client_destroy (client);
1970
1971 mongoc_cleanup ();
1972
1973 return EXIT_SUCCESS;
1974 }
1975
1976
1977 The reply document is empty:
1978
1979 { }
1980
1981 Further Reading
1982 See the Driver Bulk API Spec, which describes bulk write operations for
1983 all MongoDB drivers.
1984
1986 This document provides a number of practical examples that display the
1987 capabilities of the aggregation framework.
1988
1989 The Aggregations using the Zip Codes Data Set examples uses a publicly
1990 available data set of all zipcodes and populations in the United
1991 States. These data are available at: zips.json.
1992
1993 Requirements
1994 Let's check if everything is installed.
1995
1996 Use the following command to load zips.json data set into mongod in‐
1997 stance:
1998
1999 $ mongoimport --drop -d test -c zipcodes zips.json
2000
2001 Let's use the MongoDB shell to verify that everything was imported suc‐
2002 cessfully.
2003
2004 $ mongo test
2005 connecting to: test
2006 > db.zipcodes.count()
2007 29467
2008 > db.zipcodes.findOne()
2009 {
2010 "_id" : "35004",
2011 "city" : "ACMAR",
2012 "loc" : [
2013 -86.51557,
2014 33.584132
2015 ],
2016 "pop" : 6055,
2017 "state" : "AL"
2018 }
2019
2020 Aggregations using the Zip Codes Data Set
2021 Each document in this collection has the following form:
2022
2023 {
2024 "_id" : "35004",
2025 "city" : "Acmar",
2026 "state" : "AL",
2027 "pop" : 6055,
2028 "loc" : [-86.51557, 33.584132]
2029 }
2030
2031 In these documents:
2032
2033 • The _id field holds the zipcode as a string.
2034
2035 • The city field holds the city name.
2036
2037 • The state field holds the two letter state abbreviation.
2038
2039 • The pop field holds the population.
2040
2041 • The loc field holds the location as a [latitude, longitude] array.
2042
2043 States with Populations Over 10 Million
2044 To get all states with a population greater than 10 million, use the
2045 following aggregation pipeline:
2046
2047 aggregation1.c
2048
2049 #include <mongoc/mongoc.h>
2050 #include <stdio.h>
2051
2052 static void
2053 print_pipeline (mongoc_collection_t *collection)
2054 {
2055 mongoc_cursor_t *cursor;
2056 bson_error_t error;
2057 const bson_t *doc;
2058 bson_t *pipeline;
2059 char *str;
2060
2061 pipeline = BCON_NEW ("pipeline",
2062 "[",
2063 "{",
2064 "$group",
2065 "{",
2066 "_id",
2067 "$state",
2068 "total_pop",
2069 "{",
2070 "$sum",
2071 "$pop",
2072 "}",
2073 "}",
2074 "}",
2075 "{",
2076 "$match",
2077 "{",
2078 "total_pop",
2079 "{",
2080 "$gte",
2081 BCON_INT32 (10000000),
2082 "}",
2083 "}",
2084 "}",
2085 "]");
2086
2087 cursor = mongoc_collection_aggregate (
2088 collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
2089
2090 while (mongoc_cursor_next (cursor, &doc)) {
2091 str = bson_as_canonical_extended_json (doc, NULL);
2092 printf ("%s\n", str);
2093 bson_free (str);
2094 }
2095
2096 if (mongoc_cursor_error (cursor, &error)) {
2097 fprintf (stderr, "Cursor Failure: %s\n", error.message);
2098 }
2099
2100 mongoc_cursor_destroy (cursor);
2101 bson_destroy (pipeline);
2102 }
2103
2104 int
2105 main (void)
2106 {
2107 mongoc_client_t *client;
2108 mongoc_collection_t *collection;
2109 const char *uri_string =
2110 "mongodb://localhost:27017/?appname=aggregation-example";
2111 mongoc_uri_t *uri;
2112 bson_error_t error;
2113
2114 mongoc_init ();
2115
2116 uri = mongoc_uri_new_with_error (uri_string, &error);
2117 if (!uri) {
2118 fprintf (stderr,
2119 "failed to parse URI: %s\n"
2120 "error message: %s\n",
2121 uri_string,
2122 error.message);
2123 return EXIT_FAILURE;
2124 }
2125
2126 client = mongoc_client_new_from_uri (uri);
2127 if (!client) {
2128 return EXIT_FAILURE;
2129 }
2130
2131 mongoc_client_set_error_api (client, 2);
2132 collection = mongoc_client_get_collection (client, "test", "zipcodes");
2133
2134 print_pipeline (collection);
2135
2136 mongoc_uri_destroy (uri);
2137 mongoc_collection_destroy (collection);
2138 mongoc_client_destroy (client);
2139
2140 mongoc_cleanup ();
2141
2142 return EXIT_SUCCESS;
2143 }
2144
2145
2146 You should see a result like the following:
2147
2148 { "_id" : "PA", "total_pop" : 11881643 }
2149 { "_id" : "OH", "total_pop" : 10847115 }
2150 { "_id" : "NY", "total_pop" : 17990455 }
2151 { "_id" : "FL", "total_pop" : 12937284 }
2152 { "_id" : "TX", "total_pop" : 16986510 }
2153 { "_id" : "IL", "total_pop" : 11430472 }
2154 { "_id" : "CA", "total_pop" : 29760021 }
2155
2156 The above aggregation pipeline is build from two pipeline operators:
2157 $group and $match.
2158
2159 The $group pipeline operator requires _id field where we specify group‐
2160 ing; remaining fields specify how to generate composite value and must
2161 use one of the group aggregation functions: $addToSet, $first, $last,
2162 $max, $min, $avg, $push, $sum. The $match pipeline operator syntax is
2163 the same as the read operation query syntax.
2164
2165 The $group process reads all documents and for each state it creates a
2166 separate document, for example:
2167
2168 { "_id" : "WA", "total_pop" : 4866692 }
2169
2170 The total_pop field uses the $sum aggregation function to sum the val‐
2171 ues of all pop fields in the source documents.
2172
2173 Documents created by $group are piped to the $match pipeline operator.
2174 It returns the documents with the value of total_pop field greater than
2175 or equal to 10 million.
2176
2177 Average City Population by State
2178 To get the first three states with the greatest average population per
2179 city, use the following aggregation:
2180
2181 pipeline = BCON_NEW ("pipeline", "[",
2182 "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
2183 "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
2184 "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
2185 "{", "$limit", BCON_INT32 (3) "}",
2186 "]");
2187
2188 This aggregate pipeline produces:
2189
2190 { "_id" : "DC", "avg_city_pop" : 303450.0 }
2191 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
2192 { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
2193
2194 The above aggregation pipeline is build from three pipeline operators:
2195 $group, $sort and $limit.
2196
2197 The first $group operator creates the following documents:
2198
2199 { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
2200
2201 Note, that the $group operator can't use nested documents except the
2202 _id field.
2203
2204 The second $group uses these documents to create the following docu‐
2205 ments:
2206
2207 { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
2208
2209 These documents are sorted by the avg_city_pop field in descending or‐
2210 der. Finally, the $limit pipeline operator returns the first 3 docu‐
2211 ments from the sorted set.
2212
2214 This document provides some practical, simple, examples to demonstrate
2215 the distinct and mapReduce commands.
2216
2217 Setup
2218 First we'll write some code to insert sample data:
2219
2220 doc-common-insert.c
2221
2222 /* Don't try to compile this file on its own. It's meant to be #included
2223 by example code */
2224
2225 /* Insert some sample data */
2226 bool
2227 insert_data (mongoc_collection_t *collection)
2228 {
2229 mongoc_bulk_operation_t *bulk;
2230 enum N { ndocs = 4 };
2231 bson_t *docs[ndocs];
2232 bson_error_t error;
2233 int i = 0;
2234 bool ret;
2235
2236 bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2237
2238 docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
2239 docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
2240 docs[2] = BCON_NEW (
2241 "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
2242 docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
2243
2244 for (i = 0; i < ndocs; i++) {
2245 mongoc_bulk_operation_insert (bulk, docs[i]);
2246 bson_destroy (docs[i]);
2247 docs[i] = NULL;
2248 }
2249
2250 ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
2251
2252 if (!ret) {
2253 fprintf (stderr, "Error inserting data: %s\n", error.message);
2254 }
2255
2256 mongoc_bulk_operation_destroy (bulk);
2257 return ret;
2258 }
2259
2260 /* A helper which we'll use a lot later on */
2261 void
2262 print_res (const bson_t *reply)
2263 {
2264 char *str;
2265 BSON_ASSERT (reply);
2266 str = bson_as_canonical_extended_json (reply, NULL);
2267 printf ("%s\n", str);
2268 bson_free (str);
2269 }
2270
2271
2272 "distinct" command
2273 This is how to use the distinct command to get the distinct values of x
2274 which are greater than 1:
2275
2276 distinct.c
2277
2278 bool
2279 distinct (mongoc_database_t *database)
2280 {
2281 bson_t *command;
2282 bson_t reply;
2283 bson_error_t error;
2284 bool res;
2285 bson_iter_t iter;
2286 bson_iter_t array_iter;
2287 double val;
2288
2289 command = BCON_NEW ("distinct",
2290 BCON_UTF8 (COLLECTION_NAME),
2291 "key",
2292 BCON_UTF8 ("x"),
2293 "query",
2294 "{",
2295 "x",
2296 "{",
2297 "$gt",
2298 BCON_DOUBLE (1.0),
2299 "}",
2300 "}");
2301 res =
2302 mongoc_database_command_simple (database, command, NULL, &reply, &error);
2303 if (!res) {
2304 fprintf (stderr, "Error with distinct: %s\n", error.message);
2305 goto cleanup;
2306 }
2307
2308 /* Do something with reply (in this case iterate through the values) */
2309 if (!(bson_iter_init_find (&iter, &reply, "values") &&
2310 BSON_ITER_HOLDS_ARRAY (&iter) &&
2311 bson_iter_recurse (&iter, &array_iter))) {
2312 fprintf (stderr, "Couldn't extract \"values\" field from response\n");
2313 goto cleanup;
2314 }
2315
2316 while (bson_iter_next (&array_iter)) {
2317 if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
2318 val = bson_iter_double (&array_iter);
2319 printf ("Next double: %f\n", val);
2320 }
2321 }
2322
2323 cleanup:
2324 /* cleanup */
2325 bson_destroy (command);
2326 bson_destroy (&reply);
2327 return res;
2328 }
2329
2330
2331 "mapReduce" - basic example
2332 A simple example using the map reduce framework. It simply adds up the
2333 number of occurrences of each "tag".
2334
2335 First define the map and reduce functions:
2336
2337 constants.c
2338
2339 const char *const COLLECTION_NAME = "things";
2340
2341 /* Our map function just emits a single (key, 1) pair for each tag
2342 in the array: */
2343 const char *const MAPPER = "function () {"
2344 "this.tags.forEach(function(z) {"
2345 "emit(z, 1);"
2346 "});"
2347 "}";
2348
2349 /* The reduce function sums over all of the emitted values for a
2350 given key: */
2351 const char *const REDUCER = "function (key, values) {"
2352 "var total = 0;"
2353 "for (var i = 0; i < values.length; i++) {"
2354 "total += values[i];"
2355 "}"
2356 "return total;"
2357 "}";
2358 /* Note We can't just return values.length as the reduce function
2359 might be called iteratively on the results of other reduce
2360 steps. */
2361
2362
2363 Run the mapReduce command. Use the generic command helpers (e.g.
2364 mongoc_database_command_simple()). Do not the read command helpers
2365 (e.g. mongoc_database_read_command_with_opts()) because they are con‐
2366 sidered retryable read operations. If retryable reads are enabled,
2367 those operations will retry once on a retryable error, giving undesir‐
2368 able behavior for mapReduce.
2369
2370 map-reduce-basic.c
2371
2372 bool
2373 map_reduce_basic (mongoc_database_t *database)
2374 {
2375 bson_t reply;
2376 bson_t *command;
2377 bool res;
2378 bson_error_t error;
2379 mongoc_cursor_t *cursor;
2380 const bson_t *doc;
2381
2382 bool query_done = false;
2383
2384 const char *out_collection_name = "outCollection";
2385 mongoc_collection_t *out_collection;
2386
2387 /* Empty find query */
2388 bson_t find_query = BSON_INITIALIZER;
2389
2390 /* Construct the mapReduce command */
2391
2392 /* Other arguments can also be specified here, like "query" or
2393 "limit" and so on */
2394 command = BCON_NEW ("mapReduce",
2395 BCON_UTF8 (COLLECTION_NAME),
2396 "map",
2397 BCON_CODE (MAPPER),
2398 "reduce",
2399 BCON_CODE (REDUCER),
2400 "out",
2401 BCON_UTF8 (out_collection_name));
2402 res =
2403 mongoc_database_command_simple (database, command, NULL, &reply, &error);
2404
2405 if (!res) {
2406 fprintf (stderr, "MapReduce failed: %s\n", error.message);
2407 goto cleanup;
2408 }
2409
2410 /* Do something with the reply (it doesn't contain the mapReduce results) */
2411 print_res (&reply);
2412
2413 /* Now we'll query outCollection to see what the results are */
2414 out_collection =
2415 mongoc_database_get_collection (database, out_collection_name);
2416 cursor = mongoc_collection_find_with_opts (
2417 out_collection, &find_query, NULL, NULL);
2418 query_done = true;
2419
2420 /* Do something with the results */
2421 while (mongoc_cursor_next (cursor, &doc)) {
2422 print_res (doc);
2423 }
2424
2425 if (mongoc_cursor_error (cursor, &error)) {
2426 fprintf (stderr, "ERROR: %s\n", error.message);
2427 res = false;
2428 goto cleanup;
2429 }
2430
2431 cleanup:
2432 /* cleanup */
2433 if (query_done) {
2434 mongoc_cursor_destroy (cursor);
2435 mongoc_collection_destroy (out_collection);
2436 }
2437
2438 bson_destroy (&reply);
2439 bson_destroy (command);
2440
2441 return res;
2442 }
2443
2444
2445 "mapReduce" - more complicated example
2446 You must have replica set running for this.
2447
2448 In this example we contact a secondary in the replica set and do an
2449 "inline" map reduce, so the results are returned immediately:
2450
2451 map-reduce-advanced.c
2452
2453 bool
2454 map_reduce_advanced (mongoc_database_t *database)
2455 {
2456 bson_t *command;
2457 bson_error_t error;
2458 bool res = true;
2459 mongoc_cursor_t *cursor;
2460 mongoc_read_prefs_t *read_pref;
2461 const bson_t *doc;
2462
2463 /* Construct the mapReduce command */
2464 /* Other arguments can also be specified here, like "query" or "limit"
2465 and so on */
2466
2467 /* Read the results inline from a secondary replica */
2468 command = BCON_NEW ("mapReduce",
2469 BCON_UTF8 (COLLECTION_NAME),
2470 "map",
2471 BCON_CODE (MAPPER),
2472 "reduce",
2473 BCON_CODE (REDUCER),
2474 "out",
2475 "{",
2476 "inline",
2477 "1",
2478 "}");
2479
2480 read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
2481 cursor = mongoc_database_command (
2482 database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
2483
2484 /* Do something with the results */
2485 while (mongoc_cursor_next (cursor, &doc)) {
2486 print_res (doc);
2487 }
2488
2489 if (mongoc_cursor_error (cursor, &error)) {
2490 fprintf (stderr, "ERROR: %s\n", error.message);
2491 res = false;
2492 }
2493
2494 mongoc_cursor_destroy (cursor);
2495 mongoc_read_prefs_destroy (read_pref);
2496 bson_destroy (command);
2497
2498 return res;
2499 }
2500
2501
2502 Running the Examples
2503 Here's how to run the example code
2504
2505 basic-aggregation.c
2506
2507 /*
2508 * Copyright 2016 MongoDB, Inc.
2509 *
2510 * Licensed under the Apache License, Version 2.0 (the "License");
2511 * you may not use this file except in compliance with the License.
2512 * You may obtain a copy of the License at
2513 *
2514 * http://www.apache.org/licenses/LICENSE-2.0
2515 *
2516 * Unless required by applicable law or agreed to in writing, software
2517 * distributed under the License is distributed on an "AS IS" BASIS,
2518 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2519 * See the License for the specific language governing permissions and
2520 * limitations under the License.
2521 */
2522
2523
2524 #include <mongoc/mongoc.h>
2525 #include <stdio.h>
2526
2527
2528 #include "constants.c"
2529
2530 #include "../doc-common-insert.c"
2531 #include "distinct.c"
2532 #include "map-reduce-basic.c"
2533 #include "map-reduce-advanced.c"
2534
2535
2536 int
2537 main (int argc, char *argv[])
2538 {
2539 mongoc_database_t *database = NULL;
2540 mongoc_client_t *client = NULL;
2541 mongoc_collection_t *collection = NULL;
2542 mongoc_uri_t *uri = NULL;
2543 bson_error_t error;
2544 char *host_and_port = NULL;
2545 int exit_code = EXIT_FAILURE;
2546
2547 if (argc != 2) {
2548 fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
2549 fprintf (stderr,
2550 "the connection string can be of the following forms:\n");
2551 fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
2552 fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
2553 fprintf (stderr,
2554 "mongodb://user:pass@localhost:27017\t"
2555 "local machine on port 27017, and authenticate with username "
2556 "user and password pass\n");
2557 return exit_code;
2558 }
2559
2560 mongoc_init ();
2561
2562 if (strncmp (argv[1], "mongodb://", 10) == 0) {
2563 host_and_port = bson_strdup (argv[1]);
2564 } else {
2565 host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
2566 }
2567
2568 uri = mongoc_uri_new_with_error (host_and_port, &error);
2569 if (!uri) {
2570 fprintf (stderr,
2571 "failed to parse URI: %s\n"
2572 "error message: %s\n",
2573 host_and_port,
2574 error.message);
2575 goto cleanup;
2576 }
2577
2578 client = mongoc_client_new_from_uri (uri);
2579 if (!client) {
2580 goto cleanup;
2581 }
2582
2583 mongoc_client_set_error_api (client, 2);
2584 database = mongoc_client_get_database (client, "test");
2585 collection = mongoc_database_get_collection (database, COLLECTION_NAME);
2586
2587 printf ("Inserting data\n");
2588 if (!insert_data (collection)) {
2589 goto cleanup;
2590 }
2591
2592 printf ("distinct\n");
2593 if (!distinct (database)) {
2594 goto cleanup;
2595 }
2596
2597 printf ("map reduce\n");
2598 if (!map_reduce_basic (database)) {
2599 goto cleanup;
2600 }
2601
2602 printf ("more complicated map reduce\n");
2603 if (!map_reduce_advanced (database)) {
2604 goto cleanup;
2605 }
2606
2607 exit_code = EXIT_SUCCESS;
2608
2609 cleanup:
2610 if (collection) {
2611 mongoc_collection_destroy (collection);
2612 }
2613
2614 if (database) {
2615 mongoc_database_destroy (database);
2616 }
2617
2618 if (client) {
2619 mongoc_client_destroy (client);
2620 }
2621
2622 if (uri) {
2623 mongoc_uri_destroy (uri);
2624 }
2625
2626 if (host_and_port) {
2627 bson_free (host_and_port);
2628 }
2629
2630 mongoc_cleanup ();
2631 return exit_code;
2632 }
2633
2634
2635 If you want to try the advanced map reduce example with a secondary,
2636 start a replica set (instructions for how to do this can be found
2637 here).
2638
2639 Otherwise, just start an instance of MongoDB:
2640
2641 $ mongod
2642
2643 Now compile and run the example program:
2644
2645 $ cd examples/basic_aggregation/
2646 $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
2647 $ ./agg-example localhost
2648
2649 Inserting data
2650 distinct
2651 Next double: 2.000000
2652 Next double: 3.000000
2653 map reduce
2654 { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
2655 { "_id" : "cat", "value" : 63 }
2656 { "_id" : "dog", "value" : 42 }
2657 { "_id" : "mouse", "value" : 21 }
2658 more complicated map reduce
2659 { "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 }
2660
2662 Download and install libmongoc on your system, then open Visual Studio,
2663 select "File→New→Project...", and create a new Win32 Console Applica‐
2664 tion. [image]
2665
2666 Remember to switch the platform from 32-bit to 64-bit: [image]
2667
2668 Right-click on your console application in the Solution Explorer and
2669 select "Properties". Choose to edit properties for "All Configura‐
2670 tions", expand the "C/C++" options and choose "General". Add to the
2671 "Additional Include Directories" these paths:
2672
2673 C:\mongo-c-driver\include\libbson-1.0
2674 C:\mongo-c-driver\include\libmongoc-1.0
2675 [image]
2676
2677 (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
2678 include paths will be different.)
2679
2680 Also in the Properties dialog, expand the "Linker" options and choose
2681 "Input", and add to the "Additional Dependencies" these libraries:
2682
2683 C:\mongo-c-driver\lib\bson-1.0.lib
2684 C:\mongo-c-driver\lib\mongoc-1.0.lib
2685 [image]
2686
2687 Adding these libraries as dependencies provides linker symbols to build
2688 your application, but to actually run it, libbson's and libmongoc's
2689 DLLs must be in your executable path. Select "Debugging" in the Proper‐
2690 ties dialog, and set the "Environment" option to:
2691
2692 PATH=c:/mongo-c-driver/bin
2693 [image]
2694
2695 Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
2696
2697 #include <mongoc/mongoc.h>
2698
2699 Static linking
2700 Following the instructions above, you have dynamically linked your ap‐
2701 plication to the libbson and libmongoc DLLs. This is usually the right
2702 choice. If you want to link statically instead, update your "Additional
2703 Dependencies" list by removing bson-1.0.lib and mongoc-1.0.lib and re‐
2704 placing them with these libraries:
2705
2706 C:\mongo-c-driver\lib\bson-static-1.0.lib
2707 C:\mongo-c-driver\lib\mongoc-static-1.0.lib
2708 ws2_32.lib
2709 Secur32.lib
2710 Crypt32.lib
2711 BCrypt.lib
2712 [image]
2713
2714 (To explain the purpose of each library: bson-static-1.0.lib and mon‐
2715 goc-static-1.0.lib are static archives of the driver code. The socket
2716 library ws2_32 is required by libbson, which uses the socket routine
2717 gethostname to help guarantee ObjectId uniqueness. The BCrypt library
2718 is used by libmongoc for TLS connections to MongoDB, and Secur32 and
2719 Crypt32 are required for enterprise authentication methods like Ker‐
2720 beros.)
2721
2722 Finally, define two preprocessor symbols before including mongoc/mon‐
2723 goc.h in your stdafx.h:
2724
2725 #define BSON_STATIC
2726 #define MONGOC_STATIC
2727 #include <mongoc/mongoc.h>
2728
2729 Making these changes to your project is only required for static link‐
2730 ing; for most people, the dynamic-linking instructions above are pre‐
2731 ferred.
2732
2733 Next Steps
2734 Now you can build and debug applications in Visual Studio that use
2735 libbson and libmongoc. Proceed to Making a Connection in the tutorial
2736 to learn how connect to MongoDB and perform operations.
2737
2739 To create indexes on a MongoDB collection, use
2740 mongoc_collection_create_indexes_with_opts():
2741
2742 // `keys` represents an ascending index on field `x`.
2743 bson_t *keys = BCON_NEW ("x", BCON_INT32 (1));
2744 mongoc_index_model_t *im = mongoc_index_model_new (keys, NULL /* opts */);
2745 if (mongoc_collection_create_indexes_with_opts (
2746 coll, &im, 1, NULL /* opts */, NULL /* reply */, &error)) {
2747 printf ("Successfully created index\n");
2748 } else {
2749 bson_destroy (keys);
2750 HANDLE_ERROR ("Failed to create index: %s", error.message);
2751 }
2752 bson_destroy (keys);
2753
2754
2755 To list indexes, use mongoc_collection_find_indexes_with_opts():
2756
2757 mongoc_cursor_t *cursor =
2758 mongoc_collection_find_indexes_with_opts (coll, NULL /* opts */);
2759 printf ("Listing indexes:\n");
2760 const bson_t *got;
2761 while (mongoc_cursor_next (cursor, &got)) {
2762 char *got_str = bson_as_canonical_extended_json (got, NULL);
2763 printf (" %s\n", got_str);
2764 bson_free (got_str);
2765 }
2766 if (mongoc_cursor_error (cursor, &error)) {
2767 mongoc_cursor_destroy (cursor);
2768 HANDLE_ERROR ("Failed to list indexes: %s", error.message);
2769 }
2770 mongoc_cursor_destroy (cursor);
2771
2772
2773 To drop an index, use mongoc_collection_drop_index_with_opts(). The in‐
2774 dex name may be obtained from the keys document with
2775 mongoc_collection_keys_to_index_string():
2776
2777 bson_t *keys = BCON_NEW ("x", BCON_INT32 (1));
2778 char *index_name = mongoc_collection_keys_to_index_string (keys);
2779 if (mongoc_collection_drop_index_with_opts (
2780 coll, index_name, NULL /* opts */, &error)) {
2781 printf ("Successfully dropped index\n");
2782 } else {
2783 bson_free (index_name);
2784 bson_destroy (keys);
2785 HANDLE_ERROR ("Failed to drop index: %s", error.message);
2786 }
2787 bson_free (index_name);
2788 bson_destroy (keys);
2789
2790
2791 For a full example, see example-manage-collection-indexes.c.
2792
2794 GDB
2795 This repository contains a .gdbinit file that contains helper functions
2796 to aid debugging of data structures. GDB will load this file
2797 automatically if you have added the directory which contains the
2798 .gdbinit file to GDB's auto-load safe-path, and you start GDB from the
2799 directory which holds the .gdbinit file.
2800
2801 You can see the safe-path with show auto-load safe-path on a GDB
2802 prompt. You can configure it by setting it in ~/.gdbinit with:
2803
2804 add-auto-load-safe-path /path/to/mongo-c-driver
2805
2806 If you haven't added the path to your auto-load safe-path, or start GDB
2807 in another directory, load the file with:
2808
2809 source path/to/mongo-c-driver/.gdbinit
2810
2811 The .gdbinit file defines the printbson function, which shows the con‐
2812 tents of a bson_t * variable. If you have a local bson_t, then you
2813 must prefix the variable with a &.
2814
2815 An example GDB session looks like:
2816
2817 (gdb) printbson bson
2818 ALLOC [0x555556cd7310 + 0] (len=475)
2819 {
2820 'bool' : true,
2821 'int32' : NumberInt("42"),
2822 'int64' : NumberLong("3000000042"),
2823 'string' : "Stŕìñg",
2824 'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
2825 'utcDateTime' : UTCDateTime(1511277299031),
2826 'arrayOfInts' : [
2827 '0' : NumberInt("1"),
2828 '1' : NumberInt("2")
2829 ],
2830 'embeddedDocument' : {
2831 'arrayOfStrings' : [
2832 '0' : "one",
2833 '1' : "two"
2834 ],
2835 'double' : 2.718280,
2836 'notherDoc' : {
2837 'true' : NumberInt("1"),
2838 'false' : false
2839 }
2840 },
2841 'binary' : Binary("02", "3031343532333637"),
2842 'regex' : Regex("@[a-z]+@", "im"),
2843 'null' : null,
2844 'js' : JavaScript("print foo"),
2845 'jsws' : JavaScript("print foo") with scope: {
2846 'f' : NumberInt("42"),
2847 'a' : [
2848 '0' : 3.141593,
2849 '1' : 2.718282
2850 ]
2851 },
2852 'timestamp' : Timestamp(4294967295, 4294967295),
2853 'double' : 3.141593
2854 }
2855
2856 LLDB
2857 The mongo-c-driver repository contains a script lldb_bson.py that can
2858 be imported into an LLDB sessions and allows rich inspection of BSON
2859 values.
2860
2861 NOTE:
2862 The lldb_bson.py module requires an LLDB with Python 3.8 or newer.
2863
2864 To activate the script, import it from the LLDB command line:
2865
2866 (lldb) command script import /path/to/mongo-c-driver/lldb_bson.py
2867
2868 Upon success, the message lldb_bson is ready will be printed to the
2869 LLDB console.
2870
2871 The import of this script can be made automatic by adding the command
2872 to an .lldbinit file. For example: Create a file ~/.lldbinit contain‐
2873 ing:
2874
2875 command script import /path/to/mongo-c-driver/lldb_bson.py
2876
2877 The docstring at the top of the lldb_bson.py file contains more infor‐
2878 mation on the capabilities of the module.
2879
2880 Debug assertions
2881 To enable runtime debug assertions, configure with -DENABLE_DEBUG_AS‐
2882 SERTIONS=ON.
2883
2885 In-Use Encryption consists of two features:
2886
2887 Client-Side Field Level Encryption
2888 New in MongoDB 4.2, Client-Side Field Level Encryption (also referred
2889 to as CSFLE) allows administrators and developers to encrypt specific
2890 data fields in addition to other MongoDB encryption features.
2891
2892 With CSFLE, developers can encrypt fields client side without any
2893 server-side configuration or directives. CSFLE supports workloads where
2894 applications must guarantee that unauthorized parties, including server
2895 administrators, cannot read the encrypted data.
2896
2897 Automatic encryption, where sensitive fields in commands are encrypted
2898 automatically, requires an Enterprise-only dependency for Query Analy‐
2899 sis. See In-Use Encryption for more information.
2900
2901 SEE ALSO:
2902 The MongoDB Manual for Client-Side Field Level Encryption
2903
2904
2905 Automatic Client-Side Field Level Encryption
2906 Automatic encryption is enabled by calling
2907 mongoc_client_enable_auto_encryption() on a mongoc_client_t. The fol‐
2908 lowing examples show how to set up automatic encryption using
2909 mongoc_client_encryption_t to create a new encryption data key.
2910
2911 NOTE:
2912 Automatic encryption requires MongoDB 4.2 enterprise or a MongoDB
2913 4.2 Atlas cluster. The community version of the server supports au‐
2914 tomatic decryption as well as Explicit Encryption.
2915
2916 Providing Local Automatic Encryption Rules
2917 The following example shows how to specify automatic encryption rules
2918 using a schema map set with
2919 mongoc_auto_encryption_opts_set_schema_map(). The automatic encryption
2920 rules are expressed using a strict subset of the JSON Schema syntax.
2921
2922 Supplying a schema map provides more security than relying on JSON
2923 Schemas obtained from the server. It protects against a malicious
2924 server advertising a false JSON Schema, which could trick the client
2925 into sending unencrypted data that should be encrypted.
2926
2927 JSON Schemas supplied in the schema map only apply to configuring auto‐
2928 matic encryption. Other validation rules in the JSON schema will not be
2929 enforced by the driver and will result in an error:
2930
2931 client-side-encryption-schema-map.c
2932
2933 #include <mongoc/mongoc.h>
2934 #include <stdio.h>
2935 #include <stdlib.h>
2936
2937 #include "client-side-encryption-helpers.h"
2938
2939 /* Helper method to create a new data key in the key vault, a schema to use that
2940 * key, and writes the schema to a file for later use. */
2941 static bool
2942 create_schema_file (bson_t *kms_providers,
2943 const char *keyvault_db,
2944 const char *keyvault_coll,
2945 mongoc_client_t *keyvault_client,
2946 bson_error_t *error)
2947 {
2948 mongoc_client_encryption_t *client_encryption = NULL;
2949 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
2950 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
2951 bson_value_t datakey_id = {0};
2952 char *keyaltnames[] = {"mongoc_encryption_example_1"};
2953 bson_t *schema = NULL;
2954 char *schema_string = NULL;
2955 size_t schema_string_len;
2956 FILE *outfile = NULL;
2957 bool ret = false;
2958
2959 client_encryption_opts = mongoc_client_encryption_opts_new ();
2960 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
2961 kms_providers);
2962 mongoc_client_encryption_opts_set_keyvault_namespace (
2963 client_encryption_opts, keyvault_db, keyvault_coll);
2964 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
2965 keyvault_client);
2966
2967 client_encryption =
2968 mongoc_client_encryption_new (client_encryption_opts, error);
2969 if (!client_encryption) {
2970 goto fail;
2971 }
2972
2973 /* Create a new data key and json schema for the encryptedField.
2974 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
2975 */
2976 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
2977 mongoc_client_encryption_datakey_opts_set_keyaltnames (
2978 datakey_opts, keyaltnames, 1);
2979 if (!mongoc_client_encryption_create_datakey (
2980 client_encryption, "local", datakey_opts, &datakey_id, error)) {
2981 goto fail;
2982 }
2983
2984 /* Create a schema describing that "encryptedField" is a string encrypted
2985 * with the newly created data key using deterministic encryption. */
2986 schema = BCON_NEW ("properties",
2987 "{",
2988 "encryptedField",
2989 "{",
2990 "encrypt",
2991 "{",
2992 "keyId",
2993 "[",
2994 BCON_BIN (datakey_id.value.v_binary.subtype,
2995 datakey_id.value.v_binary.data,
2996 datakey_id.value.v_binary.data_len),
2997 "]",
2998 "bsonType",
2999 "string",
3000 "algorithm",
3001 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
3002 "}",
3003 "}",
3004 "}",
3005 "bsonType",
3006 "object");
3007
3008 /* Use canonical JSON so that other drivers and tools will be
3009 * able to parse the MongoDB extended JSON file. */
3010 schema_string = bson_as_canonical_extended_json (schema, &schema_string_len);
3011 outfile = fopen ("jsonSchema.json", "w");
3012 if (0 == fwrite (schema_string, sizeof (char), schema_string_len, outfile)) {
3013 fprintf (stderr, "failed to write to file\n");
3014 goto fail;
3015 }
3016
3017 ret = true;
3018 fail:
3019 mongoc_client_encryption_destroy (client_encryption);
3020 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
3021 mongoc_client_encryption_opts_destroy (client_encryption_opts);
3022 bson_free (schema_string);
3023 bson_destroy (schema);
3024 bson_value_destroy (&datakey_id);
3025 if (outfile) {
3026 fclose (outfile);
3027 }
3028 return ret;
3029 }
3030
3031 /* This example demonstrates how to use automatic encryption with a client-side
3032 * schema map using the enterprise version of MongoDB */
3033 int
3034 main (void)
3035 {
3036 /* The collection used to store the encryption data keys. */
3037 #define KEYVAULT_DB "encryption"
3038 #define KEYVAULT_COLL "__libmongocTestKeyVault"
3039 /* The collection used to store the encrypted documents in this example. */
3040 #define ENCRYPTED_DB "test"
3041 #define ENCRYPTED_COLL "coll"
3042
3043 int exit_status = EXIT_FAILURE;
3044 bool ret;
3045 uint8_t *local_masterkey = NULL;
3046 uint32_t local_masterkey_len;
3047 bson_t *kms_providers = NULL;
3048 bson_error_t error = {0};
3049 bson_t *index_keys = NULL;
3050 bson_t *index_opts = NULL;
3051 mongoc_index_model_t *index_model = NULL;
3052 bson_json_reader_t *reader = NULL;
3053 bson_t schema = BSON_INITIALIZER;
3054 bson_t *schema_map = NULL;
3055
3056 /* The MongoClient used to access the key vault (keyvault_namespace). */
3057 mongoc_client_t *keyvault_client = NULL;
3058 mongoc_collection_t *keyvault_coll = NULL;
3059 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
3060 mongoc_client_t *client = NULL;
3061 mongoc_collection_t *coll = NULL;
3062 bson_t *to_insert = NULL;
3063 mongoc_client_t *unencrypted_client = NULL;
3064 mongoc_collection_t *unencrypted_coll = NULL;
3065
3066 mongoc_init ();
3067
3068 /* Configure the master key. This must be the same master key that was used
3069 * to create the encryption key. */
3070 local_masterkey =
3071 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
3072 if (!local_masterkey || local_masterkey_len != 96) {
3073 fprintf (stderr,
3074 "Specify LOCAL_MASTERKEY environment variable as a "
3075 "secure random 96 byte hex value.\n");
3076 goto fail;
3077 }
3078
3079 kms_providers = BCON_NEW ("local",
3080 "{",
3081 "key",
3082 BCON_BIN (0, local_masterkey, local_masterkey_len),
3083 "}");
3084
3085 /* Set up the key vault for this example. */
3086 keyvault_client = mongoc_client_new (
3087 "mongodb://localhost/?appname=client-side-encryption-keyvault");
3088 BSON_ASSERT (keyvault_client);
3089
3090 keyvault_coll = mongoc_client_get_collection (
3091 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
3092 mongoc_collection_drop (keyvault_coll, NULL);
3093
3094 /* Create a unique index to ensure that two data keys cannot share the same
3095 * keyAltName. This is recommended practice for the key vault. */
3096 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
3097 index_opts = BCON_NEW ("unique",
3098 BCON_BOOL (true),
3099 "partialFilterExpression",
3100 "{",
3101 "keyAltNames",
3102 "{",
3103 "$exists",
3104 BCON_BOOL (true),
3105 "}",
3106 "}");
3107 index_model = mongoc_index_model_new (index_keys, index_opts);
3108 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
3109 &index_model,
3110 1,
3111 NULL /* opts */,
3112 NULL /* reply */,
3113 &error);
3114
3115 if (!ret) {
3116 goto fail;
3117 }
3118
3119 /* Create a new data key and a schema using it for encryption. Save the
3120 * schema to the file jsonSchema.json */
3121 ret = create_schema_file (
3122 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
3123
3124 if (!ret) {
3125 goto fail;
3126 }
3127
3128 /* Load the JSON Schema and construct the local schema_map option. */
3129 reader = bson_json_reader_new_from_file ("jsonSchema.json", &error);
3130 if (!reader) {
3131 goto fail;
3132 }
3133
3134 bson_json_reader_read (reader, &schema, &error);
3135
3136 /* Construct the schema map, mapping the namespace of the collection to the
3137 * schema describing encryption. */
3138 schema_map =
3139 BCON_NEW (ENCRYPTED_DB "." ENCRYPTED_COLL, BCON_DOCUMENT (&schema));
3140
3141 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
3142 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
3143 keyvault_client);
3144 mongoc_auto_encryption_opts_set_keyvault_namespace (
3145 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
3146 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
3147 kms_providers);
3148 mongoc_auto_encryption_opts_set_schema_map (auto_encryption_opts,
3149 schema_map);
3150
3151 client =
3152 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
3153 BSON_ASSERT (client);
3154
3155 /* Enable automatic encryption. It will determine that encryption is
3156 * necessary from the schema map instead of relying on the server to provide
3157 * a schema. */
3158 ret = mongoc_client_enable_auto_encryption (
3159 client, auto_encryption_opts, &error);
3160 if (!ret) {
3161 goto fail;
3162 }
3163
3164 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
3165
3166 /* Clear old data */
3167 mongoc_collection_drop (coll, NULL);
3168
3169 to_insert = BCON_NEW ("encryptedField", "123456789");
3170 ret = mongoc_collection_insert_one (
3171 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
3172 if (!ret) {
3173 goto fail;
3174 }
3175 printf ("decrypted document: ");
3176 if (!print_one_document (coll, &error)) {
3177 goto fail;
3178 }
3179 printf ("\n");
3180
3181 unencrypted_client = mongoc_client_new (
3182 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
3183 BSON_ASSERT (unencrypted_client);
3184
3185 unencrypted_coll = mongoc_client_get_collection (
3186 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
3187 printf ("encrypted document: ");
3188 if (!print_one_document (unencrypted_coll, &error)) {
3189 goto fail;
3190 }
3191 printf ("\n");
3192
3193 exit_status = EXIT_SUCCESS;
3194 fail:
3195 if (error.code) {
3196 fprintf (stderr, "error: %s\n", error.message);
3197 }
3198
3199 bson_free (local_masterkey);
3200 bson_destroy (kms_providers);
3201 mongoc_collection_destroy (keyvault_coll);
3202 mongoc_index_model_destroy (index_model);
3203 bson_destroy (index_opts);
3204 bson_destroy (index_keys);
3205 bson_json_reader_destroy (reader);
3206 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
3207 mongoc_collection_destroy (coll);
3208 mongoc_client_destroy (client);
3209 bson_destroy (to_insert);
3210 mongoc_collection_destroy (unencrypted_coll);
3211 mongoc_client_destroy (unencrypted_client);
3212 mongoc_client_destroy (keyvault_client);
3213 bson_destroy (&schema);
3214 bson_destroy (schema_map);
3215 mongoc_cleanup ();
3216 return exit_status;
3217 }
3218
3219
3220 Server-Side Field Level Encryption Enforcement
3221 The MongoDB 4.2 server supports using schema validation to enforce en‐
3222 cryption of specific fields in a collection. This schema validation
3223 will prevent an application from inserting unencrypted values for any
3224 fields marked with the "encrypt" JSON schema keyword.
3225
3226 The following example shows how to set up automatic encryption using
3227 mongoc_client_encryption_t to create a new encryption data key and cre‐
3228 ate a collection with the necessary JSON Schema:
3229
3230 client-side-encryption-server-schema.c
3231
3232 #include <mongoc/mongoc.h>
3233 #include <stdio.h>
3234 #include <stdlib.h>
3235
3236 #include "client-side-encryption-helpers.h"
3237
3238 /* Helper method to create and return a JSON schema to use for encryption.
3239 The caller will use the returned schema for server-side encryption validation.
3240 */
3241 static bson_t *
3242 create_schema (bson_t *kms_providers,
3243 const char *keyvault_db,
3244 const char *keyvault_coll,
3245 mongoc_client_t *keyvault_client,
3246 bson_error_t *error)
3247 {
3248 mongoc_client_encryption_t *client_encryption = NULL;
3249 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
3250 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
3251 bson_value_t datakey_id = {0};
3252 char *keyaltnames[] = {"mongoc_encryption_example_2"};
3253 bson_t *schema = NULL;
3254
3255 client_encryption_opts = mongoc_client_encryption_opts_new ();
3256 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
3257 kms_providers);
3258 mongoc_client_encryption_opts_set_keyvault_namespace (
3259 client_encryption_opts, keyvault_db, keyvault_coll);
3260 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
3261 keyvault_client);
3262
3263 client_encryption =
3264 mongoc_client_encryption_new (client_encryption_opts, error);
3265 if (!client_encryption) {
3266 goto fail;
3267 }
3268
3269 /* Create a new data key and json schema for the encryptedField.
3270 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
3271 */
3272 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
3273 mongoc_client_encryption_datakey_opts_set_keyaltnames (
3274 datakey_opts, keyaltnames, 1);
3275 if (!mongoc_client_encryption_create_datakey (
3276 client_encryption, "local", datakey_opts, &datakey_id, error)) {
3277 goto fail;
3278 }
3279
3280 /* Create a schema describing that "encryptedField" is a string encrypted
3281 * with the newly created data key using deterministic encryption. */
3282 schema = BCON_NEW ("properties",
3283 "{",
3284 "encryptedField",
3285 "{",
3286 "encrypt",
3287 "{",
3288 "keyId",
3289 "[",
3290 BCON_BIN (datakey_id.value.v_binary.subtype,
3291 datakey_id.value.v_binary.data,
3292 datakey_id.value.v_binary.data_len),
3293 "]",
3294 "bsonType",
3295 "string",
3296 "algorithm",
3297 MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
3298 "}",
3299 "}",
3300 "}",
3301 "bsonType",
3302 "object");
3303
3304 fail:
3305 mongoc_client_encryption_destroy (client_encryption);
3306 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
3307 mongoc_client_encryption_opts_destroy (client_encryption_opts);
3308 bson_value_destroy (&datakey_id);
3309 return schema;
3310 }
3311
3312 /* This example demonstrates how to use automatic encryption with a server-side
3313 * schema using the enterprise version of MongoDB */
3314 int
3315 main (void)
3316 {
3317 /* The collection used to store the encryption data keys. */
3318 #define KEYVAULT_DB "encryption"
3319 #define KEYVAULT_COLL "__libmongocTestKeyVault"
3320 /* The collection used to store the encrypted documents in this example. */
3321 #define ENCRYPTED_DB "test"
3322 #define ENCRYPTED_COLL "coll"
3323
3324 int exit_status = EXIT_FAILURE;
3325 bool ret;
3326 uint8_t *local_masterkey = NULL;
3327 uint32_t local_masterkey_len;
3328 bson_t *kms_providers = NULL;
3329 bson_error_t error = {0};
3330 bson_t *index_keys = NULL;
3331 bson_t *index_opts = NULL;
3332 mongoc_index_model_t *index_model = NULL;
3333 bson_json_reader_t *reader = NULL;
3334 bson_t *schema = NULL;
3335
3336 /* The MongoClient used to access the key vault (keyvault_namespace). */
3337 mongoc_client_t *keyvault_client = NULL;
3338 mongoc_collection_t *keyvault_coll = NULL;
3339 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
3340 mongoc_client_t *client = NULL;
3341 mongoc_collection_t *coll = NULL;
3342 bson_t *to_insert = NULL;
3343 mongoc_client_t *unencrypted_client = NULL;
3344 mongoc_collection_t *unencrypted_coll = NULL;
3345 bson_t *create_cmd = NULL;
3346 bson_t *create_cmd_opts = NULL;
3347 mongoc_write_concern_t *wc = NULL;
3348
3349 mongoc_init ();
3350
3351 /* Configure the master key. This must be the same master key that was used
3352 * to create
3353 * the encryption key. */
3354 local_masterkey =
3355 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
3356 if (!local_masterkey || local_masterkey_len != 96) {
3357 fprintf (stderr,
3358 "Specify LOCAL_MASTERKEY environment variable as a "
3359 "secure random 96 byte hex value.\n");
3360 goto fail;
3361 }
3362
3363 kms_providers = BCON_NEW ("local",
3364 "{",
3365 "key",
3366 BCON_BIN (0, local_masterkey, local_masterkey_len),
3367 "}");
3368
3369 /* Set up the key vault for this example. */
3370 keyvault_client = mongoc_client_new (
3371 "mongodb://localhost/?appname=client-side-encryption-keyvault");
3372 BSON_ASSERT (keyvault_client);
3373
3374 keyvault_coll = mongoc_client_get_collection (
3375 keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
3376 mongoc_collection_drop (keyvault_coll, NULL);
3377
3378 /* Create a unique index to ensure that two data keys cannot share the same
3379 * keyAltName. This is recommended practice for the key vault. */
3380 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
3381 index_opts = BCON_NEW ("unique",
3382 BCON_BOOL (true),
3383 "partialFilterExpression",
3384 "{",
3385 "keyAltNames",
3386 "{",
3387 "$exists",
3388 BCON_BOOL (true),
3389 "}",
3390 "}");
3391 index_model = mongoc_index_model_new (index_keys, index_opts);
3392 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
3393 &index_model,
3394 1,
3395 NULL /* opts */,
3396 NULL /* reply */,
3397 &error);
3398
3399 if (!ret) {
3400 goto fail;
3401 }
3402
3403 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
3404 mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
3405 keyvault_client);
3406 mongoc_auto_encryption_opts_set_keyvault_namespace (
3407 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
3408 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
3409 kms_providers);
3410 schema = create_schema (
3411 kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
3412
3413 if (!schema) {
3414 goto fail;
3415 }
3416
3417 client =
3418 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
3419 BSON_ASSERT (client);
3420
3421 ret = mongoc_client_enable_auto_encryption (
3422 client, auto_encryption_opts, &error);
3423 if (!ret) {
3424 goto fail;
3425 }
3426
3427 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
3428
3429 /* Clear old data */
3430 mongoc_collection_drop (coll, NULL);
3431
3432 /* Create the collection with the encryption JSON Schema. */
3433 create_cmd = BCON_NEW ("create",
3434 ENCRYPTED_COLL,
3435 "validator",
3436 "{",
3437 "$jsonSchema",
3438 BCON_DOCUMENT (schema),
3439 "}");
3440 wc = mongoc_write_concern_new ();
3441 mongoc_write_concern_set_wmajority (wc, 0);
3442 create_cmd_opts = bson_new ();
3443 mongoc_write_concern_append (wc, create_cmd_opts);
3444 ret = mongoc_client_command_with_opts (client,
3445 ENCRYPTED_DB,
3446 create_cmd,
3447 NULL /* read prefs */,
3448 create_cmd_opts,
3449 NULL /* reply */,
3450 &error);
3451 if (!ret) {
3452 goto fail;
3453 }
3454
3455 to_insert = BCON_NEW ("encryptedField", "123456789");
3456 ret = mongoc_collection_insert_one (
3457 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
3458 if (!ret) {
3459 goto fail;
3460 }
3461 printf ("decrypted document: ");
3462 if (!print_one_document (coll, &error)) {
3463 goto fail;
3464 }
3465 printf ("\n");
3466
3467 unencrypted_client = mongoc_client_new (
3468 "mongodb://localhost/?appname=client-side-encryption-unencrypted");
3469 BSON_ASSERT (unencrypted_client);
3470
3471 unencrypted_coll = mongoc_client_get_collection (
3472 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
3473 printf ("encrypted document: ");
3474 if (!print_one_document (unencrypted_coll, &error)) {
3475 goto fail;
3476 }
3477 printf ("\n");
3478
3479 /* Expect a server-side error if inserting with the unencrypted collection.
3480 */
3481 ret = mongoc_collection_insert_one (
3482 unencrypted_coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
3483 if (!ret) {
3484 printf ("insert with unencrypted collection failed: %s\n", error.message);
3485 memset (&error, 0, sizeof (error));
3486 }
3487
3488 exit_status = EXIT_SUCCESS;
3489 fail:
3490 if (error.code) {
3491 fprintf (stderr, "error: %s\n", error.message);
3492 }
3493
3494 bson_free (local_masterkey);
3495 bson_destroy (kms_providers);
3496 mongoc_collection_destroy (keyvault_coll);
3497 mongoc_index_model_destroy (index_model);
3498 bson_destroy (index_opts);
3499 bson_destroy (index_keys);
3500 bson_json_reader_destroy (reader);
3501 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
3502 mongoc_collection_destroy (coll);
3503 mongoc_client_destroy (client);
3504 bson_destroy (to_insert);
3505 mongoc_collection_destroy (unencrypted_coll);
3506 mongoc_client_destroy (unencrypted_client);
3507 mongoc_client_destroy (keyvault_client);
3508 bson_destroy (schema);
3509 bson_destroy (create_cmd);
3510 bson_destroy (create_cmd_opts);
3511 mongoc_write_concern_destroy (wc);
3512
3513 mongoc_cleanup ();
3514 return exit_status;
3515 }
3516
3517
3518 Explicit Encryption
3519 Explicit encryption is a MongoDB community feature and does not use
3520 Query Analysis (mongocryptd or crypt_shared). Explicit encryption is
3521 provided by the mongoc_client_encryption_t class, for example:
3522
3523 client-side-encryption-explicit.c
3524
3525 #include <mongoc/mongoc.h>
3526 #include <stdio.h>
3527 #include <stdlib.h>
3528
3529 #include "client-side-encryption-helpers.h"
3530
3531 /* This example demonstrates how to use explicit encryption and decryption using
3532 * the community version of MongoDB */
3533 int
3534 main (void)
3535 {
3536 /* The collection used to store the encryption data keys. */
3537 #define KEYVAULT_DB "encryption"
3538 #define KEYVAULT_COLL "__libmongocTestKeyVault"
3539 /* The collection used to store the encrypted documents in this example. */
3540 #define ENCRYPTED_DB "test"
3541 #define ENCRYPTED_COLL "coll"
3542
3543 int exit_status = EXIT_FAILURE;
3544 bool ret;
3545 uint8_t *local_masterkey = NULL;
3546 uint32_t local_masterkey_len;
3547 bson_t *kms_providers = NULL;
3548 bson_error_t error = {0};
3549 bson_t *index_keys = NULL;
3550 bson_t *index_opts = NULL;
3551 mongoc_index_model_t *index_model = NULL;
3552 bson_t *schema = NULL;
3553 mongoc_client_t *client = NULL;
3554 mongoc_collection_t *coll = NULL;
3555 mongoc_collection_t *keyvault_coll = NULL;
3556 bson_t *to_insert = NULL;
3557 bson_t *create_cmd = NULL;
3558 bson_t *create_cmd_opts = NULL;
3559 mongoc_write_concern_t *wc = NULL;
3560 mongoc_client_encryption_t *client_encryption = NULL;
3561 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
3562 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
3563 char *keyaltnames[] = {"mongoc_encryption_example_3"};
3564 bson_value_t datakey_id = {0};
3565 bson_value_t encrypted_field = {0};
3566 bson_value_t to_encrypt = {0};
3567 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
3568 bson_value_t decrypted = {0};
3569
3570 mongoc_init ();
3571
3572 /* Configure the master key. This must be the same master key that was used
3573 * to create the encryption key. */
3574 local_masterkey =
3575 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
3576 if (!local_masterkey || local_masterkey_len != 96) {
3577 fprintf (stderr,
3578 "Specify LOCAL_MASTERKEY environment variable as a "
3579 "secure random 96 byte hex value.\n");
3580 goto fail;
3581 }
3582
3583 kms_providers = BCON_NEW ("local",
3584 "{",
3585 "key",
3586 BCON_BIN (0, local_masterkey, local_masterkey_len),
3587 "}");
3588
3589 /* The mongoc_client_t used to read/write application data. */
3590 client =
3591 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
3592 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
3593
3594 /* Clear old data */
3595 mongoc_collection_drop (coll, NULL);
3596
3597 /* Set up the key vault for this example. */
3598 keyvault_coll =
3599 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
3600 mongoc_collection_drop (keyvault_coll, NULL);
3601
3602 /* Create a unique index to ensure that two data keys cannot share the same
3603 * keyAltName. This is recommended practice for the key vault. */
3604 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
3605 index_opts = BCON_NEW ("unique",
3606 BCON_BOOL (true),
3607 "partialFilterExpression",
3608 "{",
3609 "keyAltNames",
3610 "{",
3611 "$exists",
3612 BCON_BOOL (true),
3613 "}",
3614 "}");
3615 index_model = mongoc_index_model_new (index_keys, index_opts);
3616 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
3617 &index_model,
3618 1,
3619 NULL /* opts */,
3620 NULL /* reply */,
3621 &error);
3622
3623 if (!ret) {
3624 goto fail;
3625 }
3626
3627 client_encryption_opts = mongoc_client_encryption_opts_new ();
3628 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
3629 kms_providers);
3630 mongoc_client_encryption_opts_set_keyvault_namespace (
3631 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
3632
3633 /* Set a mongoc_client_t to use for reading/writing to the key vault. This
3634 * can be the same mongoc_client_t used by the main application. */
3635 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
3636 client);
3637 client_encryption =
3638 mongoc_client_encryption_new (client_encryption_opts, &error);
3639 if (!client_encryption) {
3640 goto fail;
3641 }
3642
3643 /* Create a new data key for the encryptedField.
3644 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
3645 */
3646 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
3647 mongoc_client_encryption_datakey_opts_set_keyaltnames (
3648 datakey_opts, keyaltnames, 1);
3649 if (!mongoc_client_encryption_create_datakey (
3650 client_encryption, "local", datakey_opts, &datakey_id, &error)) {
3651 goto fail;
3652 }
3653
3654 /* Explicitly encrypt a field */
3655 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
3656 mongoc_client_encryption_encrypt_opts_set_algorithm (
3657 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
3658 mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts, &datakey_id);
3659 to_encrypt.value_type = BSON_TYPE_UTF8;
3660 to_encrypt.value.v_utf8.str = "123456789";
3661 const size_t len = strlen (to_encrypt.value.v_utf8.str);
3662 BSON_ASSERT (bson_in_range_unsigned (uint32_t, len));
3663 to_encrypt.value.v_utf8.len = (uint32_t) len;
3664
3665 ret = mongoc_client_encryption_encrypt (
3666 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
3667 if (!ret) {
3668 goto fail;
3669 }
3670
3671 to_insert = bson_new ();
3672 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
3673 ret = mongoc_collection_insert_one (
3674 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
3675 if (!ret) {
3676 goto fail;
3677 }
3678
3679 printf ("encrypted document: ");
3680 if (!print_one_document (coll, &error)) {
3681 goto fail;
3682 }
3683 printf ("\n");
3684
3685 /* Explicitly decrypt a field */
3686 ret = mongoc_client_encryption_decrypt (
3687 client_encryption, &encrypted_field, &decrypted, &error);
3688 if (!ret) {
3689 goto fail;
3690 }
3691 printf ("decrypted value: %s\n", decrypted.value.v_utf8.str);
3692
3693 exit_status = EXIT_SUCCESS;
3694 fail:
3695 if (error.code) {
3696 fprintf (stderr, "error: %s\n", error.message);
3697 }
3698
3699 bson_free (local_masterkey);
3700 bson_destroy (kms_providers);
3701 mongoc_collection_destroy (keyvault_coll);
3702 mongoc_index_model_destroy (index_model);
3703 bson_destroy (index_opts);
3704 bson_destroy (index_keys);
3705 mongoc_collection_destroy (coll);
3706 mongoc_client_destroy (client);
3707 bson_destroy (to_insert);
3708 bson_destroy (schema);
3709 bson_destroy (create_cmd);
3710 bson_destroy (create_cmd_opts);
3711 mongoc_write_concern_destroy (wc);
3712 mongoc_client_encryption_destroy (client_encryption);
3713 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
3714 mongoc_client_encryption_opts_destroy (client_encryption_opts);
3715 bson_value_destroy (&encrypted_field);
3716 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
3717 bson_value_destroy (&decrypted);
3718 bson_value_destroy (&datakey_id);
3719
3720 mongoc_cleanup ();
3721 return exit_status;
3722 }
3723
3724
3725 Explicit Encryption with Automatic Decryption
3726 Although automatic encryption requires MongoDB 4.2 enterprise or a Mon‐
3727 goDB 4.2 Atlas cluster, automatic decryption is supported for all
3728 users. To configure automatic decryption without automatic encryption
3729 set bypass_auto_encryption=True in mongoc_auto_encryption_opts_t:
3730
3731 client-side-encryption-auto-decryption.c
3732
3733 #include <mongoc/mongoc.h>
3734 #include <stdio.h>
3735 #include <stdlib.h>
3736
3737 #include "client-side-encryption-helpers.h"
3738
3739 /* This example demonstrates how to set up automatic decryption without
3740 * automatic encryption using the community version of MongoDB */
3741 int
3742 main (void)
3743 {
3744 /* The collection used to store the encryption data keys. */
3745 #define KEYVAULT_DB "encryption"
3746 #define KEYVAULT_COLL "__libmongocTestKeyVault"
3747 /* The collection used to store the encrypted documents in this example. */
3748 #define ENCRYPTED_DB "test"
3749 #define ENCRYPTED_COLL "coll"
3750
3751 int exit_status = EXIT_FAILURE;
3752 bool ret;
3753 uint8_t *local_masterkey = NULL;
3754 uint32_t local_masterkey_len;
3755 bson_t *kms_providers = NULL;
3756 bson_error_t error = {0};
3757 bson_t *index_keys = NULL;
3758 bson_t *index_opts = NULL;
3759 mongoc_index_model_t *index_model = NULL;
3760 bson_t *schema = NULL;
3761 mongoc_client_t *client = NULL;
3762 mongoc_collection_t *coll = NULL;
3763 mongoc_collection_t *keyvault_coll = NULL;
3764 bson_t *to_insert = NULL;
3765 bson_t *create_cmd = NULL;
3766 bson_t *create_cmd_opts = NULL;
3767 mongoc_write_concern_t *wc = NULL;
3768 mongoc_client_encryption_t *client_encryption = NULL;
3769 mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
3770 mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
3771 char *keyaltnames[] = {"mongoc_encryption_example_4"};
3772 bson_value_t datakey_id = {0};
3773 bson_value_t encrypted_field = {0};
3774 bson_value_t to_encrypt = {0};
3775 mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
3776 bson_value_t decrypted = {0};
3777 mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
3778 mongoc_client_t *unencrypted_client = NULL;
3779 mongoc_collection_t *unencrypted_coll = NULL;
3780
3781 mongoc_init ();
3782
3783 /* Configure the master key. This must be the same master key that was used
3784 * to create the encryption key. */
3785 local_masterkey =
3786 hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
3787 if (!local_masterkey || local_masterkey_len != 96) {
3788 fprintf (stderr,
3789 "Specify LOCAL_MASTERKEY environment variable as a "
3790 "secure random 96 byte hex value.\n");
3791 goto fail;
3792 }
3793
3794 kms_providers = BCON_NEW ("local",
3795 "{",
3796 "key",
3797 BCON_BIN (0, local_masterkey, local_masterkey_len),
3798 "}");
3799
3800 client =
3801 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
3802 auto_encryption_opts = mongoc_auto_encryption_opts_new ();
3803 mongoc_auto_encryption_opts_set_keyvault_namespace (
3804 auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
3805 mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
3806 kms_providers);
3807
3808 /* Setting bypass_auto_encryption to true disables automatic encryption but
3809 * keeps the automatic decryption behavior. bypass_auto_encryption will also
3810 * disable spawning mongocryptd */
3811 mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts,
3812 true);
3813
3814 /* Once bypass_auto_encryption is set, community users can enable auto
3815 * encryption on the client. This will, in fact, only perform automatic
3816 * decryption. */
3817 ret = mongoc_client_enable_auto_encryption (
3818 client, auto_encryption_opts, &error);
3819 if (!ret) {
3820 goto fail;
3821 }
3822
3823 /* Now that automatic decryption is on, we can test it by inserting a
3824 * document with an explicitly encrypted value into the collection. When we
3825 * look up the document later, it should be automatically decrypted for us.
3826 */
3827 coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
3828
3829 /* Clear old data */
3830 mongoc_collection_drop (coll, NULL);
3831
3832 /* Set up the key vault for this example. */
3833 keyvault_coll =
3834 mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
3835 mongoc_collection_drop (keyvault_coll, NULL);
3836
3837 /* Create a unique index to ensure that two data keys cannot share the same
3838 * keyAltName. This is recommended practice for the key vault. */
3839 index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
3840 index_opts = BCON_NEW ("unique",
3841 BCON_BOOL (true),
3842 "partialFilterExpression",
3843 "{",
3844 "keyAltNames",
3845 "{",
3846 "$exists",
3847 BCON_BOOL (true),
3848 "}",
3849 "}");
3850 index_model = mongoc_index_model_new (index_keys, index_opts);
3851 ret = mongoc_collection_create_indexes_with_opts (keyvault_coll,
3852 &index_model,
3853 1,
3854 NULL /* opts */,
3855 NULL /* reply */,
3856 &error);
3857
3858 if (!ret) {
3859 goto fail;
3860 }
3861
3862 client_encryption_opts = mongoc_client_encryption_opts_new ();
3863 mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
3864 kms_providers);
3865 mongoc_client_encryption_opts_set_keyvault_namespace (
3866 client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
3867
3868 /* The key vault client is used for reading to/from the key vault. This can
3869 * be the same mongoc_client_t used by the application. */
3870 mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
3871 client);
3872 client_encryption =
3873 mongoc_client_encryption_new (client_encryption_opts, &error);
3874 if (!client_encryption) {
3875 goto fail;
3876 }
3877
3878 /* Create a new data key for the encryptedField.
3879 * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
3880 */
3881 datakey_opts = mongoc_client_encryption_datakey_opts_new ();
3882 mongoc_client_encryption_datakey_opts_set_keyaltnames (
3883 datakey_opts, keyaltnames, 1);
3884 ret = mongoc_client_encryption_create_datakey (
3885 client_encryption, "local", datakey_opts, &datakey_id, &error);
3886 if (!ret) {
3887 goto fail;
3888 }
3889
3890 /* Explicitly encrypt a field. */
3891 encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
3892 mongoc_client_encryption_encrypt_opts_set_algorithm (
3893 encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
3894 mongoc_client_encryption_encrypt_opts_set_keyaltname (
3895 encrypt_opts, "mongoc_encryption_example_4");
3896 to_encrypt.value_type = BSON_TYPE_UTF8;
3897 to_encrypt.value.v_utf8.str = "123456789";
3898 const size_t len = strlen (to_encrypt.value.v_utf8.str);
3899 BSON_ASSERT (bson_in_range_unsigned (uint32_t, len));
3900 to_encrypt.value.v_utf8.len = (uint32_t) len;
3901
3902 ret = mongoc_client_encryption_encrypt (
3903 client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
3904 if (!ret) {
3905 goto fail;
3906 }
3907
3908 to_insert = bson_new ();
3909 BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
3910 ret = mongoc_collection_insert_one (
3911 coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
3912 if (!ret) {
3913 goto fail;
3914 }
3915
3916 /* When we retrieve the document, any encrypted fields will get automatically
3917 * decrypted by the driver. */
3918 printf ("decrypted document: ");
3919 if (!print_one_document (coll, &error)) {
3920 goto fail;
3921 }
3922 printf ("\n");
3923
3924 unencrypted_client =
3925 mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
3926 unencrypted_coll = mongoc_client_get_collection (
3927 unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
3928
3929 printf ("encrypted document: ");
3930 if (!print_one_document (unencrypted_coll, &error)) {
3931 goto fail;
3932 }
3933 printf ("\n");
3934
3935 exit_status = EXIT_SUCCESS;
3936 fail:
3937 if (error.code) {
3938 fprintf (stderr, "error: %s\n", error.message);
3939 }
3940
3941 bson_free (local_masterkey);
3942 bson_destroy (kms_providers);
3943 mongoc_collection_destroy (keyvault_coll);
3944 mongoc_index_model_destroy (index_model);
3945 bson_destroy (index_opts);
3946 bson_destroy (index_keys);
3947 mongoc_collection_destroy (coll);
3948 mongoc_client_destroy (client);
3949 bson_destroy (to_insert);
3950 bson_destroy (schema);
3951 bson_destroy (create_cmd);
3952 bson_destroy (create_cmd_opts);
3953 mongoc_write_concern_destroy (wc);
3954 mongoc_client_encryption_destroy (client_encryption);
3955 mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
3956 mongoc_client_encryption_opts_destroy (client_encryption_opts);
3957 bson_value_destroy (&encrypted_field);
3958 mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
3959 bson_value_destroy (&decrypted);
3960 bson_value_destroy (&datakey_id);
3961 mongoc_collection_destroy (unencrypted_coll);
3962 mongoc_client_destroy (unencrypted_client);
3963 mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
3964
3965 mongoc_cleanup ();
3966 return exit_status;
3967 }
3968
3969
3970 Queryable Encryption
3971 Using Queryable Encryption requires MongoDB Server 7.0 or higher.
3972
3973 See the MongoDB Manual for Queryable Encryption for more information
3974 about the feature.
3975
3976 API related to the "rangePreview" algorithm is still experimental and
3977 subject to breaking changes!
3978
3979 Queryable Encryption in older MongoDB Server versions
3980 MongoDB Server 6.0 introduced Queryable Encryption as a Public Techni‐
3981 cal Preview. MongoDB Server 7.0 includes backwards breaking changes to
3982 the Queryable Encryption protocol.
3983
3984 The backwards breaking changes are applied in the client protocol in
3985 libmongocrypt 1.8.0. libmongoc 1.24.0 requires libmongocrypt 1.8.0 or
3986 newer. libmongoc 1.24.0 no longer supports Queryable Encryption in
3987 MongoDB Server <7.0. Using Queryable Encryption libmongoc 1.24.0 and
3988 higher requires MongoDB Server >=7.0.
3989
3990 Using Queryable Encryption with libmongocrypt<1.8.0 on a MongoDB
3991 Server>=7.0, or using libmongocrypt>=1.8.0 on a MongoDB Server<6.0 will
3992 result in a server error when using the incompatible protocol.
3993
3994 SEE ALSO:
3995 The MongoDB Manual for Queryable Encryption
3996
3997
3998 Installation
3999 Using In-Use Encryption in the C driver requires the dependency libmon‐
4000 gocrypt. See the MongoDB Manual for libmongocrypt installation instruc‐
4001 tions.
4002
4003 Once libmongocrypt is installed, configure the C driver with -DEN‐
4004 ABLE_CLIENT_SIDE_ENCRYPTION=ON to require In-Use Encryption be enabled.
4005
4006 $ cd mongo-c-driver
4007 $ mkdir cmake-build && cd cmake-build
4008 $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_CLIENT_SIDE_ENCRYPTION=ON ..
4009 $ cmake --build . --target install
4010
4011 API
4012 mongoc_client_encryption_t is used for explicit encryption and key man‐
4013 agement. mongoc_client_enable_auto_encryption() and
4014 mongoc_client_pool_enable_auto_encryption() is used to enable automatic
4015 encryption.
4016
4017 The Queryable Encryption and CSFLE features share much of the same API
4018 with some exceptions.
4019
4020 • The supported algorithms documented in
4021 mongoc_client_encryption_encrypt_opts_set_algorithm() do not apply to
4022 both features.
4023
4024 • mongoc_auto_encryption_opts_set_encrypted_fields_map() only applies
4025 to Queryable Encryption.
4026
4027 • mongoc_auto_encryption_opts_set_schema_map() only applies to CSFLE.
4028
4029 Query Analysis
4030 To support the automatic encryption feature, one of the following de‐
4031 pendencies are required:
4032
4033 • The mongocryptd executable. See the MongoDB Manual documentation:
4034 Install and Configure mongocryptd
4035
4036 • The crypt_shared library. See the MongoDB Manual documentation:
4037 Automatic Encryption Shared Library
4038
4039 A mongoc_client_t or mongoc_client_pool_t configured with auto encryp‐
4040 tion will automatically try to load the crypt_shared library. If load‐
4041 ing the crypt_shared library fails, the mongoc_client_t or
4042 mongoc_client_pool_t will try to spawn the mongocryptd process from the
4043 application's PATH. To configure use of crypt_shared and mongocryptd
4044 see mongoc_auto_encryption_opts_set_extra().
4045
4047 MongoDB, Inc
4048
4050 2017-present, MongoDB, Inc
4051
4052
4053
4054
40551.24.3 Aug 17, 2023 MONGOC_GUIDES(3)