1MONGOC_GUIDES(3)               MongoDB C Driver               MONGOC_GUIDES(3)
2
3
4

NAME

6       mongoc_guides - Guides
7

COMMON TASKS

9       Drivers  for  some  other languages provide helper functions to perform
10       certain common tasks. In the C Driver we must explicitly build commands
11       to send to the server.
12
13   Setup
14       First   we'll   write   some  code  to  insert  sample  data:  doc-com‐
15       mon-insert.c.INDENT 0.0
16
17          /* Don't try to compile this file on its own. It's meant to be #included
18             by example code */
19
20          /* Insert some sample data */
21          bool
22          insert_data (mongoc_collection_t *collection)
23          {
24             mongoc_bulk_operation_t *bulk;
25             enum N { ndocs = 4 };
26             bson_t *docs[ndocs];
27             bson_error_t error;
28             int i = 0;
29             bool ret;
30
31             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
32
33             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
34             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
35             docs[2] = BCON_NEW (
36                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
37             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
38
39             for (i = 0; i < ndocs; i++) {
40                mongoc_bulk_operation_insert (bulk, docs[i]);
41                bson_destroy (docs[i]);
42                docs[i] = NULL;
43             }
44
45             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
46
47             if (!ret) {
48                fprintf (stderr, "Error inserting data: %s\n", error.message);
49             }
50
51             mongoc_bulk_operation_destroy (bulk);
52             return ret;
53          }
54
55          /* A helper which we'll use a lot later on */
56          void
57          print_res (const bson_t *reply)
58          {
59             char *str;
60             BSON_ASSERT (reply);
61             str = bson_as_canonical_extended_json (reply, NULL);
62             printf ("%s\n", str);
63             bson_free (str);
64          }
65
66
67   explain Command
68       This  is  how  to  use   the   explain   command   in   MongoDB   3.2+:
69       explain.c.INDENT 0.0
70
71          bool
72          explain (mongoc_collection_t *collection)
73          {
74             bson_t *command;
75             bson_t reply;
76             bson_error_t error;
77             bool res;
78
79             command = BCON_NEW ("explain",
80                                 "{",
81                                 "find",
82                                 BCON_UTF8 (COLLECTION_NAME),
83                                 "filter",
84                                 "{",
85                                 "x",
86                                 BCON_INT32 (1),
87                                 "}",
88                                 "}");
89             res = mongoc_collection_command_simple (
90                collection, command, NULL, &reply, &error);
91             if (!res) {
92                fprintf (stderr, "Error with explain: %s\n", error.message);
93                goto cleanup;
94             }
95
96             /* Do something with the reply */
97             print_res (&reply);
98
99          cleanup:
100             bson_destroy (&reply);
101             bson_destroy (command);
102             return res;
103          }
104
105
106   Running the Examples
107       common-operations.c.INDENT 0.0
108
109          /*
110           * Copyright 2016 MongoDB, Inc.
111           *
112           * Licensed under the Apache License, Version 2.0 (the "License");
113           * you may not use this file except in compliance with the License.
114           * You may obtain a copy of the License at
115           *
116           *   http://www.apache.org/licenses/LICENSE-2.0
117           *
118           * Unless required by applicable law or agreed to in writing, software
119           * distributed under the License is distributed on an "AS IS" BASIS,
120           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121           * See the License for the specific language governing permissions and
122           * limitations under the License.
123           */
124
125
126          #include <mongoc/mongoc.h>
127          #include <stdio.h>
128
129
130          const char *COLLECTION_NAME = "things";
131
132          #include "../doc-common-insert.c"
133          #include "explain.c"
134
135
136          int
137          main (int argc, char *argv[])
138          {
139             mongoc_database_t *database = NULL;
140             mongoc_client_t *client = NULL;
141             mongoc_collection_t *collection = NULL;
142             mongoc_uri_t *uri = NULL;
143             bson_error_t error;
144             char *host_and_port;
145             int res = 0;
146
147             if (argc < 2 || argc > 3) {
148                fprintf (stderr,
149                         "usage: %s MONGOD-1-CONNECTION-STRING "
150                         "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
151                         argv[0]);
152                fprintf (stderr,
153                         "MONGOD-1-CONNECTION-STRING can be "
154                         "of the following forms:\n");
155                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
156                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
157                fprintf (stderr,
158                         "mongodb://user:pass@localhost:27017\t"
159                         "local machine on port 27017, and authenticate with username "
160                         "user and password pass\n");
161                return EXIT_FAILURE;
162             }
163
164             mongoc_init ();
165
166             if (strncmp (argv[1], "mongodb://", 10) == 0) {
167                host_and_port = bson_strdup (argv[1]);
168             } else {
169                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
170             }
171
172             uri = mongoc_uri_new_with_error (host_and_port, &error);
173             if (!uri) {
174                fprintf (stderr,
175                         "failed to parse URI: %s\n"
176                         "error message:       %s\n",
177                         host_and_port,
178                         error.message);
179                res = EXIT_FAILURE;
180                goto cleanup;
181             }
182
183             client = mongoc_client_new_from_uri (uri);
184             if (!client) {
185                res = EXIT_FAILURE;
186                goto cleanup;
187             }
188
189             mongoc_client_set_error_api (client, 2);
190             database = mongoc_client_get_database (client, "test");
191             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
192
193             printf ("Inserting data\n");
194             if (!insert_data (collection)) {
195                res = EXIT_FAILURE;
196                goto cleanup;
197             }
198
199             printf ("explain\n");
200             if (!explain (collection)) {
201                res = EXIT_FAILURE;
202                goto cleanup;
203             }
204
205          cleanup:
206             if (collection) {
207                mongoc_collection_destroy (collection);
208             }
209
210             if (database) {
211                mongoc_database_destroy (database);
212             }
213
214             if (client) {
215                mongoc_client_destroy (client);
216             }
217
218             if (uri) {
219                mongoc_uri_destroy (uri);
220             }
221
222             bson_free (host_and_port);
223             mongoc_cleanup ();
224             return res;
225          }
226
227
228First  launch  two  separate  instances  of mongod (must be done from separate
229shells):
230
231          $ mongod
232
233          $ mkdir /tmp/db2
234          $ mongod --dbpath /tmp/db2 --port 27018 # second instance
235
236       Now compile and run the example program:
237
238          $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
239          Inserting data
240          explain
241          {
242             "executionStats" : {
243                "allPlansExecution" : [],
244                "executionStages" : {
245                   "advanced" : 19,
246                   "direction" : "forward" ,
247                   "docsExamined" : 76,
248                   "executionTimeMillisEstimate" : 0,
249                   "filter" : {
250                      "x" : {
251                         "$eq" : 1
252                      }
253                   },
254                   "invalidates" : 0,
255                   "isEOF" : 1,
256                   "nReturned" : 19,
257                   "needTime" : 58,
258                   "needYield" : 0,
259                   "restoreState" : 0,
260                   "saveState" : 0,
261                   "stage" : "COLLSCAN" ,
262                   "works" : 78
263                },
264                "executionSuccess" : true,
265                "executionTimeMillis" : 0,
266                "nReturned" : 19,
267                "totalDocsExamined" : 76,
268                "totalKeysExamined" : 0
269             },
270             "ok" : 1,
271             "queryPlanner" : {
272                "indexFilterSet" : false,
273                "namespace" : "test.things",
274                "parsedQuery" : {
275                   "x" : {
276                      "$eq" : 1
277                   }
278                },
279                "plannerVersion" : 1,
280                "rejectedPlans" : [],
281                "winningPlan" : {
282                   "direction" : "forward" ,
283                   "filter" : {
284                      "x" : {
285                         "$eq" : 1
286                      }
287                   },
288                   "stage" : "COLLSCAN"
289                }
290             },
291             "serverInfo" : {
292                "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
293                "host" : "MacBook-Pro-57.local",
294                "port" : 27017,
295                "version" : "3.2.6"
296             }
297          }
298

ADVANCED CONNECTIONS

300       The following guide contains information specific to certain  types  of
301       MongoDB configurations.
302
303       For  an  example  of  connecting to a simple standalone server, see the
304       Tutorial.  To  establish  a  connection  with  authentication   options
305       enabled, see the Authentication page.
306
307   Connecting to a Replica Set
308       Connecting  to  a  replica  set is much like connecting to a standalone
309       MongoDB server. Simply specify the replica set name using  the  ?repli‐
310       caSet=myreplset URI option.
311
312          #include <bson/bson.h>
313          #include <mongoc/mongoc.h>
314
315          int
316          main (int argc, char *argv[])
317          {
318             mongoc_client_t *client;
319
320             mongoc_init ();
321
322             /* Create our MongoDB Client */
323             client = mongoc_client_new (
324                "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");
325
326             /* Do some work */
327             /* TODO */
328
329             /* Clean up */
330             mongoc_client_destroy (client);
331             mongoc_cleanup ();
332
333             return 0;
334          }
335
336       TIP:
337          Multiple hostnames can be specified in the MongoDB connection string
338          URI, with a comma separating hosts in the seed list.
339
340          It is recommended to use a seed list of members of the  replica  set
341          to allow the driver to connect to any node.
342
343   Connecting to a Sharded Cluster
344       To  connect  to  a sharded cluster, specify the mongos nodes the client
345       should connect to. The C Driver will automatically detect that  it  has
346       connected to a mongos sharding server.
347
348       If  more than one hostname is specified, a seed list will be created to
349       attempt failover between the mongos instances.
350
351       WARNING:
352          Specifying the replicaSet parameter  when  connecting  to  a  mongos
353          sharding server is invalid.
354
355          #include <bson/bson.h>
356          #include <mongoc/mongoc.h>
357
358          int
359          main (int argc, char *argv[])
360          {
361             mongoc_client_t *client;
362
363             mongoc_init ();
364
365             /* Create our MongoDB Client */
366             client = mongoc_client_new ("mongodb://myshard01:27017/");
367
368             /* Do something with client ... */
369
370             /* Free the client */
371             mongoc_client_destroy (client);
372
373             mongoc_cleanup ();
374
375             return 0;
376          }
377
378   Connecting to an IPv6 Address
379       The  MongoDB  C  Driver  will automatically resolve IPv6 addresses from
380       host names. However, to specify an  IPv6  address  directly,  wrap  the
381       address in [].
382
383          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");
384
385   Connecting with IPv4 and IPv6
386       If  connecting  to  a hostname that has both IPv4 and IPv6 DNS records,
387       the behavior follows RFC-6555. A connection  to  the  IPv6  address  is
388       attempted  first.  If IPv6 fails, then a connection is attempted to the
389       IPv4 address. If the connection  attempt  to  IPv6  does  not  complete
390       within  250ms,  then IPv4 is tried in parallel. Whichever succeeds con‐
391       nection first cancels the other. The successful DNS  result  is  cached
392       for 10 minutes.
393
394       As  a  consequence,  attempts  to connect to a mongod only listening on
395       IPv4 may be delayed if there are both A  (IPv4)  and  AAAA  (IPv6)  DNS
396       records associated with the host.
397
398       To  avoid  a delay, configure hostnames to match the MongoDB configura‐
399       tion. That is, only create an A record if the mongod is only  listening
400       on IPv4.
401
402   Connecting to a UNIX Domain Socket
403       On  UNIX-like  systems,  the C Driver can connect directly to a MongoDB
404       server using a UNIX domain socket. Pass the  URL-encoded  path  to  the
405       socket, which must be suffixed with .sock. For example, to connect to a
406       domain socket at /tmp/mongodb-27017.sock:
407
408          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");
409
410       Include username and password like so:
411
412          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");
413
414   Connecting to a server over SSL
415       These are instructions for configuring TLS/SSL connections.
416
417       To run a server locally (on port 27017, for example):
418
419          $ mongod --port 27017 --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem
420
421       Add /?ssl=true to the end of a client URI.
422
423          mongoc_client_t *client = NULL;
424          client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true");
425
426       MongoDB requires client certificates by default, unless the --sslAllow‐
427       ConnectionsWithoutCertificates is provided. The C Driver can be config‐
428       ured to present a client certificate using a mongoc_ssl_opt_t:
429
430          const mongoc_ssl_opt_t *ssl_default = mongoc_ssl_opt_get_default ();
431          mongoc_ssl_opt_t ssl_opts = { 0 };
432
433          /* optionally copy in a custom trust directory or file; otherwise the default is used. */
434          memcpy (&ssl_opts, ssl_default, sizeof ssl_opts);
435          ssl_opts.pem_file = "client.pem"
436
437          mongoc_client_set_ssl_opts (client, &ssl_opts);
438
439       The client certificate provided by pem_file must be issued  by  one  of
440       the  server  trusted  Certificate Authorities listed in --sslCAFile, or
441       issued by a CA in the native certificate store on the server when omit‐
442       ted.
443
444       To  verify  the server certificate against a specific CA, provide a PEM
445       armored file with a CA certificate, or concatenated list of CA certifi‐
446       cates using the ca_file option, or c_rehash directory structure of CAs,
447       pointed to using the ca_dir option. When no ca_file or ca_dir  is  pro‐
448       vided, the driver will use CAs provided by the native platform certifi‐
449       cate store.
450
451       See mongoc_ssl_opt_t for more information on the  various  SSL  related
452       options.
453
454   Compressing data to and from MongoDB
455       MongoDB  3.4 added Snappy compression support, zlib compression in 3.6,
456       and zstd compression in 4.2.  To enable compression support the  client
457       must be configured with which compressors to use:
458
459          mongoc_client_t *client = NULL;
460          client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib,zstd");
461
462       The  compressors option specifies the priority order of compressors the
463       client wants to use. Messages are compressed if the client  and  server
464       share any compressors in common.
465
466       Note  that the compressor used by the server might not be the same com‐
467       pressor as the client used.  For example, if the client uses  the  con‐
468       nection  string  compressors=zlib,snappy  the client will use zlib com‐
469       pression to send data (if possible), but the server might  still  reply
470       using snappy, depending on how the server was configured.
471
472       The driver must be built with zlib and/or snappy and/or zstd support to
473       enable compression support, any unknown (or not compiled in) compressor
474       value  will be ignored. Note: to build with zstd requires cmake 3.12 or
475       higher.
476
477   Additional Connection Options
478       The full list of connection options can be found  in  the  mongoc_uri_t
479       docs.
480
481       Certain socket/connection related options are not configurable:
482
483             ┌──────────────┬─────────────────────┬─────────────────────┐
484             │Option        │ Description         │ Value               │
485             ├──────────────┼─────────────────────┼─────────────────────┤
486             │SO_KEEPALIVE  │ TCP Keep Alive      │ Enabled             │
487             ├──────────────┼─────────────────────┼─────────────────────┤
488             │TCP_KEEPIDLE  │ How  long a connec‐ │ 300 seconds         │
489             │              │ tion    needs    to │                     │
490             │              │ remain  idle before │                     │
491             │              │ TCP starts  sending │                     │
492             │              │ keepalive probes    │                     │
493             ├──────────────┼─────────────────────┼─────────────────────┤
494             │TCP_KEEPINTVL │ The time in seconds │ 10 seconds          │
495             │              │ between TCP probes  │                     │
496             ├──────────────┼─────────────────────┼─────────────────────┤
497             │TCP_KEEPCNT   │ How many probes  to │ 9 probes            │
498             │              │ send,       without │                     │
499             │              │ acknowledgement,    │                     │
500             │              │ before dropping the │                     │
501             │              │ connection          │                     │
502             ├──────────────┼─────────────────────┼─────────────────────┤
503             │TCP_NODELAY   │ Send   packets   as │ Enabled (no buffer‐ │
504             │              │ soon as possible or │ ing)                │
505             │              │ buffer small  pack‐ │                     │
506             │              │ ets   (Nagle  algo‐ │                     │
507             │              │ rithm)              │                     │
508             └──────────────┴─────────────────────┴─────────────────────┘
509

CONNECTION POOLING

511       The  MongoDB  C  driver  has  two connection modes: single-threaded and
512       pooled. Single-threaded mode is  optimized  for  embedding  the  driver
513       within  languages  like  PHP. Multi-threaded programs should use pooled
514       mode: this mode minimizes the total connection  count,  and  in  pooled
515       mode  a  background thread monitors the MongoDB server topology, so the
516       program need not block to scan it.
517
518   Single Mode
519       In single mode, your program creates a mongoc_client_t directly:
520
521          mongoc_client_t *client = mongoc_client_new (
522             "mongodb://hostA,hostB/?replicaSet=my_rs");
523
524       The client connects on demand when your program first  uses  it  for  a
525       MongoDB  operation. Using a non-blocking socket per server, it begins a
526       check on each server concurrently, and uses the  asynchronous  poll  or
527       select  function  to  receive  events  from the sockets, until all have
528       responded or timed out. Put another way, in single-threaded mode the  C
529       Driver fans out to begin all checks concurrently, then fans in once all
530       checks have completed or timed out. Once the scan completes, the client
531       executes your program's operation and returns.
532
533       In  single  mode,  the client re-scans the server topology roughly once
534       per minute. If more than a minute has elapsed since the previous  scan,
535       the  next operation on the client will block while the client completes
536       its scan. This interval is configurable  with  heartbeatFrequencyMS  in
537       the connection string. (See mongoc_uri_t.)
538
539       A single client opens one connection per server in your topology: these
540       connections are used both for scanning the topology and performing nor‐
541       mal operations.
542
543   Pooled Mode
544       To activate pooled mode, create a mongoc_client_pool_t:
545
546          mongoc_uri_t *uri = mongoc_uri_new (
547             "mongodb://hostA,hostB/?replicaSet=my_rs");
548
549          mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
550
551       When your program first calls mongoc_client_pool_pop, the pool launches
552       a background thread for monitoring. The thread fans out and connects to
553       all  servers in the connection string, using non-blocking sockets and a
554       simple event loop. As it receives ismaster responses from the  servers,
555       it  updates  its view of the server topology. Each time the thread dis‐
556       covers a new server it begins connecting to it, and adds the new socket
557       to the list of non-blocking sockets in the event loop.
558
559       Each  thread  that  executes MongoDB operations must check out a client
560       from the pool:
561
562          mongoc_client_t *client = mongoc_client_pool_pop (pool);
563
564          /* use the client for operations ... */
565
566          mongoc_client_pool_push (pool, client);
567
568       The  mongoc_client_t  object  is  not  thread-safe,   only   the   mon‐
569       goc_client_pool_t is.
570
571       When  the  driver  is  in  pooled  mode,  your program's operations are
572       unblocked as soon as monitoring discovers a usable server. For example,
573       if  a  thread  in your program is waiting to execute an "insert" on the
574       primary, it is unblocked as soon as the primary is  discovered,  rather
575       than waiting for all secondaries to be checked as well.
576
577       The  pool  opens  one  connection  per  server for monitoring, and each
578       client opens its own connection to each server it uses for  application
579       operations.  The background thread re-scans the server topology roughly
580       every 10 seconds. This interval is configurable with  heartbeatFrequen‐
581       cyMS in the connection string. (See mongoc_uri_t.)
582
583       See  connection_pool_options  to  configure pool size and behavior, and
584       see mongoc_client_pool_t for an extended example  of  a  multi-threaded
585       program that uses the driver in pooled mode.
586

CURSORS

588   Handling Cursor Failures
589       Cursors  exist on a MongoDB server. However, the mongoc_cursor_t struc‐
590       ture gives the local process a handle to the cursor. It is possible for
591       errors  to  occur on the server while iterating a cursor on the client.
592       Even a network partition may occur. This means that applications should
593       be robust in handling cursor failures.
594
595       While  iterating  cursors,  you  should  check  to  see if an error has
596       occurred. See the following example  for  how  to  robustly  check  for
597       errors.
598
599          static void
600          print_all_documents (mongoc_collection_t *collection)
601          {
602             mongoc_cursor_t *cursor;
603             const bson_t *doc;
604             bson_error_t error;
605             bson_t query = BSON_INITIALIZER;
606             char *str;
607
608             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
609
610             while (mongoc_cursor_next (cursor, &doc)) {
611                str = bson_as_canonical_extended_json (doc, NULL);
612                printf ("%s\n", str);
613                bson_free (str);
614             }
615
616             if (mongoc_cursor_error (cursor, &error)) {
617                fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
618             }
619
620             mongoc_cursor_destroy (cursor);
621          }
622
623   Destroying Server-Side Cursors
624       The  MongoDB  C  driver will automatically destroy a server-side cursor
625       when mongoc_cursor_destroy() is called. Failure to call  this  function
626       when done with a cursor will leak memory client side as well as consume
627       extra memory server side. If the cursor was configured to  never  time‐
628       out, it will become a memory leak on the server.
629
630   Tailable Cursors
631       Tailable  cursors  are  cursors  that  remain  open  even after they've
632       returned a final result. This way, if more documents  are  added  to  a
633       collection (i.e., to the cursor's result set), then you can continue to
634       call mongoc_cursor_next() to retrieve those additional results.
635
636       Here's a complete test case that demonstrates the use of tailable  cur‐
637       sors.
638
639       NOTE:
640          Tailable cursors are for capped collections only.
641
642       An  example to tail the oplog from a replica set.  mongoc-tail.c.INDENT
643       0.0
644
645          #include <bson/bson.h>
646          #include <mongoc/mongoc.h>
647          #include <stdio.h>
648          #include <stdlib.h>
649
650          #ifdef _WIN32
651          #define sleep(_n) Sleep ((_n) *1000)
652          #endif
653
654
655          static void
656          print_bson (const bson_t *b)
657          {
658             char *str;
659
660             str = bson_as_canonical_extended_json (b, NULL);
661             fprintf (stdout, "%s\n", str);
662             bson_free (str);
663          }
664
665
666          static mongoc_cursor_t *
667          query_collection (mongoc_collection_t *collection, uint32_t last_time)
668          {
669             mongoc_cursor_t *cursor;
670             bson_t query;
671             bson_t gt;
672             bson_t opts;
673
674             BSON_ASSERT (collection);
675
676             bson_init (&query);
677             BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", &gt);
678             BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
679             bson_append_document_end (&query, &gt);
680
681             bson_init (&opts);
682             BSON_APPEND_BOOL (&opts, "tailable", true);
683             BSON_APPEND_BOOL (&opts, "awaitData", true);
684
685             cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
686
687             bson_destroy (&query);
688             bson_destroy (&opts);
689
690             return cursor;
691          }
692
693
694          static void
695          tail_collection (mongoc_collection_t *collection)
696          {
697             mongoc_cursor_t *cursor;
698             uint32_t last_time;
699             const bson_t *doc;
700             bson_error_t error;
701             bson_iter_t iter;
702
703             BSON_ASSERT (collection);
704
705             last_time = (uint32_t) time (NULL);
706
707             while (true) {
708                cursor = query_collection (collection, last_time);
709                while (!mongoc_cursor_error (cursor, &error) &&
710                       mongoc_cursor_more (cursor)) {
711                   if (mongoc_cursor_next (cursor, &doc)) {
712                      if (bson_iter_init_find (&iter, doc, "ts") &&
713                          BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
714                         bson_iter_timestamp (&iter, &last_time, NULL);
715                      }
716                      print_bson (doc);
717                   }
718                }
719                if (mongoc_cursor_error (cursor, &error)) {
720                   if (error.domain == MONGOC_ERROR_SERVER) {
721                      fprintf (stderr, "%s\n", error.message);
722                      exit (1);
723                   }
724                }
725
726                mongoc_cursor_destroy (cursor);
727                sleep (1);
728             }
729          }
730
731
732          int
733          main (int argc, char *argv[])
734          {
735             mongoc_collection_t *collection;
736             mongoc_client_t *client;
737             mongoc_uri_t *uri;
738             bson_error_t error;
739
740             if (argc != 2) {
741                fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
742                return EXIT_FAILURE;
743             }
744
745             mongoc_init ();
746
747             uri = mongoc_uri_new_with_error (argv[1], &error);
748             if (!uri) {
749                fprintf (stderr,
750                         "failed to parse URI: %s\n"
751                         "error message:       %s\n",
752                         argv[1],
753                         error.message);
754                return EXIT_FAILURE;
755             }
756
757             client = mongoc_client_new_from_uri (uri);
758             if (!client) {
759                return EXIT_FAILURE;
760             }
761
762             mongoc_client_set_error_api (client, 2);
763
764             collection = mongoc_client_get_collection (client, "local", "oplog.rs");
765
766             tail_collection (collection);
767
768             mongoc_collection_destroy (collection);
769             mongoc_uri_destroy (uri);
770             mongoc_client_destroy (client);
771
772             return EXIT_SUCCESS;
773          }
774
775
776Let's compile and run this example against a replica set  to  see  updates  as
777they are made.
778
779          $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
780          $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
781          {
782              "h" : -8458503739429355503,
783              "ns" : "test.test",
784              "o" : {
785                  "_id" : {
786                      "$oid" : "5372ab0a25164be923d10d50"
787                  }
788              },
789              "op" : "i",
790              "ts" : {
791                  "$timestamp" : {
792                      "i" : 1,
793                      "t" : 1400023818
794                  }
795              },
796              "v" : 2
797          }
798
799       The  line of output is a sample from performing db.test.insert({}) from
800       the mongo shell on the replica set.
801
802       See also mongoc_cursor_set_max_await_time_ms.
803

BULK WRITE OPERATIONS

805       This tutorial explains how to take advantage of MongoDB C  driver  bulk
806       write operation features. Executing write operations in batches reduces
807       the number of network round trips, increasing write throughput.
808
809   Bulk Insert
810       First we need to fetch a bulk operation handle from the  mongoc_collec‐
811       tion_t.
812
813          mongoc_bulk_operation_t *bulk =
814             mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
815
816       We  can now start inserting documents to the bulk operation. These will
817       be buffered until we execute the operation.
818
819       The bulk operation will coalesce insertions as a single batch for  each
820       consecutive  call  to  mongoc_bulk_operation_insert().  This  creates a
821       pipelined effect when possible.
822
823       To execute the bulk operation and  receive  the  result  we  call  mon‐
824       goc_bulk_operation_execute().  bulk1.c.INDENT 0.0
825
826          #include <assert.h>
827          #include <mongoc/mongoc.h>
828          #include <stdio.h>
829
830          static void
831          bulk1 (mongoc_collection_t *collection)
832          {
833             mongoc_bulk_operation_t *bulk;
834             bson_error_t error;
835             bson_t *doc;
836             bson_t reply;
837             char *str;
838             bool ret;
839             int i;
840
841             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
842
843             for (i = 0; i < 10000; i++) {
844                doc = BCON_NEW ("i", BCON_INT32 (i));
845                mongoc_bulk_operation_insert (bulk, doc);
846                bson_destroy (doc);
847             }
848
849             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
850
851             str = bson_as_canonical_extended_json (&reply, NULL);
852             printf ("%s\n", str);
853             bson_free (str);
854
855             if (!ret) {
856                fprintf (stderr, "Error: %s\n", error.message);
857             }
858
859             bson_destroy (&reply);
860             mongoc_bulk_operation_destroy (bulk);
861          }
862
863          int
864          main (int argc, char *argv[])
865          {
866             mongoc_client_t *client;
867             mongoc_collection_t *collection;
868             const char *uri_string = "mongodb://localhost/?appname=bulk1-example";
869             mongoc_uri_t *uri;
870             bson_error_t error;
871
872             mongoc_init ();
873
874             uri = mongoc_uri_new_with_error (uri_string, &error);
875             if (!uri) {
876                fprintf (stderr,
877                         "failed to parse URI: %s\n"
878                         "error message:       %s\n",
879                         uri_string,
880                         error.message);
881                return EXIT_FAILURE;
882             }
883
884             client = mongoc_client_new_from_uri (uri);
885             if (!client) {
886                return EXIT_FAILURE;
887             }
888
889             mongoc_client_set_error_api (client, 2);
890             collection = mongoc_client_get_collection (client, "test", "test");
891
892             bulk1 (collection);
893
894             mongoc_uri_destroy (uri);
895             mongoc_collection_destroy (collection);
896             mongoc_client_destroy (client);
897
898             mongoc_cleanup ();
899
900             return EXIT_SUCCESS;
901          }
902
903
904Example reply document:
905
906          {"nInserted"   : 10000,
907           "nMatched"    : 0,
908           "nModified"   : 0,
909           "nRemoved"    : 0,
910           "nUpserted"   : 0,
911           "writeErrors" : []
912           "writeConcernErrors" : [] }
913
914   Mixed Bulk Write Operations
915       MongoDB C driver also supports executing mixed bulk write operations. A
916       batch of insert, update, and remove operations can be executed together
917       using the bulk write operations API.
918
919   Ordered Bulk Write Operations
920       Ordered bulk write operations are batched and sent to the server in the
921       order provided for serial execution. The reply document  describes  the
922       type and count of operations performed.  bulk2.c.INDENT 0.0
923
924          #include <assert.h>
925          #include <mongoc/mongoc.h>
926          #include <stdio.h>
927
928          static void
929          bulk2 (mongoc_collection_t *collection)
930          {
931             mongoc_bulk_operation_t *bulk;
932             bson_error_t error;
933             bson_t *query;
934             bson_t *doc;
935             bson_t *opts;
936             bson_t reply;
937             char *str;
938             bool ret;
939             int i;
940
941             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
942
943             /* Remove everything */
944             query = bson_new ();
945             mongoc_bulk_operation_remove (bulk, query);
946             bson_destroy (query);
947
948             /* Add a few documents */
949             for (i = 1; i < 4; i++) {
950                doc = BCON_NEW ("_id", BCON_INT32 (i));
951                mongoc_bulk_operation_insert (bulk, doc);
952                bson_destroy (doc);
953             }
954
955             /* {_id: 1} => {$set: {foo: "bar"}} */
956             query = BCON_NEW ("_id", BCON_INT32 (1));
957             doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
958             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
959             bson_destroy (query);
960             bson_destroy (doc);
961
962             /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
963             opts = BCON_NEW ("upsert", BCON_BOOL (true));
964             query = BCON_NEW ("_id", BCON_INT32 (4));
965             doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
966             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
967             bson_destroy (query);
968             bson_destroy (doc);
969             bson_destroy (opts);
970
971             /* replace {j:1} with {j:2} */
972             query = BCON_NEW ("j", BCON_INT32 (1));
973             doc = BCON_NEW ("j", BCON_INT32 (2));
974             mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
975             bson_destroy (query);
976             bson_destroy (doc);
977
978             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
979
980             str = bson_as_canonical_extended_json (&reply, NULL);
981             printf ("%s\n", str);
982             bson_free (str);
983
984             if (!ret) {
985                printf ("Error: %s\n", error.message);
986             }
987
988             bson_destroy (&reply);
989             mongoc_bulk_operation_destroy (bulk);
990          }
991
992          int
993          main (int argc, char *argv[])
994          {
995             mongoc_client_t *client;
996             mongoc_collection_t *collection;
997             const char *uri_string = "mongodb://localhost/?appname=bulk2-example";
998             mongoc_uri_t *uri;
999             bson_error_t error;
1000
1001             mongoc_init ();
1002
1003             uri = mongoc_uri_new_with_error (uri_string, &error);
1004             if (!uri) {
1005                fprintf (stderr,
1006                         "failed to parse URI: %s\n"
1007                         "error message:       %s\n",
1008                         uri_string,
1009                         error.message);
1010                return EXIT_FAILURE;
1011             }
1012
1013             client = mongoc_client_new_from_uri (uri);
1014             if (!client) {
1015                return EXIT_FAILURE;
1016             }
1017
1018             mongoc_client_set_error_api (client, 2);
1019             collection = mongoc_client_get_collection (client, "test", "test");
1020
1021             bulk2 (collection);
1022
1023             mongoc_uri_destroy (uri);
1024             mongoc_collection_destroy (collection);
1025             mongoc_client_destroy (client);
1026
1027             mongoc_cleanup ();
1028
1029             return EXIT_SUCCESS;
1030          }
1031
1032
1033Example reply document:
1034
1035          { "nInserted"   : 3,
1036            "nMatched"    : 2,
1037            "nModified"   : 2,
1038            "nRemoved"    : 10000,
1039            "nUpserted"   : 1,
1040            "upserted"    : [{"index" : 5, "_id" : 4}],
1041            "writeErrors" : []
1042            "writeConcernErrors" : [] }
1043
1044       The  index  field  in  the  upserted  array is the 0-based index of the
1045       upsert operation; in this example, the sixth operation of  the  overall
1046       bulk operation was an upsert, so its index is 5.
1047
1048   Unordered Bulk Write Operations
1049       Unordered  bulk  write operations are batched and sent to the server in
1050       arbitrary order where they may be executed in parallel. Any errors that
1051       occur are reported after all operations are attempted.
1052
1053       In  the  next  example  the  first and third operations fail due to the
1054       unique constraint on _id. Since we are doing  unordered  execution  the
1055       second and fourth operations succeed.  bulk3.c.INDENT 0.0
1056
1057          #include <assert.h>
1058          #include <mongoc/mongoc.h>
1059          #include <stdio.h>
1060
1061          static void
1062          bulk3 (mongoc_collection_t *collection)
1063          {
1064             bson_t opts = BSON_INITIALIZER;
1065             mongoc_bulk_operation_t *bulk;
1066             bson_error_t error;
1067             bson_t *query;
1068             bson_t *doc;
1069             bson_t reply;
1070             char *str;
1071             bool ret;
1072
1073             /* false indicates unordered */
1074             BSON_APPEND_BOOL (&opts, "ordered", false);
1075             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
1076             bson_destroy (&opts);
1077
1078             /* Add a document */
1079             doc = BCON_NEW ("_id", BCON_INT32 (1));
1080             mongoc_bulk_operation_insert (bulk, doc);
1081             bson_destroy (doc);
1082
1083             /* remove {_id: 2} */
1084             query = BCON_NEW ("_id", BCON_INT32 (2));
1085             mongoc_bulk_operation_remove_one (bulk, query);
1086             bson_destroy (query);
1087
1088             /* insert {_id: 3} */
1089             doc = BCON_NEW ("_id", BCON_INT32 (3));
1090             mongoc_bulk_operation_insert (bulk, doc);
1091             bson_destroy (doc);
1092
1093             /* replace {_id:4} {'i': 1} */
1094             query = BCON_NEW ("_id", BCON_INT32 (4));
1095             doc = BCON_NEW ("i", BCON_INT32 (1));
1096             mongoc_bulk_operation_replace_one (bulk, query, doc, false);
1097             bson_destroy (query);
1098             bson_destroy (doc);
1099
1100             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1101
1102             str = bson_as_canonical_extended_json (&reply, NULL);
1103             printf ("%s\n", str);
1104             bson_free (str);
1105
1106             if (!ret) {
1107                printf ("Error: %s\n", error.message);
1108             }
1109
1110             bson_destroy (&reply);
1111             mongoc_bulk_operation_destroy (bulk);
1112             bson_destroy (&opts);
1113          }
1114
1115          int
1116          main (int argc, char *argv[])
1117          {
1118             mongoc_client_t *client;
1119             mongoc_collection_t *collection;
1120             const char *uri_string = "mongodb://localhost/?appname=bulk3-example";
1121             mongoc_uri_t *uri;
1122             bson_error_t error;
1123
1124             mongoc_init ();
1125
1126             uri = mongoc_uri_new_with_error (uri_string, &error);
1127             if (!uri) {
1128                fprintf (stderr,
1129                         "failed to parse URI: %s\n"
1130                         "error message:       %s\n",
1131                         uri_string,
1132                         error.message);
1133                return EXIT_FAILURE;
1134             }
1135
1136             client = mongoc_client_new_from_uri (uri);
1137             if (!client) {
1138                return EXIT_FAILURE;
1139             }
1140
1141             mongoc_client_set_error_api (client, 2);
1142             collection = mongoc_client_get_collection (client, "test", "test");
1143
1144             bulk3 (collection);
1145
1146             mongoc_uri_destroy (uri);
1147             mongoc_collection_destroy (collection);
1148             mongoc_client_destroy (client);
1149
1150             mongoc_cleanup ();
1151
1152             return EXIT_SUCCESS;
1153          }
1154
1155
1156Example reply document:
1157
1158          { "nInserted"    : 0,
1159            "nMatched"     : 1,
1160            "nModified"    : 1,
1161            "nRemoved"     : 1,
1162            "nUpserted"    : 0,
1163            "writeErrors"  : [
1164              { "index"  : 0,
1165                "code"   : 11000,
1166                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
1167              { "index"  : 2,
1168                "code"   : 11000,
1169                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
1170            "writeConcernErrors" : [] }
1171
1172          Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }
1173
1174       The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.
1175
1176   Bulk Operation Bypassing Document Validation
1177       This feature is only available when using MongoDB 3.2 and later.
1178
1179       By  default bulk operations are validated against the schema, if any is
1180       defined. In certain cases however it may be  necessary  to  bypass  the
1181       document validation.  bulk5.c.INDENT 0.0
1182
1183          #include <assert.h>
1184          #include <mongoc/mongoc.h>
1185          #include <stdio.h>
1186
1187          static void
1188          bulk5_fail (mongoc_collection_t *collection)
1189          {
1190             mongoc_bulk_operation_t *bulk;
1191             bson_error_t error;
1192             bson_t *doc;
1193             bson_t reply;
1194             char *str;
1195             bool ret;
1196
1197             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1198
1199             /* Two inserts */
1200             doc = BCON_NEW ("_id", BCON_INT32 (31));
1201             mongoc_bulk_operation_insert (bulk, doc);
1202             bson_destroy (doc);
1203
1204             doc = BCON_NEW ("_id", BCON_INT32 (32));
1205             mongoc_bulk_operation_insert (bulk, doc);
1206             bson_destroy (doc);
1207
1208             /* The above documents do not comply to the schema validation rules
1209              * we created previously, so this will result in an error */
1210             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1211
1212             str = bson_as_canonical_extended_json (&reply, NULL);
1213             printf ("%s\n", str);
1214             bson_free (str);
1215
1216             if (!ret) {
1217                printf ("Error: %s\n", error.message);
1218             }
1219
1220             bson_destroy (&reply);
1221             mongoc_bulk_operation_destroy (bulk);
1222          }
1223
1224          static void
1225          bulk5_success (mongoc_collection_t *collection)
1226          {
1227             mongoc_bulk_operation_t *bulk;
1228             bson_error_t error;
1229             bson_t *doc;
1230             bson_t reply;
1231             char *str;
1232             bool ret;
1233
1234             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1235
1236             /* Allow this document to bypass document validation.
1237              * NOTE: When authentication is enabled, the authenticated user must have
1238              * either the "dbadmin" or "restore" roles to bypass document validation */
1239             mongoc_bulk_operation_set_bypass_document_validation (bulk, true);
1240
1241             /* Two inserts */
1242             doc = BCON_NEW ("_id", BCON_INT32 (31));
1243             mongoc_bulk_operation_insert (bulk, doc);
1244             bson_destroy (doc);
1245
1246             doc = BCON_NEW ("_id", BCON_INT32 (32));
1247             mongoc_bulk_operation_insert (bulk, doc);
1248             bson_destroy (doc);
1249
1250             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1251
1252             str = bson_as_canonical_extended_json (&reply, NULL);
1253             printf ("%s\n", str);
1254             bson_free (str);
1255
1256             if (!ret) {
1257                printf ("Error: %s\n", error.message);
1258             }
1259
1260             bson_destroy (&reply);
1261             mongoc_bulk_operation_destroy (bulk);
1262          }
1263
1264          int
1265          main (int argc, char *argv[])
1266          {
1267             bson_t *options;
1268             bson_error_t error;
1269             mongoc_client_t *client;
1270             mongoc_collection_t *collection;
1271             mongoc_database_t *database;
1272             const char *uri_string = "mongodb://localhost/?appname=bulk5-example";
1273             mongoc_uri_t *uri;
1274
1275             mongoc_init ();
1276
1277             uri = mongoc_uri_new_with_error (uri_string, &error);
1278             if (!uri) {
1279                fprintf (stderr,
1280                         "failed to parse URI: %s\n"
1281                         "error message:       %s\n",
1282                         uri_string,
1283                         error.message);
1284                return EXIT_FAILURE;
1285             }
1286
1287             client = mongoc_client_new_from_uri (uri);
1288             if (!client) {
1289                return EXIT_FAILURE;
1290             }
1291
1292             mongoc_client_set_error_api (client, 2);
1293             database = mongoc_client_get_database (client, "testasdf");
1294
1295             /* Create schema validator */
1296             options = BCON_NEW (
1297                "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
1298             collection =
1299                mongoc_database_create_collection (database, "collname", options, &error);
1300
1301             if (collection) {
1302                bulk5_fail (collection);
1303                bulk5_success (collection);
1304                mongoc_collection_destroy (collection);
1305             } else {
1306                fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
1307             }
1308
1309             bson_free (options);
1310             mongoc_uri_destroy (uri);
1311             mongoc_database_destroy (database);
1312             mongoc_client_destroy (client);
1313
1314             mongoc_cleanup ();
1315
1316             return EXIT_SUCCESS;
1317          }
1318
1319
1320Running the above example will result in:
1321
1322          { "nInserted" : 0,
1323            "nMatched" : 0,
1324            "nModified" : 0,
1325            "nRemoved" : 0,
1326            "nUpserted" : 0,
1327            "writeErrors" : [
1328              { "index" : 0,
1329                "code" : 121,
1330                "errmsg" : "Document failed validation" } ] }
1331
1332          Error: Document failed validation
1333
1334          { "nInserted" : 2,
1335            "nMatched" : 0,
1336            "nModified" : 0,
1337            "nRemoved" : 0,
1338            "nUpserted" : 0,
1339            "writeErrors" : [] }
1340
1341       The bson_error_t domain is MONGOC_ERROR_COMMAND.
1342
1343   Bulk Operation Write Concerns
1344       By  default  bulk operations are executed with the write_concern of the
1345       collection they are executed against. A custom  write  concern  can  be
1346       passed   to   the   mongoc_collection_create_bulk_operation_with_opts()
1347       method. Write concern errors (e.g. wtimeout) will be reported after all
1348       operations    are    attempted,    regardless   of   execution   order.
1349       bulk4.c.INDENT 0.0
1350
1351          #include <assert.h>
1352          #include <mongoc/mongoc.h>
1353          #include <stdio.h>
1354
1355          static void
1356          bulk4 (mongoc_collection_t *collection)
1357          {
1358             bson_t opts = BSON_INITIALIZER;
1359             mongoc_write_concern_t *wc;
1360             mongoc_bulk_operation_t *bulk;
1361             bson_error_t error;
1362             bson_t *doc;
1363             bson_t reply;
1364             char *str;
1365             bool ret;
1366
1367             wc = mongoc_write_concern_new ();
1368             mongoc_write_concern_set_w (wc, 4);
1369             mongoc_write_concern_set_wtimeout_int64 (wc, 100); /* milliseconds */
1370             mongoc_write_concern_append (wc, &opts);
1371
1372             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
1373
1374             /* Two inserts */
1375             doc = BCON_NEW ("_id", BCON_INT32 (10));
1376             mongoc_bulk_operation_insert (bulk, doc);
1377             bson_destroy (doc);
1378
1379             doc = BCON_NEW ("_id", BCON_INT32 (11));
1380             mongoc_bulk_operation_insert (bulk, doc);
1381             bson_destroy (doc);
1382
1383             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1384
1385             str = bson_as_canonical_extended_json (&reply, NULL);
1386             printf ("%s\n", str);
1387             bson_free (str);
1388
1389             if (!ret) {
1390                printf ("Error: %s\n", error.message);
1391             }
1392
1393             bson_destroy (&reply);
1394             mongoc_bulk_operation_destroy (bulk);
1395             mongoc_write_concern_destroy (wc);
1396             bson_destroy (&opts);
1397          }
1398
1399          int
1400          main (int argc, char *argv[])
1401          {
1402             mongoc_client_t *client;
1403             mongoc_collection_t *collection;
1404             const char *uri_string = "mongodb://localhost/?appname=bulk4-example";
1405             mongoc_uri_t *uri;
1406             bson_error_t error;
1407
1408             mongoc_init ();
1409
1410             uri = mongoc_uri_new_with_error (uri_string, &error);
1411             if (!uri) {
1412                fprintf (stderr,
1413                         "failed to parse URI: %s\n"
1414                         "error message:       %s\n",
1415                         uri_string,
1416                         error.message);
1417                return EXIT_FAILURE;
1418             }
1419
1420             client = mongoc_client_new_from_uri (uri);
1421             if (!client) {
1422                return EXIT_FAILURE;
1423             }
1424
1425             mongoc_client_set_error_api (client, 2);
1426             collection = mongoc_client_get_collection (client, "test", "test");
1427
1428             bulk4 (collection);
1429
1430             mongoc_uri_destroy (uri);
1431             mongoc_collection_destroy (collection);
1432             mongoc_client_destroy (client);
1433
1434             mongoc_cleanup ();
1435
1436             return EXIT_SUCCESS;
1437          }
1438
1439
1440Example reply document and error message:
1441
1442          { "nInserted"    : 2,
1443            "nMatched"     : 0,
1444            "nModified"    : 0,
1445            "nRemoved"     : 0,
1446            "nUpserted"    : 0,
1447            "writeErrors"  : [],
1448            "writeConcernErrors" : [
1449              { "code"   : 64,
1450                "errmsg" : "waiting for replication timed out" }
1451          ] }
1452
1453          Error: waiting for replication timed out
1454
1455       The bson_error_t domain  is  MONGOC_ERROR_WRITE_CONCERN  if  there  are
1456       write  concern errors and no write errors. Write errors indicate failed
1457       operations, so they take precedence over write  concern  errors,  which
1458       mean merely that the write concern is not satisfied yet.
1459
1460   Setting Collation Order
1461       This  feature  is  only  available  when  using  MongoDB 3.4 and later.
1462       bulk-collation.c.INDENT 0.0
1463
1464          #include <mongoc/mongoc.h>
1465          #include <stdio.h>
1466
1467          static void
1468          bulk_collation (mongoc_collection_t *collection)
1469          {
1470             mongoc_bulk_operation_t *bulk;
1471             bson_t *opts;
1472             bson_t *doc;
1473             bson_t *selector;
1474             bson_t *update;
1475             bson_error_t error;
1476             bson_t reply;
1477             char *str;
1478             uint32_t ret;
1479
1480             /* insert {_id: "one"} and {_id: "One"} */
1481             bulk = mongoc_collection_create_bulk_operation_with_opts (
1482                collection, NULL);
1483             doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
1484             mongoc_bulk_operation_insert (bulk, doc);
1485             bson_destroy (doc);
1486
1487             doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
1488             mongoc_bulk_operation_insert (bulk, doc);
1489             bson_destroy (doc);
1490
1491             /* "One" normally sorts before "one"; make "one" come first */
1492             opts = BCON_NEW ("collation",
1493                              "{",
1494                              "locale",
1495                              BCON_UTF8 ("en_US"),
1496                              "caseFirst",
1497                              BCON_UTF8 ("lower"),
1498                              "}");
1499
1500             /* set x=1 on the document with _id "One", which now sorts after "one" */
1501             update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
1502             selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
1503             mongoc_bulk_operation_update_one_with_opts (
1504                bulk, selector, update, opts, &error);
1505
1506             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1507
1508             str = bson_as_canonical_extended_json (&reply, NULL);
1509             printf ("%s\n", str);
1510             bson_free (str);
1511
1512             if (!ret) {
1513                printf ("Error: %s\n", error.message);
1514             }
1515
1516             bson_destroy (&reply);
1517             bson_destroy (update);
1518             bson_destroy (selector);
1519             bson_destroy (opts);
1520             mongoc_bulk_operation_destroy (bulk);
1521          }
1522
1523          int
1524          main (int argc, char *argv[])
1525          {
1526             mongoc_client_t *client;
1527             mongoc_collection_t *collection;
1528             const char *uri_string = "mongodb://localhost/?appname=bulk-collation";
1529             mongoc_uri_t *uri;
1530             bson_error_t error;
1531
1532             mongoc_init ();
1533
1534             uri = mongoc_uri_new_with_error (uri_string, &error);
1535             if (!uri) {
1536                fprintf (stderr,
1537                         "failed to parse URI: %s\n"
1538                         "error message:       %s\n",
1539                         uri_string,
1540                         error.message);
1541                return EXIT_FAILURE;
1542             }
1543
1544             client = mongoc_client_new_from_uri (uri);
1545             if (!client) {
1546                return EXIT_FAILURE;
1547             }
1548
1549             mongoc_client_set_error_api (client, 2);
1550             collection = mongoc_client_get_collection (client, "db", "collection");
1551             bulk_collation (collection);
1552
1553             mongoc_uri_destroy (uri);
1554             mongoc_collection_destroy (collection);
1555             mongoc_client_destroy (client);
1556
1557             mongoc_cleanup ();
1558
1559             return EXIT_SUCCESS;
1560          }
1561
1562
1563Running the above example will result in:
1564
1565          { "nInserted" : 2,
1566             "nMatched" : 1,
1567             "nModified" : 1,
1568             "nRemoved" : 0,
1569             "nUpserted" : 0,
1570             "writeErrors" : [  ]
1571          }
1572
1573   Unacknowledged Bulk Writes
1574       Set "w" to zero for an unacknowledged write.  The  driver  sends  unac‐
1575       knowledged  writes  using  the legacy opcodes OP_INSERT, OP_UPDATE, and
1576       OP_DELETE.  bulk6.c.INDENT 0.0
1577
1578          #include <mongoc/mongoc.h>
1579          #include <stdio.h>
1580
1581          static void
1582          bulk6 (mongoc_collection_t *collection)
1583          {
1584             bson_t opts = BSON_INITIALIZER;
1585             mongoc_write_concern_t *wc;
1586             mongoc_bulk_operation_t *bulk;
1587             bson_error_t error;
1588             bson_t *doc;
1589             bson_t *selector;
1590             bson_t reply;
1591             char *str;
1592             bool ret;
1593
1594             wc = mongoc_write_concern_new ();
1595             mongoc_write_concern_set_w (wc, 0);
1596             mongoc_write_concern_append (wc, &opts);
1597
1598             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
1599
1600             doc = BCON_NEW ("_id", BCON_INT32 (10));
1601             mongoc_bulk_operation_insert (bulk, doc);
1602             bson_destroy (doc);
1603
1604             selector = BCON_NEW ("_id", BCON_INT32 (11));
1605             mongoc_bulk_operation_remove_one (bulk, selector);
1606             bson_destroy (selector);
1607
1608             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
1609
1610             str = bson_as_canonical_extended_json (&reply, NULL);
1611             printf ("%s\n", str);
1612             bson_free (str);
1613
1614             if (!ret) {
1615                printf ("Error: %s\n", error.message);
1616             }
1617
1618             bson_destroy (&reply);
1619             mongoc_bulk_operation_destroy (bulk);
1620             mongoc_write_concern_destroy (wc);
1621             bson_destroy (&opts);
1622          }
1623
1624          int
1625          main (int argc, char *argv[])
1626          {
1627             mongoc_client_t *client;
1628             mongoc_collection_t *collection;
1629             const char *uri_string = "mongodb://localhost/?appname=bulk6-example";
1630             mongoc_uri_t *uri;
1631             bson_error_t error;
1632
1633             mongoc_init ();
1634
1635             uri = mongoc_uri_new_with_error (uri_string, &error);
1636             if (!uri) {
1637                fprintf (stderr,
1638                         "failed to parse URI: %s\n"
1639                         "error message:       %s\n",
1640                         uri_string,
1641                         error.message);
1642                return EXIT_FAILURE;
1643             }
1644
1645             client = mongoc_client_new_from_uri (uri);
1646             if (!client) {
1647                return EXIT_FAILURE;
1648             }
1649
1650             mongoc_client_set_error_api (client, 2);
1651             collection = mongoc_client_get_collection (client, "test", "test");
1652
1653             bulk6 (collection);
1654
1655             mongoc_uri_destroy (uri);
1656             mongoc_collection_destroy (collection);
1657             mongoc_client_destroy (client);
1658
1659             mongoc_cleanup ();
1660
1661             return EXIT_SUCCESS;
1662          }
1663
1664
1665The reply document is empty:
1666
1667          { }
1668
1669   Further Reading
1670       See the Driver Bulk API Spec, which describes bulk write operations for
1671       all MongoDB drivers.
1672

AGGREGATION FRAMEWORK EXAMPLES

1674       This  document provides a number of practical examples that display the
1675       capabilities of the aggregation framework.
1676
1677       The Aggregations using the Zip Codes Data Set examples uses a  publicly
1678       available  data  set  of  all  zipcodes  and  populations in the United
1679       States. These data are available at: zips.json.
1680
1681   Requirements
1682       Let's check if everything is installed.
1683
1684       Use the following command  to  load  zips.json  data  set  into  mongod
1685       instance:
1686
1687          $ mongoimport --drop -d test -c zipcodes zips.json
1688
1689       Let's use the MongoDB shell to verify that everything was imported suc‐
1690       cessfully.
1691
1692          $ mongo test
1693          connecting to: test
1694          > db.zipcodes.count()
1695          29467
1696          > db.zipcodes.findOne()
1697          {
1698                "_id" : "35004",
1699                "city" : "ACMAR",
1700                "loc" : [
1701                        -86.51557,
1702                        33.584132
1703                ],
1704                "pop" : 6055,
1705                "state" : "AL"
1706          }
1707
1708   Aggregations using the Zip Codes Data Set
1709       Each document in this collection has the following form:
1710
1711          {
1712            "_id" : "35004",
1713            "city" : "Acmar",
1714            "state" : "AL",
1715            "pop" : 6055,
1716            "loc" : [-86.51557, 33.584132]
1717          }
1718
1719       In these documents:
1720
1721       · The _id field holds the zipcode as a string.
1722
1723       · The city field holds the city name.
1724
1725       · The state field holds the two letter state abbreviation.
1726
1727       · The pop field holds the population.
1728
1729       · The loc field holds the location as a [latitude, longitude] array.
1730
1731   States with Populations Over 10 Million
1732       To get all states with a population greater than 10  million,  use  the
1733       following aggregation pipeline: aggregation1.c.INDENT 0.0
1734
1735          #include <mongoc/mongoc.h>
1736          #include <stdio.h>
1737
1738          static void
1739          print_pipeline (mongoc_collection_t *collection)
1740          {
1741             mongoc_cursor_t *cursor;
1742             bson_error_t error;
1743             const bson_t *doc;
1744             bson_t *pipeline;
1745             char *str;
1746
1747             pipeline = BCON_NEW ("pipeline",
1748                                  "[",
1749                                  "{",
1750                                  "$group",
1751                                  "{",
1752                                  "_id",
1753                                  "$state",
1754                                  "total_pop",
1755                                  "{",
1756                                  "$sum",
1757                                  "$pop",
1758                                  "}",
1759                                  "}",
1760                                  "}",
1761                                  "{",
1762                                  "$match",
1763                                  "{",
1764                                  "total_pop",
1765                                  "{",
1766                                  "$gte",
1767                                  BCON_INT32 (10000000),
1768                                  "}",
1769                                  "}",
1770                                  "}",
1771                                  "]");
1772
1773             cursor = mongoc_collection_aggregate (
1774                collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
1775
1776             while (mongoc_cursor_next (cursor, &doc)) {
1777                str = bson_as_canonical_extended_json (doc, NULL);
1778                printf ("%s\n", str);
1779                bson_free (str);
1780             }
1781
1782             if (mongoc_cursor_error (cursor, &error)) {
1783                fprintf (stderr, "Cursor Failure: %s\n", error.message);
1784             }
1785
1786             mongoc_cursor_destroy (cursor);
1787             bson_destroy (pipeline);
1788          }
1789
1790          int
1791          main (int argc, char *argv[])
1792          {
1793             mongoc_client_t *client;
1794             mongoc_collection_t *collection;
1795             const char *uri_string =
1796                "mongodb://localhost:27017/?appname=aggregation-example";
1797             mongoc_uri_t *uri;
1798             bson_error_t error;
1799
1800             mongoc_init ();
1801
1802             uri = mongoc_uri_new_with_error (uri_string, &error);
1803             if (!uri) {
1804                fprintf (stderr,
1805                         "failed to parse URI: %s\n"
1806                         "error message:       %s\n",
1807                         uri_string,
1808                         error.message);
1809                return EXIT_FAILURE;
1810             }
1811
1812             client = mongoc_client_new_from_uri (uri);
1813             if (!client) {
1814                return EXIT_FAILURE;
1815             }
1816
1817             mongoc_client_set_error_api (client, 2);
1818             collection = mongoc_client_get_collection (client, "test", "zipcodes");
1819
1820             print_pipeline (collection);
1821
1822             mongoc_uri_destroy (uri);
1823             mongoc_collection_destroy (collection);
1824             mongoc_client_destroy (client);
1825
1826             mongoc_cleanup ();
1827
1828             return EXIT_SUCCESS;
1829          }
1830
1831
1832You should see a result like the following:
1833
1834          { "_id" : "PA", "total_pop" : 11881643 }
1835          { "_id" : "OH", "total_pop" : 10847115 }
1836          { "_id" : "NY", "total_pop" : 17990455 }
1837          { "_id" : "FL", "total_pop" : 12937284 }
1838          { "_id" : "TX", "total_pop" : 16986510 }
1839          { "_id" : "IL", "total_pop" : 11430472 }
1840          { "_id" : "CA", "total_pop" : 29760021 }
1841
1842       The  above  aggregation  pipeline is build from two pipeline operators:
1843       $group and $match.
1844
1845       The $group pipeline operator requires _id field where we specify group‐
1846       ing;  remaining fields specify how to generate composite value and must
1847       use one of the group aggregation functions: $addToSet,  $first,  $last,
1848       $max,  $min,  $avg, $push, $sum. The $match pipeline operator syntax is
1849       the same as the read operation query syntax.
1850
1851       The $group process reads all documents and for each state it creates  a
1852       separate document, for example:
1853
1854          { "_id" : "WA", "total_pop" : 4866692 }
1855
1856       The  total_pop field uses the $sum aggregation function to sum the val‐
1857       ues of all pop fields in the source documents.
1858
1859       Documents created by $group are piped to the $match pipeline  operator.
1860       It returns the documents with the value of total_pop field greater than
1861       or equal to 10 million.
1862
1863   Average City Population by State
1864       To get the first three states with the greatest average population  per
1865       city, use the following aggregation:
1866
1867          pipeline = BCON_NEW ("pipeline", "[",
1868             "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
1869             "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
1870             "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
1871             "{", "$limit", BCON_INT32 (3) "}",
1872          "]");
1873
1874       This aggregate pipeline produces:
1875
1876          { "_id" : "DC", "avg_city_pop" : 303450.0 }
1877          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
1878          { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
1879
1880       The  above aggregation pipeline is build from three pipeline operators:
1881       $group, $sort and $limit.
1882
1883       The first $group operator creates the following documents:
1884
1885          { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
1886
1887       Note, that the $group operator can't use nested  documents  except  the
1888       _id field.
1889
1890       The  second  $group  uses these documents to create the following docu‐
1891       ments:
1892
1893          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
1894
1895       These documents are sorted by  the  avg_city_pop  field  in  descending
1896       order.  Finally, the $limit pipeline operator returns the first 3 docu‐
1897       ments from the sorted set.
1898

DISTINCT AND MAPREDUCE

1900       This document provides some practical, simple, examples to  demonstrate
1901       the distinct and mapReduce commands.
1902
1903   Setup
1904       First   we'll   write   some  code  to  insert  sample  data:  doc-com‐
1905       mon-insert.c.INDENT 0.0
1906
1907          /* Don't try to compile this file on its own. It's meant to be #included
1908             by example code */
1909
1910          /* Insert some sample data */
1911          bool
1912          insert_data (mongoc_collection_t *collection)
1913          {
1914             mongoc_bulk_operation_t *bulk;
1915             enum N { ndocs = 4 };
1916             bson_t *docs[ndocs];
1917             bson_error_t error;
1918             int i = 0;
1919             bool ret;
1920
1921             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1922
1923             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
1924             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
1925             docs[2] = BCON_NEW (
1926                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
1927             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
1928
1929             for (i = 0; i < ndocs; i++) {
1930                mongoc_bulk_operation_insert (bulk, docs[i]);
1931                bson_destroy (docs[i]);
1932                docs[i] = NULL;
1933             }
1934
1935             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
1936
1937             if (!ret) {
1938                fprintf (stderr, "Error inserting data: %s\n", error.message);
1939             }
1940
1941             mongoc_bulk_operation_destroy (bulk);
1942             return ret;
1943          }
1944
1945          /* A helper which we'll use a lot later on */
1946          void
1947          print_res (const bson_t *reply)
1948          {
1949             char *str;
1950             BSON_ASSERT (reply);
1951             str = bson_as_canonical_extended_json (reply, NULL);
1952             printf ("%s\n", str);
1953             bson_free (str);
1954          }
1955
1956
1957   distinct command
1958       This is how to use the distinct command to get the distinct values of x
1959       which are greater than 1: distinct.c.INDENT 0.0
1960
1961          bool
1962          distinct (mongoc_database_t *database)
1963          {
1964             bson_t *command;
1965             bson_t reply;
1966             bson_error_t error;
1967             bool res;
1968             bson_iter_t iter;
1969             bson_iter_t array_iter;
1970             double val;
1971
1972             command = BCON_NEW ("distinct",
1973                                 BCON_UTF8 (COLLECTION_NAME),
1974                                 "key",
1975                                 BCON_UTF8 ("x"),
1976                                 "query",
1977                                 "{",
1978                                 "x",
1979                                 "{",
1980                                 "$gt",
1981                                 BCON_DOUBLE (1.0),
1982                                 "}",
1983                                 "}");
1984             res =
1985                mongoc_database_command_simple (database, command, NULL, &reply, &error);
1986             if (!res) {
1987                fprintf (stderr, "Error with distinct: %s\n", error.message);
1988                goto cleanup;
1989             }
1990
1991             /* Do something with reply (in this case iterate through the values) */
1992             if (!(bson_iter_init_find (&iter, &reply, "values") &&
1993                   BSON_ITER_HOLDS_ARRAY (&iter) &&
1994                   bson_iter_recurse (&iter, &array_iter))) {
1995                fprintf (stderr, "Couldn't extract \"values\" field from response\n");
1996                goto cleanup;
1997             }
1998
1999             while (bson_iter_next (&array_iter)) {
2000                if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
2001                   val = bson_iter_double (&array_iter);
2002                   printf ("Next double: %f\n", val);
2003                }
2004             }
2005
2006          cleanup:
2007             /* cleanup */
2008             bson_destroy (command);
2009             bson_destroy (&reply);
2010             return res;
2011          }
2012
2013
2014   mapReduce - basic example
2015       A  simple example using the map reduce framework. It simply adds up the
2016       number of occurrences of each "tag".
2017
2018       First define the map and reduce functions: constants.c.INDENT 0.0
2019
2020          const char *const COLLECTION_NAME = "things";
2021
2022          /* Our map function just emits a single (key, 1) pair for each tag
2023             in the array: */
2024          const char *const MAPPER = "function () {"
2025                                     "this.tags.forEach(function(z) {"
2026                                     "emit(z, 1);"
2027                                     "});"
2028                                     "}";
2029
2030          /* The reduce function sums over all of the emitted values for a
2031             given key: */
2032          const char *const REDUCER = "function (key, values) {"
2033                                      "var total = 0;"
2034                                      "for (var i = 0; i < values.length; i++) {"
2035                                      "total += values[i];"
2036                                      "}"
2037                                      "return total;"
2038                                      "}";
2039          /* Note We can't just return values.length as the reduce function
2040             might be called iteratively on the results of other reduce
2041             steps. */
2042
2043
2044Run the mapReduce command. Use the generic command helpers (e.g.  mongoc_data‐

base_command_simple()). Do not the read command helpers (e.g. mongoc_data‐

base_read_command_with_opts()) because they are considered retryable read

2047operations.  If  retryable reads are enabled, those operations will retry once
2048on  a  retryable   error,   giving   undesirable   behavior   for   mapReduce.
2049map-reduce-basic.c.INDENT 0.0
2050
2051          bool
2052          map_reduce_basic (mongoc_database_t *database)
2053          {
2054             bson_t reply;
2055             bson_t *command;
2056             bool res;
2057             bson_error_t error;
2058             mongoc_cursor_t *cursor;
2059             const bson_t *doc;
2060
2061             bool query_done = false;
2062
2063             const char *out_collection_name = "outCollection";
2064             mongoc_collection_t *out_collection;
2065
2066             /* Empty find query */
2067             bson_t find_query = BSON_INITIALIZER;
2068
2069             /* Construct the mapReduce command */
2070
2071             /* Other arguments can also be specified here, like "query" or
2072                "limit" and so on */
2073             command = BCON_NEW ("mapReduce",
2074                                 BCON_UTF8 (COLLECTION_NAME),
2075                                 "map",
2076                                 BCON_CODE (MAPPER),
2077                                 "reduce",
2078                                 BCON_CODE (REDUCER),
2079                                 "out",
2080                                 BCON_UTF8 (out_collection_name));
2081             res =
2082                mongoc_database_command_simple (database, command, NULL, &reply, &error);
2083
2084             if (!res) {
2085                fprintf (stderr, "MapReduce failed: %s\n", error.message);
2086                goto cleanup;
2087             }
2088
2089             /* Do something with the reply (it doesn't contain the mapReduce results) */
2090             print_res (&reply);
2091
2092             /* Now we'll query outCollection to see what the results are */
2093             out_collection =
2094                mongoc_database_get_collection (database, out_collection_name);
2095             cursor = mongoc_collection_find_with_opts (
2096                out_collection, &find_query, NULL, NULL);
2097             query_done = true;
2098
2099             /* Do something with the results */
2100             while (mongoc_cursor_next (cursor, &doc)) {
2101                print_res (doc);
2102             }
2103
2104             if (mongoc_cursor_error (cursor, &error)) {
2105                fprintf (stderr, "ERROR: %s\n", error.message);
2106                res = false;
2107                goto cleanup;
2108             }
2109
2110          cleanup:
2111             /* cleanup */
2112             if (query_done) {
2113                mongoc_cursor_destroy (cursor);
2114                mongoc_collection_destroy (out_collection);
2115             }
2116
2117             bson_destroy (&reply);
2118             bson_destroy (command);
2119
2120             return res;
2121          }
2122
2123
2124   mapReduce - more complicated example
2125       You must have replica set running for this.
2126
2127       In  this  example  we  contact a secondary in the replica set and do an
2128       "inline"  map  reduce,  so  the  results  are   returned   immediately:
2129       map-reduce-advanced.c.INDENT 0.0
2130
2131          bool
2132          map_reduce_advanced (mongoc_database_t *database)
2133          {
2134             bson_t *command;
2135             bson_error_t error;
2136             bool res = true;
2137             mongoc_cursor_t *cursor;
2138             mongoc_read_prefs_t *read_pref;
2139             const bson_t *doc;
2140
2141             /* Construct the mapReduce command */
2142             /* Other arguments can also be specified here, like "query" or "limit"
2143                and so on */
2144
2145             /* Read the results inline from a secondary replica */
2146             command = BCON_NEW ("mapReduce",
2147                                 BCON_UTF8 (COLLECTION_NAME),
2148                                 "map",
2149                                 BCON_CODE (MAPPER),
2150                                 "reduce",
2151                                 BCON_CODE (REDUCER),
2152                                 "out",
2153                                 "{",
2154                                 "inline",
2155                                 "1",
2156                                 "}");
2157
2158             read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
2159             cursor = mongoc_database_command (
2160                database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
2161
2162             /* Do something with the results */
2163             while (mongoc_cursor_next (cursor, &doc)) {
2164                print_res (doc);
2165             }
2166
2167             if (mongoc_cursor_error (cursor, &error)) {
2168                fprintf (stderr, "ERROR: %s\n", error.message);
2169                res = false;
2170             }
2171
2172             mongoc_cursor_destroy (cursor);
2173             mongoc_read_prefs_destroy (read_pref);
2174             bson_destroy (command);
2175
2176             return res;
2177          }
2178
2179
2180   Running the Examples
2181       Here's how to run the example code basic-aggregation.c.INDENT 0.0
2182
2183          /*
2184           * Copyright 2016 MongoDB, Inc.
2185           *
2186           * Licensed under the Apache License, Version 2.0 (the "License");
2187           * you may not use this file except in compliance with the License.
2188           * You may obtain a copy of the License at
2189           *
2190           *   http://www.apache.org/licenses/LICENSE-2.0
2191           *
2192           * Unless required by applicable law or agreed to in writing, software
2193           * distributed under the License is distributed on an "AS IS" BASIS,
2194           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2195           * See the License for the specific language governing permissions and
2196           * limitations under the License.
2197           */
2198
2199
2200          #include <mongoc/mongoc.h>
2201          #include <stdio.h>
2202
2203
2204          #include "constants.c"
2205
2206          #include "../doc-common-insert.c"
2207          #include "distinct.c"
2208          #include "map-reduce-basic.c"
2209          #include "map-reduce-advanced.c"
2210
2211
2212          int
2213          main (int argc, char *argv[])
2214          {
2215             mongoc_database_t *database = NULL;
2216             mongoc_client_t *client = NULL;
2217             mongoc_collection_t *collection = NULL;
2218             mongoc_uri_t *uri = NULL;
2219             bson_error_t error;
2220             char *host_and_port = NULL;
2221             int exit_code = EXIT_FAILURE;
2222
2223             if (argc != 2) {
2224                fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
2225                fprintf (stderr,
2226                         "the connection string can be of the following forms:\n");
2227                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
2228                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
2229                fprintf (stderr,
2230                         "mongodb://user:pass@localhost:27017\t"
2231                         "local machine on port 27017, and authenticate with username "
2232                         "user and password pass\n");
2233                return exit_code;
2234             }
2235
2236             mongoc_init ();
2237
2238             if (strncmp (argv[1], "mongodb://", 10) == 0) {
2239                host_and_port = bson_strdup (argv[1]);
2240             } else {
2241                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
2242             }
2243
2244             uri = mongoc_uri_new_with_error (host_and_port, &error);
2245             if (!uri) {
2246                fprintf (stderr,
2247                         "failed to parse URI: %s\n"
2248                         "error message:       %s\n",
2249                         host_and_port,
2250                         error.message);
2251                goto cleanup;
2252             }
2253
2254             client = mongoc_client_new_from_uri (uri);
2255             if (!client) {
2256                goto cleanup;
2257             }
2258
2259             mongoc_client_set_error_api (client, 2);
2260             database = mongoc_client_get_database (client, "test");
2261             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
2262
2263             printf ("Inserting data\n");
2264             if (!insert_data (collection)) {
2265                goto cleanup;
2266             }
2267
2268             printf ("distinct\n");
2269             if (!distinct (database)) {
2270                goto cleanup;
2271             }
2272
2273             printf ("map reduce\n");
2274             if (!map_reduce_basic (database)) {
2275                goto cleanup;
2276             }
2277
2278             printf ("more complicated map reduce\n");
2279             if (!map_reduce_advanced (database)) {
2280                goto cleanup;
2281             }
2282
2283             exit_code = EXIT_SUCCESS;
2284
2285          cleanup:
2286             if (collection) {
2287                mongoc_collection_destroy (collection);
2288             }
2289
2290             if (database) {
2291                mongoc_database_destroy (database);
2292             }
2293
2294             if (client) {
2295                mongoc_client_destroy (client);
2296             }
2297
2298             if (uri) {
2299                mongoc_uri_destroy (uri);
2300             }
2301
2302             if (host_and_port) {
2303                bson_free (host_and_port);
2304             }
2305
2306             mongoc_cleanup ();
2307             return exit_code;
2308          }
2309
2310
2311If  you  want to try the advanced map reduce example with a secondary, start a
2312replica set (instructions for how to do this can be found here).
2313
2314Otherwise, just start an instance of MongoDB:
2315
2316          $ mongod
2317
2318       Now compile and run the example program:
2319
2320          $ cd examples/basic_aggregation/
2321          $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
2322          $ ./agg-example localhost
2323
2324          Inserting data
2325          distinct
2326          Next double: 2.000000
2327          Next double: 3.000000
2328          map reduce
2329          { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
2330          { "_id" : "cat", "value" : 63 }
2331          { "_id" : "dog", "value" : 42 }
2332          { "_id" : "mouse", "value" : 21 }
2333          more complicated map reduce
2334          { "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 }
2335

USING LIBMONGOC IN A MICROSOFT VISUAL STUDIO PROJECT

2337       Download and install libmongoc on your system, then open Visual Studio,
2338       select  "File→New→Project...",  and create a new Win32 Console Applica‐
2339       tion.  [image]
2340
2341       Remember to switch the platform from 32-bit to 64-bit: [image]
2342
2343       Right-click on your console application in the  Solution  Explorer  and
2344       select  "Properties".  Choose  to  edit  properties for "All Configura‐
2345       tions", expand the "C/C++" options and choose  "General".  Add  to  the
2346       "Additional Include Directories" these paths:
2347
2348          C:\mongo-c-driver\include\libbson-1.0
2349          C:\mongo-c-driver\include\libmongoc-1.0
2350       [image]
2351
2352       (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
2353       include paths will be different.)
2354
2355       Also in the Properties dialog, expand the "Linker" options  and  choose
2356       "Input", and add to the "Additional Dependencies" these libraries:
2357
2358          C:\mongo-c-driver\lib\bson-1.0.lib
2359          C:\mongo-c-driver\lib\mongoc-1.0.lib
2360       [image]
2361
2362       Adding these libraries as dependencies provides linker symbols to build
2363       your application, but to actually run  it,  libbson's  and  libmongoc's
2364       DLLs must be in your executable path. Select "Debugging" in the Proper‐
2365       ties dialog, and set the "Environment" option to:
2366
2367          PATH=c:/mongo-c-driver/bin
2368       [image]
2369
2370       Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
2371
2372          #include <mongoc/mongoc.h>
2373
2374   Static linking
2375       Following the instructions above,  you  have  dynamically  linked  your
2376       application  to  the  libbson  and  libmongoc DLLs. This is usually the
2377       right choice. If you want  to  link  statically  instead,  update  your
2378       "Additional  Dependencies"  list  by  removing  bson-1.0.lib  and  mon‐
2379       goc-1.0.lib and replacing them with these libraries:
2380
2381          C:\mongo-c-driver\lib\bson-static-1.0.lib
2382          C:\mongo-c-driver\lib\mongoc-static-1.0.lib
2383          ws2_32.lib
2384          Secur32.lib
2385          Crypt32.lib
2386          BCrypt.lib
2387       [image]
2388
2389       (To explain the purpose of each library: bson-static-1.0.lib  and  mon‐
2390       goc-static-1.0.lib  are  static archives of the driver code. The socket
2391       library ws2_32 is required by libbson, which uses  the  socket  routine
2392       gethostname  to  help guarantee ObjectId uniqueness. The BCrypt library
2393       is used by libmongoc for SSL connections to MongoDB,  and  Secur32  and
2394       Crypt32  are  required  for enterprise authentication methods like Ker‐
2395       beros.)
2396
2397       Finally, define two preprocessor symbols before  including  mongoc/mon‐
2398       goc.h in your stdafx.h:
2399
2400          #define BSON_STATIC
2401          #define MONGOC_STATIC
2402          #include <mongoc/mongoc.h>
2403
2404       Making  these changes to your project is only required for static link‐
2405       ing; for most people, the dynamic-linking instructions above  are  pre‐
2406       ferred.
2407
2408   Next Steps
2409       Now  you  can  build  and  debug applications in Visual Studio that use
2410       libbson and libmongoc. Proceed to making-a-connection in  the  tutorial
2411       to learn how connect to MongoDB and perform operations.
2412

CREATING INDEXES

2414       To  create  indexes  on a MongoDB collection, execute the createIndexes
2415       command  with  a  command  function   like   mongoc_database_write_com‐
2416       mand_with_opts  or  mongoc_collection_write_command_with_opts.  See the
2417       MongoDB Manual entry for the createIndexes command for details.
2418
2419   Example
2420       example-create-indexes.c.INDENT 0.0
2421
2422          /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
2423           * --libs libmongoc-1.0) */
2424
2425          /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */
2426
2427          #include <mongoc/mongoc.h>
2428          #include <stdio.h>
2429          #include <stdlib.h>
2430
2431          int
2432          main (int argc, char *argv[])
2433          {
2434             mongoc_client_t *client;
2435             const char *uri_string =
2436                "mongodb://127.0.0.1/?appname=create-indexes-example";
2437             mongoc_uri_t *uri;
2438             mongoc_database_t *db;
2439             const char *collection_name = "test";
2440             bson_t keys;
2441             char *index_name;
2442             bson_t *create_indexes;
2443             bson_t reply;
2444             char *reply_str;
2445             bson_error_t error;
2446             bool r;
2447
2448             mongoc_init ();
2449
2450             if (argc > 1) {
2451                uri_string = argv[1];
2452             }
2453
2454             if (argc > 2) {
2455                collection_name = argv[2];
2456             }
2457
2458             uri = mongoc_uri_new_with_error (uri_string, &error);
2459             if (!uri) {
2460                fprintf (stderr,
2461                         "failed to parse URI: %s\n"
2462                         "error message:       %s\n",
2463                         uri_string,
2464                         error.message);
2465                return EXIT_FAILURE;
2466             }
2467
2468             client = mongoc_client_new_from_uri (uri);
2469             if (!client) {
2470                return EXIT_FAILURE;
2471             }
2472
2473             mongoc_client_set_error_api (client, 2);
2474             db = mongoc_client_get_database (client, "test");
2475
2476             /* ascending index on field "x" */
2477             bson_init (&keys);
2478             BSON_APPEND_INT32 (&keys, "x", 1);
2479             index_name = mongoc_collection_keys_to_index_string (&keys);
2480             create_indexes = BCON_NEW ("createIndexes",
2481                                        BCON_UTF8 (collection_name),
2482                                        "indexes",
2483                                        "[",
2484                                        "{",
2485                                        "key",
2486                                        BCON_DOCUMENT (&keys),
2487                                        "name",
2488                                        BCON_UTF8 (index_name),
2489                                        "}",
2490                                        "]");
2491
2492             r = mongoc_database_write_command_with_opts (
2493                db, create_indexes, NULL /* opts */, &reply, &error);
2494
2495             reply_str = bson_as_json (&reply, NULL);
2496             printf ("%s\n", reply_str);
2497
2498             if (!r) {
2499                fprintf (stderr, "Error in createIndexes: %s\n", error.message);
2500             }
2501
2502             bson_free (index_name);
2503             bson_free (reply_str);
2504             bson_destroy (&reply);
2505             bson_destroy (create_indexes);
2506             mongoc_database_destroy (db);
2507             mongoc_uri_destroy (uri);
2508             mongoc_client_destroy (client);
2509
2510             mongoc_cleanup ();
2511
2512             return r ? EXIT_SUCCESS : EXIT_FAILURE;
2513          }
2514
2515

AIDS FOR DEBUGGING

2517   GDB
2518       This repository contains a .gdbinit file that contains helper functions
2519       to   aid  debugging  of  data  structures.  GDB  will  load  this  file
2520       automatically if you  have  added  the  directory  which  contains  the
2521       .gdbinit  file to GDB's auto-load safe-path, and you start GDB from the
2522       directory which holds the .gdbinit file.
2523
2524       You can see the safe-path  with  show  auto-load  safe-path  on  a  GDB
2525       prompt. You can configure it by setting it in ~/.gdbinit with:
2526
2527          add-auto-load-safe-path /path/to/mongo-c-driver
2528
2529       If you haven't added the path to your auto-load safe-path, or start GDB
2530       in another directory, load the file with:
2531
2532          source path/to/mongo-c-driver/.gdbinit
2533
2534       The .gdbinit file defines the printbson function, which shows the  con‐
2535       tents  of  a  bson_t  * variable.  If you have a local bson_t, then you
2536       must prefix the variable with a &.
2537
2538       An example GDB session looks like:
2539
2540          (gdb) printbson bson
2541          ALLOC [0x555556cd7310 + 0] (len=475)
2542          {
2543              'bool' : true,
2544              'int32' : NumberInt("42"),
2545              'int64' : NumberLong("3000000042"),
2546              'string' : "Stŕìñg",
2547              'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
2548              'utcDateTime' : UTCDateTime(1511277299031),
2549              'arrayOfInts' : [
2550                  '0' : NumberInt("1"),
2551                  '1' : NumberInt("2")
2552              ],
2553              'embeddedDocument' : {
2554                  'arrayOfStrings' : [
2555                      '0' : "one",
2556                      '1' : "two"
2557                  ],
2558                  'double' : 2.718280,
2559                  'notherDoc' : {
2560                      'true' : NumberInt("1"),
2561                      'false' : false
2562                  }
2563              },
2564              'binary' : Binary("02", "3031343532333637"),
2565              'regex' : Regex("@[a-z]+@", "im"),
2566              'null' : null,
2567              'js' : JavaScript("print foo"),
2568              'jsws' : JavaScript("print foo") with scope: {
2569                  'f' : NumberInt("42"),
2570                  'a' : [
2571                      '0' : 3.141593,
2572                      '1' : 2.718282
2573                  ]
2574              },
2575              'timestamp' : Timestamp(4294967295, 4294967295),
2576              'double' : 3.141593
2577          }
2578
2579   LLDB
2580       This repository also includes a script that customizes LLDB's  standard
2581       print command to print a bson_t or bson_t * as JSON:
2582
2583          (lldb) print b
2584          (bson_t) $0 = {"x": 1, "y": 2}
2585
2586       The custom bson command provides more options:
2587
2588          (lldb) bson --verbose b
2589          len=19
2590          flags=INLINE|STATIC
2591          {
2592            "x": 1,
2593            "y": 2
2594          }
2595          (lldb) bson --raw b
2596          '\x13\x00\x00\x00\x10x\x00\x01\x00\x00\x00\x10y\x00\x02\x00\x00\x00\x00'
2597
2598       Type help bson for a list of options.
2599
2600       The  script  requires  a  build  of  libbson with debug symbols, and an
2601       installation of PyMongo. Install PyMongo with:
2602
2603          python -m pip install pymongo
2604
2605       If you see "No module named pip" then you must install  pip,  then  run
2606       the previous command again.
2607
2608       Create a file ~/.lldbinit containing:
2609
2610          command script import /path/to/mongo-c-driver/lldb_bson.py
2611
2612       If  you  see  "bson command installed by lldb_bson" at the beginning of
2613       your LLDB session, you've installed the script correctly.
2614

AUTHOR

2616       MongoDB, Inc
2617
2619       2017-present, MongoDB, Inc
2620
2621
2622
2623
26241.15.2                           Nov 06, 2019                 MONGOC_GUIDES(3)
Impressum