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       This  snippet  contains  example  code  for  the  explain,  copydb  and
14       cloneCollection commands.
15
16   Setup
17       First  we'll  write  some  code  to  insert   sample   data:   doc-com‐
18       mon-insert.c.INDENT 0.0
19
20          /* Don't try to compile this file on its own. It's meant to be #included
21             by example code */
22
23          /* Insert some sample data */
24          bool
25          insert_data (mongoc_collection_t *collection)
26          {
27             mongoc_bulk_operation_t *bulk;
28             enum N { ndocs = 4 };
29             bson_t *docs[ndocs];
30             bson_error_t error;
31             int i = 0;
32             bool ret;
33
34             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
35
36             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
37             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
38             docs[2] = BCON_NEW (
39                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
40             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
41
42             for (i = 0; i < ndocs; i++) {
43                mongoc_bulk_operation_insert (bulk, docs[i]);
44                bson_destroy (docs[i]);
45                docs[i] = NULL;
46             }
47
48             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
49
50             if (!ret) {
51                fprintf (stderr, "Error inserting data: %s\n", error.message);
52             }
53
54             mongoc_bulk_operation_destroy (bulk);
55             return ret;
56          }
57
58          /* A helper which we'll use a lot later on */
59          void
60          print_res (const bson_t *reply)
61          {
62             char *str;
63             BSON_ASSERT (reply);
64             str = bson_as_canonical_extended_json (reply, NULL);
65             printf ("%s\n", str);
66             bson_free (str);
67          }
68
69
70   explain Command
71       This   is   how   to   use   the   explain  command  in  MongoDB  3.2+:
72       explain.c.INDENT 0.0
73
74          bool
75          explain (mongoc_collection_t *collection)
76          {
77             bson_t *command;
78             bson_t reply;
79             bson_error_t error;
80             bool res;
81
82             command = BCON_NEW ("explain",
83                                 "{",
84                                 "find",
85                                 BCON_UTF8 (COLLECTION_NAME),
86                                 "filter",
87                                 "{",
88                                 "x",
89                                 BCON_INT32 (1),
90                                 "}",
91                                 "}");
92             res = mongoc_collection_command_simple (
93                collection, command, NULL, &reply, &error);
94             if (!res) {
95                fprintf (stderr, "Error with explain: %s\n", error.message);
96                goto cleanup;
97             }
98
99             /* Do something with the reply */
100             print_res (&reply);
101
102          cleanup:
103             bson_destroy (&reply);
104             bson_destroy (command);
105             return res;
106          }
107
108
109   copydb Command
110       This example requires two instances of mongo to be running.
111
112       Here's how to use the copydb command to copy a  database  from  another
113       instance of MongoDB: copydb.c.INDENT 0.0
114
115          bool
116          copydb (mongoc_client_t *client, const char *other_host_and_port)
117          {
118             mongoc_database_t *admindb;
119             bson_t *command;
120             bson_t reply;
121             bson_error_t error;
122             bool res;
123
124             BSON_ASSERT (other_host_and_port);
125             /* Must do this from the admin db */
126             admindb = mongoc_client_get_database (client, "admin");
127
128             command = BCON_NEW ("copydb",
129                                 BCON_INT32 (1),
130                                 "fromdb",
131                                 BCON_UTF8 ("test"),
132                                 "todb",
133                                 BCON_UTF8 ("test2"),
134
135                                 /* If you want from a different host */
136                                 "fromhost",
137                                 BCON_UTF8 (other_host_and_port));
138             res =
139                mongoc_database_command_simple (admindb, command, NULL, &reply, &error);
140             if (!res) {
141                fprintf (stderr, "Error with copydb: %s\n", error.message);
142                goto cleanup;
143             }
144
145             /* Do something with the reply */
146             print_res (&reply);
147
148          cleanup:
149             bson_destroy (&reply);
150             bson_destroy (command);
151             mongoc_database_destroy (admindb);
152
153             return res;
154          }
155
156
157   cloneCollection Command
158       This example requires two instances of mongo to be running.
159
160       Here's  an example of the cloneCollection command to clone a collection
161       from another instance of MongoDB: clone-collection.c.INDENT 0.0
162
163          bool
164          clone_collection (mongoc_database_t *database, const char *other_host_and_port)
165          {
166             bson_t *command;
167             bson_t reply;
168             bson_error_t error;
169             bool res;
170
171             BSON_ASSERT (other_host_and_port);
172             command = BCON_NEW ("cloneCollection",
173                                 BCON_UTF8 ("test.remoteThings"),
174                                 "from",
175                                 BCON_UTF8 (other_host_and_port),
176                                 "query",
177                                 "{",
178                                 "x",
179                                 BCON_INT32 (1),
180                                 "}");
181             res =
182                mongoc_database_command_simple (database, command, NULL, &reply, &error);
183             if (!res) {
184                fprintf (stderr, "Error with clone: %s\n", error.message);
185                goto cleanup;
186             }
187
188             /* Do something with the reply */
189             print_res (&reply);
190
191          cleanup:
192             bson_destroy (&reply);
193             bson_destroy (command);
194
195             return res;
196          }
197
198
199   Running the Examples
200       common-operations.c.INDENT 0.0
201
202          /*
203           * Copyright 2016 MongoDB, Inc.
204           *
205           * Licensed under the Apache License, Version 2.0 (the "License");
206           * you may not use this file except in compliance with the License.
207           * You may obtain a copy of the License at
208           *
209           *   http://www.apache.org/licenses/LICENSE-2.0
210           *
211           * Unless required by applicable law or agreed to in writing, software
212           * distributed under the License is distributed on an "AS IS" BASIS,
213           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
214           * See the License for the specific language governing permissions and
215           * limitations under the License.
216           */
217
218
219          #include <mongoc/mongoc.h>
220          #include <stdio.h>
221
222
223          const char *COLLECTION_NAME = "things";
224
225          #include "../doc-common-insert.c"
226          #include "explain.c"
227          #include "copydb.c"
228          #include "clone-collection.c"
229
230
231          int
232          main (int argc, char *argv[])
233          {
234             mongoc_database_t *database = NULL;
235             mongoc_client_t *client = NULL;
236             mongoc_collection_t *collection = NULL;
237             mongoc_uri_t *uri = NULL;
238             bson_error_t error;
239             char *host_and_port;
240             int res = 0;
241             char *other_host_and_port = NULL;
242
243             if (argc < 2 || argc > 3) {
244                fprintf (stderr,
245                         "usage: %s MONGOD-1-CONNECTION-STRING "
246                         "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
247                         argv[0]);
248                fprintf (stderr,
249                         "MONGOD-1-CONNECTION-STRING can be "
250                         "of the following forms:\n");
251                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
252                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
253                fprintf (stderr,
254                         "mongodb://user:pass@localhost:27017\t"
255                         "local machine on port 27017, and authenticate with username "
256                         "user and password pass\n");
257                return EXIT_FAILURE;
258             }
259
260             mongoc_init ();
261
262             if (strncmp (argv[1], "mongodb://", 10) == 0) {
263                host_and_port = bson_strdup (argv[1]);
264             } else {
265                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
266             }
267             other_host_and_port = argc > 2 ? argv[2] : NULL;
268
269             uri = mongoc_uri_new_with_error (host_and_port, &error);
270             if (!uri) {
271                fprintf (stderr,
272                         "failed to parse URI: %s\n"
273                         "error message:       %s\n",
274                         host_and_port,
275                         error.message);
276                res = EXIT_FAILURE;
277                goto cleanup;
278             }
279
280             client = mongoc_client_new_from_uri (uri);
281             if (!client) {
282                res = EXIT_FAILURE;
283                goto cleanup;
284             }
285
286             mongoc_client_set_error_api (client, 2);
287             database = mongoc_client_get_database (client, "test");
288             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
289
290             printf ("Inserting data\n");
291             if (!insert_data (collection)) {
292                res = EXIT_FAILURE;
293                goto cleanup;
294             }
295
296             printf ("explain\n");
297             if (!explain (collection)) {
298                res = EXIT_FAILURE;
299                goto cleanup;
300             }
301
302             if (other_host_and_port) {
303                printf ("copydb\n");
304                if (!copydb (client, other_host_and_port)) {
305                   res = EXIT_FAILURE;
306                   goto cleanup;
307                }
308
309                printf ("clone collection\n");
310                if (!clone_collection (database, other_host_and_port)) {
311                   res = EXIT_FAILURE;
312                   goto cleanup;
313                }
314             }
315
316          cleanup:
317             if (collection) {
318                mongoc_collection_destroy (collection);
319             }
320
321             if (database) {
322                mongoc_database_destroy (database);
323             }
324
325             if (client) {
326                mongoc_client_destroy (client);
327             }
328
329             if (uri) {
330                mongoc_uri_destroy (uri);
331             }
332
333             bson_free (host_and_port);
334             mongoc_cleanup ();
335             return res;
336          }
337
338
339First launch two separate instances of mongod  (must  be  done  from  separate
340shells):
341
342          $ mongod
343
344          $ mkdir /tmp/db2$ mongod --dbpath /tmp/db2 --port 27018 # second instance
345
346       Now compile and run the example program:
347
348          $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
349          Inserting data
350          explain
351          {
352             "executionStats" : {
353                "allPlansExecution" : [],
354                "executionStages" : {
355                   "advanced" : 19,
356                   "direction" : "forward" ,
357                   "docsExamined" : 76,
358                   "executionTimeMillisEstimate" : 0,
359                   "filter" : {
360                      "x" : {
361                         "$eq" : 1
362                      }
363                   },
364                   "invalidates" : 0,
365                   "isEOF" : 1,
366                   "nReturned" : 19,
367                   "needTime" : 58,
368                   "needYield" : 0,
369                   "restoreState" : 0,
370                   "saveState" : 0,
371                   "stage" : "COLLSCAN" ,
372                   "works" : 78
373                },
374                "executionSuccess" : true,
375                "executionTimeMillis" : 0,
376                "nReturned" : 19,
377                "totalDocsExamined" : 76,
378                "totalKeysExamined" : 0
379             },
380             "ok" : 1,
381             "queryPlanner" : {
382                "indexFilterSet" : false,
383                "namespace" : "test.things",
384                "parsedQuery" : {
385                   "x" : {
386                      "$eq" : 1
387                   }
388                },
389                "plannerVersion" : 1,
390                "rejectedPlans" : [],
391                "winningPlan" : {
392                   "direction" : "forward" ,
393                   "filter" : {
394                      "x" : {
395                         "$eq" : 1
396                      }
397                   },
398                   "stage" : "COLLSCAN"
399                }
400             },
401             "serverInfo" : {
402                "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
403                "host" : "MacBook-Pro-57.local",
404                "port" : 27017,
405                "version" : "3.2.6"
406             }
407          }
408          copydb
409          { "ok" : 1 }
410          clone collection
411          { "ok" : 1 }
412

ADVANCED CONNECTIONS

414       The  following  guide contains information specific to certain types of
415       MongoDB configurations.
416
417       For an example of connecting to a simple  standalone  server,  see  the
418       Tutorial.   To  establish  a  connection  with  authentication  options
419       enabled, see the Authentication page.
420
421   Connecting to a Replica Set
422       Connecting to a replica set is much like  connecting  to  a  standalone
423       MongoDB  server.  Simply specify the replica set name using the ?repli‐
424       caSet=myreplset URI option.
425
426          #include <bson/bson.h>
427          #include <mongoc/mongoc.h>
428
429          int
430          main (int argc, char *argv[])
431          {
432             mongoc_client_t *client;
433
434             mongoc_init ();
435
436             /* Create our MongoDB Client */
437             client = mongoc_client_new (
438                "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");
439
440             /* Do some work */
441             /* TODO */
442
443             /* Clean up */
444             mongoc_client_destroy (client);
445             mongoc_cleanup ();
446
447             return 0;
448          }
449
450       TIP:
451          Multiple hostnames can be specified in the MongoDB connection string
452          URI, with a comma separating hosts in the seed list.
453
454          It  is  recommended to use a seed list of members of the replica set
455          to allow the driver to connect to any node.
456
457   Connecting to a Sharded Cluster
458       To connect to a sharded cluster, specify the mongos  nodes  the  client
459       should  connect  to. The C Driver will automatically detect that it has
460       connected to a mongos sharding server.
461
462       If more than one hostname is specified, a seed list will be created  to
463       attempt failover between the mongos instances.
464
465       WARNING:
466          Specifying  the  replicaSet  parameter  when  connecting to a mongos
467          sharding server is invalid.
468
469          #include <bson/bson.h>
470          #include <mongoc/mongoc.h>
471
472          int
473          main (int argc, char *argv[])
474          {
475             mongoc_client_t *client;
476
477             mongoc_init ();
478
479             /* Create our MongoDB Client */
480             client = mongoc_client_new ("mongodb://myshard01:27017/");
481
482             /* Do something with client ... */
483
484             /* Free the client */
485             mongoc_client_destroy (client);
486
487             mongoc_cleanup ();
488
489             return 0;
490          }
491
492   Connecting to an IPv6 Address
493       The MongoDB C Driver will automatically  resolve  IPv6  addresses  from
494       host  names.  However,  to  specify  an IPv6 address directly, wrap the
495       address in [].
496
497          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");
498
499   Connecting with IPv4 and IPv6
500       If connecting to a hostname that has both IPv4 and  IPv6  DNS  records,
501       the  behavior  follows  RFC-6555.  A  connection to the IPv6 address is
502       attempted first. If IPv6 fails, then a connection is attempted  to  the
503       IPv4  address.  If  the  connection  attempt  to IPv6 does not complete
504       within 250ms, then IPv4 is tried in parallel. Whichever  succeeds  con‐
505       nection  first  cancels  the other. The successful DNS result is cached
506       for 10 minutes.
507
508       As a consequence, attempts to connect to a  mongod  only  listening  on
509       IPv4  may  be  delayed  if  there are both A (IPv4) and AAAA (IPv6) DNS
510       records associated with the host.
511
512       To avoid a delay, configure hostnames to match the  MongoDB  configura‐
513       tion.  That is, only create an A record if the mongod is only listening
514       on IPv4.
515
516   Connecting to a UNIX Domain Socket
517       On UNIX-like systems, the C Driver can connect directly  to  a  MongoDB
518       server  using  a  UNIX  domain socket. Pass the URL-encoded path to the
519       socket, which must be suffixed with .sock. For example, to connect to a
520       domain socket at /tmp/mongodb-27017.sock:
521
522          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");
523
524       Include username and password like so:
525
526          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");
527
528   Connecting to a server over SSL
529       These are instructions for configuring TLS/SSL connections.
530
531       To run a server locally (on port 27017, for example):
532
533          $ mongod --port 27017 --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem
534
535       Add /?ssl=true to the end of a client URI.
536
537          mongoc_client_t *client = NULL;
538          client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true");
539
540       MongoDB requires client certificates by default, unless the --sslAllow‐
541       ConnectionsWithoutCertificates is provided. The C Driver can be config‐
542       ured to present a client certificate using a mongoc_ssl_opt_t:
543
544          const mongoc_ssl_opt_t *ssl_default = mongoc_ssl_opt_get_default ();
545          mongoc_ssl_opt_t ssl_opts = { 0 };
546
547          /* optionally copy in a custom trust directory or file; otherwise the default is used. */
548          memcpy (&ssl_opts, ssl_default, sizeof ssl_opts);
549          ssl_opts.pem_file = "client.pem"
550
551          mongoc_client_set_ssl_opts (client, &ssl_opts);
552
553       The  client  certificate  provided by pem_file must be issued by one of
554       the server trusted Certificate Authorities listed  in  --sslCAFile,  or
555       issued by a CA in the native certificate store on the server when omit‐
556       ted.
557
558       To verify the server certificate against a specific CA, provide  a  PEM
559       armored file with a CA certificate, or concatenated list of CA certifi‐
560       cates using the ca_file option, or c_rehash directory structure of CAs,
561       pointed  to  using the ca_dir option. When no ca_file or ca_dir is pro‐
562       vided, the driver will use CAs provided by the native platform certifi‐
563       cate store.
564
565       See  mongoc_ssl_opt_t  for  more information on the various SSL related
566       options.
567
568   Compressing data to and from MongoDB
569       MongoDB 3.4 added Snappy compression support, and zlib  compression  in
570       3.6.   To enable compression support the client must be configured with
571       which compressors to use:
572
573          mongoc_client_t *client = NULL;
574          client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib");
575
576       The compressors option specifies the priority order of compressors  the
577       client  wants  to use. Messages are compressed if the client and server
578       share any compressors in common.
579
580       Note that the compressor used by the server might not be the same  com‐
581       pressor  as  the client used.  For example, if the client uses the con‐
582       nection string compressors=zlib,snappy the client will  use  zlib  com‐
583       pression  to  send data (if possible), but the server might still reply
584       using snappy, depending on how the server was configured.
585
586       The driver must be built with zlib and/or snappy support to enable com‐
587       pression  support,  any  unknown  (or not compiled in) compressor value
588       will be ignored.
589
590   Additional Connection Options
591       The full list of connection options can be found  in  the  mongoc_uri_t
592       docs.
593
594       Certain socket/connection related options are not configurable:
595
596
597
598
599             ┌──────────────┬─────────────────────┬─────────────────────┐
600             │Option        │ Description         │ Value               │
601             ├──────────────┼─────────────────────┼─────────────────────┤
602             │SO_KEEPALIVE  │ TCP Keep Alive      │ Enabled             │
603             ├──────────────┼─────────────────────┼─────────────────────┤
604             │TCP_KEEPIDLE  │ How  long a connec‐ │ 300 seconds         │
605             │              │ tion    needs    to │                     │
606             │              │ remain  idle before │                     │
607             │              │ TCP starts  sending │                     │
608             │              │ keepalive probes    │                     │
609             ├──────────────┼─────────────────────┼─────────────────────┤
610             │TCP_KEEPINTVL │ The time in seconds │ 10 seconds          │
611             │              │ between TCP probes  │                     │
612             ├──────────────┼─────────────────────┼─────────────────────┤
613             │TCP_KEEPCNT   │ How many probes  to │ 9 probes            │
614             │              │ send,       without │                     │
615             │              │ acknowledgement,    │                     │
616             │              │ before dropping the │                     │
617             │              │ connection          │                     │
618             ├──────────────┼─────────────────────┼─────────────────────┤
619             │TCP_NODELAY   │ Send   packets   as │ Enabled (no buffer‐ │
620             │              │ soon as possible or │ ing)                │
621             │              │ buffer small  pack‐ │                     │
622             │              │ ets   (Nagle  algo‐ │                     │
623             │              │ rithm)              │                     │
624             └──────────────┴─────────────────────┴─────────────────────┘
625

CONNECTION POOLING

627       The  MongoDB  C  driver  has  two connection modes: single-threaded and
628       pooled. Single-threaded mode is  optimized  for  embedding  the  driver
629       within  languages  like  PHP. Multi-threaded programs should use pooled
630       mode: this mode minimizes the total connection  count,  and  in  pooled
631       mode  a  background thread monitors the MongoDB server topology, so the
632       program need not block to scan it.
633
634   Single Mode
635       In single mode, your program creates a mongoc_client_t directly:
636
637          mongoc_client_t *client = mongoc_client_new (
638             "mongodb://hostA,hostB/?replicaSet=my_rs");
639
640       The client connects on demand when your program first  uses  it  for  a
641       MongoDB  operation. Using a non-blocking socket per server, it begins a
642       check on each server concurrently, and uses the  asynchronous  poll  or
643       select  function  to  receive  events  from the sockets, until all have
644       responded or timed out. Put another way, in single-threaded mode the  C
645       Driver fans out to begin all checks concurrently, then fans in once all
646       checks have completed or timed out. Once the scan completes, the client
647       executes your program's operation and returns.
648
649       In  single  mode,  the client re-scans the server topology roughly once
650       per minute. If more than a minute has elapsed since the previous  scan,
651       the  next operation on the client will block while the client completes
652       its scan. This interval is configurable  with  heartbeatFrequencyMS  in
653       the connection string. (See mongoc_uri_t.)
654
655       A single client opens one connection per server in your topology: these
656       connections are used both for scanning the topology and performing nor‐
657       mal operations.
658
659   Pooled Mode
660       To activate pooled mode, create a mongoc_client_pool_t:
661
662          mongoc_uri_t *uri = mongoc_uri_new (
663             "mongodb://hostA,hostB/?replicaSet=my_rs");
664
665          mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
666
667       When your program first calls mongoc_client_pool_pop, the pool launches
668       a background thread for monitoring. The thread fans out and connects to
669       all  servers in the connection string, using non-blocking sockets and a
670       simple event loop. As it receives ismaster responses from the  servers,
671       it  updates  its view of the server topology. Each time the thread dis‐
672       covers a new server it begins connecting to it, and adds the new socket
673       to the list of non-blocking sockets in the event loop.
674
675       Each  thread  that  executes MongoDB operations must check out a client
676       from the pool:
677
678          mongoc_client_t *client = mongoc_client_pool_pop (pool);
679
680          /* use the client for operations ... */
681
682          mongoc_client_pool_push (pool, client);
683
684       The  mongoc_client_t  object  is  not  thread-safe,   only   the   mon‐
685       goc_client_pool_t is.
686
687       When  the  driver  is  in  pooled  mode,  your program's operations are
688       unblocked as soon as monitoring discovers a usable server. For example,
689       if  a  thread  in your program is waiting to execute an "insert" on the
690       primary, it is unblocked as soon as the primary is  discovered,  rather
691       than waiting for all secondaries to be checked as well.
692
693       The  pool  opens  one  connection  per  server for monitoring, and each
694       client opens its own connection to each server it uses for  application
695       operations.  The background thread re-scans the server topology roughly
696       every 10 seconds. This interval is configurable with  heartbeatFrequen‐
697       cyMS in the connection string. (See mongoc_uri_t.)
698
699       See  connection_pool_options  to  configure pool size and behavior, and
700       see mongoc_client_pool_t for an extended example  of  a  multi-threaded
701       program that uses the driver in pooled mode.
702

CURSORS

704   Handling Cursor Failures
705       Cursors  exist on a MongoDB server. However, the mongoc_cursor_t struc‐
706       ture gives the local process a handle to the cursor. It is possible for
707       errors  to  occur on the server while iterating a cursor on the client.
708       Even a network partition may occur. This means that applications should
709       be robust in handling cursor failures.
710
711       While  iterating  cursors,  you  should  check  to  see if an error has
712       occurred. See the following example  for  how  to  robustly  check  for
713       errors.
714
715          static void
716          print_all_documents (mongoc_collection_t *collection)
717          {
718             mongoc_cursor_t *cursor;
719             const bson_t *doc;
720             bson_error_t error;
721             bson_t query = BSON_INITIALIZER;
722             char *str;
723
724             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
725
726             while (mongoc_cursor_next (cursor, &doc)) {
727                str = bson_as_canonical_extended_json (doc, NULL);
728                printf ("%s\n", str);
729                bson_free (str);
730             }
731
732             if (mongoc_cursor_error (cursor, &error)) {
733                fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
734             }
735
736             mongoc_cursor_destroy (cursor);
737          }
738
739   Destroying Server-Side Cursors
740       The  MongoDB  C  driver will automatically destroy a server-side cursor
741       when mongoc_cursor_destroy() is called. Failure to call  this  function
742       when done with a cursor will leak memory client side as well as consume
743       extra memory server side. If the cursor was configured to  never  time‐
744       out, it will become a memory leak on the server.
745
746   Tailable Cursors
747       Tailable  cursors  are  cursors  that  remain  open  even after they've
748       returned a final result. This way, if more documents  are  added  to  a
749       collection (i.e., to the cursor's result set), then you can continue to
750       call mongoc_cursor_next() to retrieve those additional results.
751
752       Here's a complete test case that demonstrates the use of tailable  cur‐
753       sors.
754
755       NOTE:
756          Tailable cursors are for capped collections only.
757
758       An  example to tail the oplog from a replica set.  mongoc-tail.c.INDENT
759       0.0
760
761          #include <bson/bson.h>
762          #include <mongoc/mongoc.h>
763          #include <stdio.h>
764          #include <stdlib.h>
765
766          #ifdef _WIN32
767          #define sleep(_n) Sleep ((_n) *1000)
768          #endif
769
770
771          static void
772          print_bson (const bson_t *b)
773          {
774             char *str;
775
776             str = bson_as_canonical_extended_json (b, NULL);
777             fprintf (stdout, "%s\n", str);
778             bson_free (str);
779          }
780
781
782          static mongoc_cursor_t *
783          query_collection (mongoc_collection_t *collection, uint32_t last_time)
784          {
785             mongoc_cursor_t *cursor;
786             bson_t query;
787             bson_t gt;
788             bson_t opts;
789
790             BSON_ASSERT (collection);
791
792             bson_init (&query);
793             BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", &gt);
794             BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
795             bson_append_document_end (&query, &gt);
796
797             bson_init (&opts);
798             BSON_APPEND_BOOL (&opts, "tailable", true);
799             BSON_APPEND_BOOL (&opts, "awaitData", true);
800
801             cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
802
803             bson_destroy (&query);
804             bson_destroy (&opts);
805
806             return cursor;
807          }
808
809
810          static void
811          tail_collection (mongoc_collection_t *collection)
812          {
813             mongoc_cursor_t *cursor;
814             uint32_t last_time;
815             const bson_t *doc;
816             bson_error_t error;
817             bson_iter_t iter;
818
819             BSON_ASSERT (collection);
820
821             last_time = (uint32_t) time (NULL);
822
823             while (true) {
824                cursor = query_collection (collection, last_time);
825                while (!mongoc_cursor_error (cursor, &error) &&
826                       mongoc_cursor_more (cursor)) {
827                   if (mongoc_cursor_next (cursor, &doc)) {
828                      if (bson_iter_init_find (&iter, doc, "ts") &&
829                          BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
830                         bson_iter_timestamp (&iter, &last_time, NULL);
831                      }
832                      print_bson (doc);
833                   }
834                }
835                if (mongoc_cursor_error (cursor, &error)) {
836                   if (error.domain == MONGOC_ERROR_SERVER) {
837                      fprintf (stderr, "%s\n", error.message);
838                      exit (1);
839                   }
840                }
841
842                mongoc_cursor_destroy (cursor);
843                sleep (1);
844             }
845          }
846
847
848          int
849          main (int argc, char *argv[])
850          {
851             mongoc_collection_t *collection;
852             mongoc_client_t *client;
853             mongoc_uri_t *uri;
854             bson_error_t error;
855
856             if (argc != 2) {
857                fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
858                return EXIT_FAILURE;
859             }
860
861             mongoc_init ();
862
863             uri = mongoc_uri_new_with_error (argv[1], &error);
864             if (!uri) {
865                fprintf (stderr,
866                         "failed to parse URI: %s\n"
867                         "error message:       %s\n",
868                         argv[1],
869                         error.message);
870                return EXIT_FAILURE;
871             }
872
873             client = mongoc_client_new_from_uri (uri);
874             if (!client) {
875                return EXIT_FAILURE;
876             }
877
878             mongoc_client_set_error_api (client, 2);
879
880             collection = mongoc_client_get_collection (client, "local", "oplog.rs");
881
882             tail_collection (collection);
883
884             mongoc_collection_destroy (collection);
885             mongoc_uri_destroy (uri);
886             mongoc_client_destroy (client);
887
888             return EXIT_SUCCESS;
889          }
890
891
892Let's compile and run this example against a replica set  to  see  updates  as
893they are made.
894
895          $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
896          $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
897          {
898              "h" : -8458503739429355503,
899              "ns" : "test.test",
900              "o" : {
901                  "_id" : {
902                      "$oid" : "5372ab0a25164be923d10d50"
903                  }
904              },
905              "op" : "i",
906              "ts" : {
907                  "$timestamp" : {
908                      "i" : 1,
909                      "t" : 1400023818
910                  }
911              },
912              "v" : 2
913          }
914
915       The  line of output is a sample from performing db.test.insert({}) from
916       the mongo shell on the replica set.
917
918       See also mongoc_cursor_set_max_await_time_ms.
919

BULK WRITE OPERATIONS

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

AGGREGATION FRAMEWORK EXAMPLES

1797       This  document provides a number of practical examples that display the
1798       capabilities of the aggregation framework.
1799
1800       The Aggregations using the Zip Codes Data Set examples uses a  publicly
1801       available  data  set  of  all  zipcodes  and  populations in the United
1802       States. These data are available at: zips.json.
1803
1804   Requirements
1805       Let's check if everything is installed.
1806
1807       Use the following command  to  load  zips.json  data  set  into  mongod
1808       instance:
1809
1810          $ mongoimport --drop -d test -c zipcodes zips.json
1811
1812       Let's use the MongoDB shell to verify that everything was imported suc‐
1813       cessfully.
1814
1815          $ mongo test
1816          connecting to: test
1817          > db.zipcodes.count()
1818          29467
1819          > db.zipcodes.findOne()
1820          {
1821                "_id" : "35004",
1822                "city" : "ACMAR",
1823                "loc" : [
1824                        -86.51557,
1825                        33.584132
1826                ],
1827                "pop" : 6055,
1828                "state" : "AL"
1829          }
1830
1831   Aggregations using the Zip Codes Data Set
1832       Each document in this collection has the following form:
1833
1834          {
1835            "_id" : "35004",
1836            "city" : "Acmar",
1837            "state" : "AL",
1838            "pop" : 6055,
1839            "loc" : [-86.51557, 33.584132]
1840          }
1841
1842       In these documents:
1843
1844       · The _id field holds the zipcode as a string.
1845
1846       · The city field holds the city name.
1847
1848       · The state field holds the two letter state abbreviation.
1849
1850       · The pop field holds the population.
1851
1852       · The loc field holds the location as a [latitude, longitude] array.
1853
1854   States with Populations Over 10 Million
1855       To get all states with a population greater than 10  million,  use  the
1856       following aggregation pipeline: aggregation1.c.INDENT 0.0
1857
1858          #include <mongoc/mongoc.h>
1859          #include <stdio.h>
1860
1861          static void
1862          print_pipeline (mongoc_collection_t *collection)
1863          {
1864             mongoc_cursor_t *cursor;
1865             bson_error_t error;
1866             const bson_t *doc;
1867             bson_t *pipeline;
1868             char *str;
1869
1870             pipeline = BCON_NEW ("pipeline",
1871                                  "[",
1872                                  "{",
1873                                  "$group",
1874                                  "{",
1875                                  "_id",
1876                                  "$state",
1877                                  "total_pop",
1878                                  "{",
1879                                  "$sum",
1880                                  "$pop",
1881                                  "}",
1882                                  "}",
1883                                  "}",
1884                                  "{",
1885                                  "$match",
1886                                  "{",
1887                                  "total_pop",
1888                                  "{",
1889                                  "$gte",
1890                                  BCON_INT32 (10000000),
1891                                  "}",
1892                                  "}",
1893                                  "}",
1894                                  "]");
1895
1896             cursor = mongoc_collection_aggregate (
1897                collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
1898
1899             while (mongoc_cursor_next (cursor, &doc)) {
1900                str = bson_as_canonical_extended_json (doc, NULL);
1901                printf ("%s\n", str);
1902                bson_free (str);
1903             }
1904
1905             if (mongoc_cursor_error (cursor, &error)) {
1906                fprintf (stderr, "Cursor Failure: %s\n", error.message);
1907             }
1908
1909             mongoc_cursor_destroy (cursor);
1910             bson_destroy (pipeline);
1911          }
1912
1913          int
1914          main (int argc, char *argv[])
1915          {
1916             mongoc_client_t *client;
1917             mongoc_collection_t *collection;
1918             const char *uri_string =
1919                "mongodb://localhost:27017/?appname=aggregation-example";
1920             mongoc_uri_t *uri;
1921             bson_error_t error;
1922
1923             mongoc_init ();
1924
1925             uri = mongoc_uri_new_with_error (uri_string, &error);
1926             if (!uri) {
1927                fprintf (stderr,
1928                         "failed to parse URI: %s\n"
1929                         "error message:       %s\n",
1930                         uri_string,
1931                         error.message);
1932                return EXIT_FAILURE;
1933             }
1934
1935             client = mongoc_client_new_from_uri (uri);
1936             if (!client) {
1937                return EXIT_FAILURE;
1938             }
1939
1940             mongoc_client_set_error_api (client, 2);
1941             collection = mongoc_client_get_collection (client, "test", "zipcodes");
1942
1943             print_pipeline (collection);
1944
1945             mongoc_uri_destroy (uri);
1946             mongoc_collection_destroy (collection);
1947             mongoc_client_destroy (client);
1948
1949             mongoc_cleanup ();
1950
1951             return EXIT_SUCCESS;
1952          }
1953
1954
1955You should see a result like the following:
1956
1957          { "_id" : "PA", "total_pop" : 11881643 }
1958          { "_id" : "OH", "total_pop" : 10847115 }
1959          { "_id" : "NY", "total_pop" : 17990455 }
1960          { "_id" : "FL", "total_pop" : 12937284 }
1961          { "_id" : "TX", "total_pop" : 16986510 }
1962          { "_id" : "IL", "total_pop" : 11430472 }
1963          { "_id" : "CA", "total_pop" : 29760021 }
1964
1965       The  above  aggregation  pipeline is build from two pipeline operators:
1966       $group and $match.
1967
1968       The $group pipeline operator requires _id field where we specify group‐
1969       ing;  remaining fields specify how to generate composite value and must
1970       use one of the group aggregation functions: $addToSet,  $first,  $last,
1971       $max,  $min,  $avg, $push, $sum. The $match pipeline operator syntax is
1972       the same as the read operation query syntax.
1973
1974       The $group process reads all documents and for each state it creates  a
1975       separate document, for example:
1976
1977          { "_id" : "WA", "total_pop" : 4866692 }
1978
1979       The  total_pop field uses the $sum aggregation function to sum the val‐
1980       ues of all pop fields in the source documents.
1981
1982       Documents created by $group are piped to the $match pipeline  operator.
1983       It returns the documents with the value of total_pop field greater than
1984       or equal to 10 million.
1985
1986   Average City Population by State
1987       To get the first three states with the greatest average population  per
1988       city, use the following aggregation:
1989
1990          pipeline = BCON_NEW ("pipeline", "[",
1991             "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
1992             "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
1993             "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
1994             "{", "$limit", BCON_INT32 (3) "}",
1995          "]");
1996
1997       This aggregate pipeline produces:
1998
1999          { "_id" : "DC", "avg_city_pop" : 303450.0 }
2000          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
2001          { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
2002
2003       The  above aggregation pipeline is build from three pipeline operators:
2004       $group, $sort and $limit.
2005
2006       The first $group operator creates the following documents:
2007
2008          { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
2009
2010       Note, that the $group operator can't use nested  documents  except  the
2011       _id field.
2012
2013       The  second  $group  uses these documents to create the following docu‐
2014       ments:
2015
2016          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
2017
2018       These documents are sorted by  the  avg_city_pop  field  in  descending
2019       order.  Finally, the $limit pipeline operator returns the first 3 docu‐
2020       ments from the sorted set.
2021

DISTINCT AND MAPREDUCE

2023       This document provides some practical, simple, examples to  demonstrate
2024       the distinct and mapReduce commands.
2025
2026   Setup
2027       First   we'll   write   some  code  to  insert  sample  data:  doc-com‐
2028       mon-insert.c.INDENT 0.0
2029
2030          /* Don't try to compile this file on its own. It's meant to be #included
2031             by example code */
2032
2033          /* Insert some sample data */
2034          bool
2035          insert_data (mongoc_collection_t *collection)
2036          {
2037             mongoc_bulk_operation_t *bulk;
2038             enum N { ndocs = 4 };
2039             bson_t *docs[ndocs];
2040             bson_error_t error;
2041             int i = 0;
2042             bool ret;
2043
2044             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2045
2046             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
2047             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
2048             docs[2] = BCON_NEW (
2049                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
2050             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
2051
2052             for (i = 0; i < ndocs; i++) {
2053                mongoc_bulk_operation_insert (bulk, docs[i]);
2054                bson_destroy (docs[i]);
2055                docs[i] = NULL;
2056             }
2057
2058             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
2059
2060             if (!ret) {
2061                fprintf (stderr, "Error inserting data: %s\n", error.message);
2062             }
2063
2064             mongoc_bulk_operation_destroy (bulk);
2065             return ret;
2066          }
2067
2068          /* A helper which we'll use a lot later on */
2069          void
2070          print_res (const bson_t *reply)
2071          {
2072             char *str;
2073             BSON_ASSERT (reply);
2074             str = bson_as_canonical_extended_json (reply, NULL);
2075             printf ("%s\n", str);
2076             bson_free (str);
2077          }
2078
2079
2080   distinct command
2081       This is how to use the distinct command to get the distinct values of x
2082       which are greater than 1: distinct.c.INDENT 0.0
2083
2084          bool
2085          distinct (mongoc_database_t *database)
2086          {
2087             bson_t *command;
2088             bson_t reply;
2089             bson_error_t error;
2090             bool res;
2091             bson_iter_t iter;
2092             bson_iter_t array_iter;
2093             double val;
2094
2095             command = BCON_NEW ("distinct",
2096                                 BCON_UTF8 (COLLECTION_NAME),
2097                                 "key",
2098                                 BCON_UTF8 ("x"),
2099                                 "query",
2100                                 "{",
2101                                 "x",
2102                                 "{",
2103                                 "$gt",
2104                                 BCON_DOUBLE (1.0),
2105                                 "}",
2106                                 "}");
2107             res =
2108                mongoc_database_command_simple (database, command, NULL, &reply, &error);
2109             if (!res) {
2110                fprintf (stderr, "Error with distinct: %s\n", error.message);
2111                goto cleanup;
2112             }
2113
2114             /* Do something with reply (in this case iterate through the values) */
2115             if (!(bson_iter_init_find (&iter, &reply, "values") &&
2116                   BSON_ITER_HOLDS_ARRAY (&iter) &&
2117                   bson_iter_recurse (&iter, &array_iter))) {
2118                fprintf (stderr, "Couldn't extract \"values\" field from response\n");
2119                goto cleanup;
2120             }
2121
2122             while (bson_iter_next (&array_iter)) {
2123                if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
2124                   val = bson_iter_double (&array_iter);
2125                   printf ("Next double: %f\n", val);
2126                }
2127             }
2128
2129          cleanup:
2130             /* cleanup */
2131             bson_destroy (command);
2132             bson_destroy (&reply);
2133             return res;
2134          }
2135
2136
2137   mapReduce - basic example
2138       A  simple example using the map reduce framework. It simply adds up the
2139       number of occurrences of each "tag".
2140
2141       First define the map and reduce functions: constants.c.INDENT 0.0
2142
2143          const char *const COLLECTION_NAME = "things";
2144
2145          /* Our map function just emits a single (key, 1) pair for each tag
2146             in the array: */
2147          const char *const MAPPER = "function () {"
2148                                     "this.tags.forEach(function(z) {"
2149                                     "emit(z, 1);"
2150                                     "});"
2151                                     "}";
2152
2153          /* The reduce function sums over all of the emitted values for a
2154             given key: */
2155          const char *const REDUCER = "function (key, values) {"
2156                                      "var total = 0;"
2157                                      "for (var i = 0; i < values.length; i++) {"
2158                                      "total += values[i];"
2159                                      "}"
2160                                      "return total;"
2161                                      "}";
2162          /* Note We can't just return values.length as the reduce function
2163             might be called iteratively on the results of other reduce
2164             steps. */
2165
2166
2167Run the mapReduce command: map-reduce-basic.c.INDENT 0.0
2168
2169          bool
2170          map_reduce_basic (mongoc_database_t *database)
2171          {
2172             bson_t reply;
2173             bson_t *command;
2174             bool res;
2175             bson_error_t error;
2176             mongoc_cursor_t *cursor;
2177             const bson_t *doc;
2178
2179             bool query_done = false;
2180
2181             const char *out_collection_name = "outCollection";
2182             mongoc_collection_t *out_collection;
2183
2184             /* Empty find query */
2185             bson_t find_query = BSON_INITIALIZER;
2186
2187             /* Construct the mapReduce command */
2188
2189             /* Other arguments can also be specified here, like "query" or
2190                "limit" and so on */
2191             command = BCON_NEW ("mapReduce",
2192                                 BCON_UTF8 (COLLECTION_NAME),
2193                                 "map",
2194                                 BCON_CODE (MAPPER),
2195                                 "reduce",
2196                                 BCON_CODE (REDUCER),
2197                                 "out",
2198                                 BCON_UTF8 (out_collection_name));
2199             res =
2200                mongoc_database_command_simple (database, command, NULL, &reply, &error);
2201
2202             if (!res) {
2203                fprintf (stderr, "MapReduce failed: %s\n", error.message);
2204                goto cleanup;
2205             }
2206
2207             /* Do something with the reply (it doesn't contain the mapReduce results) */
2208             print_res (&reply);
2209
2210             /* Now we'll query outCollection to see what the results are */
2211             out_collection =
2212                mongoc_database_get_collection (database, out_collection_name);
2213             cursor = mongoc_collection_find_with_opts (
2214                out_collection, &find_query, NULL, NULL);
2215             query_done = true;
2216
2217             /* Do something with the results */
2218             while (mongoc_cursor_next (cursor, &doc)) {
2219                print_res (doc);
2220             }
2221
2222             if (mongoc_cursor_error (cursor, &error)) {
2223                fprintf (stderr, "ERROR: %s\n", error.message);
2224                res = false;
2225                goto cleanup;
2226             }
2227
2228          cleanup:
2229             /* cleanup */
2230             if (query_done) {
2231                mongoc_cursor_destroy (cursor);
2232                mongoc_collection_destroy (out_collection);
2233             }
2234
2235             bson_destroy (&reply);
2236             bson_destroy (command);
2237
2238             return res;
2239          }
2240
2241
2242   mapReduce - more complicated example
2243       You must have replica set running for this.
2244
2245       In this example we contact a secondary in the replica  set  and  do  an
2246       "inline"   map   reduce,  so  the  results  are  returned  immediately:
2247       map-reduce-advanced.c.INDENT 0.0
2248
2249          bool
2250          map_reduce_advanced (mongoc_database_t *database)
2251          {
2252             bson_t *command;
2253             bson_error_t error;
2254             bool res = true;
2255             mongoc_cursor_t *cursor;
2256             mongoc_read_prefs_t *read_pref;
2257             const bson_t *doc;
2258
2259             /* Construct the mapReduce command */
2260             /* Other arguments can also be specified here, like "query" or "limit"
2261                and so on */
2262
2263             /* Read the results inline from a secondary replica */
2264             command = BCON_NEW ("mapReduce",
2265                                 BCON_UTF8 (COLLECTION_NAME),
2266                                 "map",
2267                                 BCON_CODE (MAPPER),
2268                                 "reduce",
2269                                 BCON_CODE (REDUCER),
2270                                 "out",
2271                                 "{",
2272                                 "inline",
2273                                 "1",
2274                                 "}");
2275
2276             read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
2277             cursor = mongoc_database_command (
2278                database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
2279
2280             /* Do something with the results */
2281             while (mongoc_cursor_next (cursor, &doc)) {
2282                print_res (doc);
2283             }
2284
2285             if (mongoc_cursor_error (cursor, &error)) {
2286                fprintf (stderr, "ERROR: %s\n", error.message);
2287                res = false;
2288             }
2289
2290             mongoc_cursor_destroy (cursor);
2291             mongoc_read_prefs_destroy (read_pref);
2292             bson_destroy (command);
2293
2294             return res;
2295          }
2296
2297
2298   Running the Examples
2299       Here's how to run the example code basic-aggregation.c.INDENT 0.0
2300
2301          /*
2302           * Copyright 2016 MongoDB, Inc.
2303           *
2304           * Licensed under the Apache License, Version 2.0 (the "License");
2305           * you may not use this file except in compliance with the License.
2306           * You may obtain a copy of the License at
2307           *
2308           *   http://www.apache.org/licenses/LICENSE-2.0
2309           *
2310           * Unless required by applicable law or agreed to in writing, software
2311           * distributed under the License is distributed on an "AS IS" BASIS,
2312           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2313           * See the License for the specific language governing permissions and
2314           * limitations under the License.
2315           */
2316
2317
2318          #include <mongoc/mongoc.h>
2319          #include <stdio.h>
2320
2321
2322          #include "constants.c"
2323
2324          #include "../doc-common-insert.c"
2325          #include "distinct.c"
2326          #include "map-reduce-basic.c"
2327          #include "map-reduce-advanced.c"
2328
2329
2330          int
2331          main (int argc, char *argv[])
2332          {
2333             mongoc_database_t *database = NULL;
2334             mongoc_client_t *client = NULL;
2335             mongoc_collection_t *collection = NULL;
2336             mongoc_uri_t *uri = NULL;
2337             bson_error_t error;
2338             char *host_and_port = NULL;
2339             int exit_code = EXIT_FAILURE;
2340
2341             if (argc != 2) {
2342                fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
2343                fprintf (stderr,
2344                         "the connection string can be of the following forms:\n");
2345                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
2346                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
2347                fprintf (stderr,
2348                         "mongodb://user:pass@localhost:27017\t"
2349                         "local machine on port 27017, and authenticate with username "
2350                         "user and password pass\n");
2351                return exit_code;
2352             }
2353
2354             mongoc_init ();
2355
2356             if (strncmp (argv[1], "mongodb://", 10) == 0) {
2357                host_and_port = bson_strdup (argv[1]);
2358             } else {
2359                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
2360             }
2361
2362             uri = mongoc_uri_new_with_error (host_and_port, &error);
2363             if (!uri) {
2364                fprintf (stderr,
2365                         "failed to parse URI: %s\n"
2366                         "error message:       %s\n",
2367                         host_and_port,
2368                         error.message);
2369                goto cleanup;
2370             }
2371
2372             client = mongoc_client_new_from_uri (uri);
2373             if (!client) {
2374                goto cleanup;
2375             }
2376
2377             mongoc_client_set_error_api (client, 2);
2378             database = mongoc_client_get_database (client, "test");
2379             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
2380
2381             printf ("Inserting data\n");
2382             if (!insert_data (collection)) {
2383                goto cleanup;
2384             }
2385
2386             printf ("distinct\n");
2387             if (!distinct (database)) {
2388                goto cleanup;
2389             }
2390
2391             printf ("map reduce\n");
2392             if (!map_reduce_basic (database)) {
2393                goto cleanup;
2394             }
2395
2396             printf ("more complicated map reduce\n");
2397             if (!map_reduce_advanced (database)) {
2398                goto cleanup;
2399             }
2400
2401             exit_code = EXIT_SUCCESS;
2402
2403          cleanup:
2404             if (collection) {
2405                mongoc_collection_destroy (collection);
2406             }
2407
2408             if (database) {
2409                mongoc_database_destroy (database);
2410             }
2411
2412             if (client) {
2413                mongoc_client_destroy (client);
2414             }
2415
2416             if (uri) {
2417                mongoc_uri_destroy (uri);
2418             }
2419
2420             if (host_and_port) {
2421                bson_free (host_and_port);
2422             }
2423
2424             mongoc_cleanup ();
2425             return exit_code;
2426          }
2427
2428
2429If you want to try the advanced map reduce example with a secondary,  start  a
2430replica set (instructions for how to do this can be found here).
2431
2432Otherwise, just start an instance of MongoDB:
2433
2434          $ mongod
2435
2436       Now compile and run the example program:
2437
2438          $ cd examples/basic_aggregation/
2439          $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
2440          $ ./agg-example localhost
2441
2442          Inserting data
2443          distinct
2444          Next double: 2.000000
2445          Next double: 3.000000
2446          map reduce
2447          { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
2448          { "_id" : "cat", "value" : 63 }
2449          { "_id" : "dog", "value" : 42 }
2450          { "_id" : "mouse", "value" : 21 }
2451          more complicated map reduce
2452          { "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 }
2453

USING LIBMONGOC IN A MICROSOFT VISUAL STUDIO PROJECT

2455       Download and install libmongoc on your system, then open Visual Studio,
2456       select "File→New→Project...", and create a new Win32  Console  Applica‐
2457       tion.  [image]
2458
2459       Remember to switch the platform from 32-bit to 64-bit: [image]
2460
2461       Right-click  on  your  console application in the Solution Explorer and
2462       select "Properties". Choose to  edit  properties  for  "All  Configura‐
2463       tions",  expand  the  "C/C++"  options and choose "General". Add to the
2464       "Additional Include Directories" these paths:
2465
2466          C:\mongo-c-driver\include\libbson-1.0
2467          C:\mongo-c-driver\include\libmongoc-1.0
2468       [image]
2469
2470       (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
2471       include paths will be different.)
2472
2473       Also  in  the Properties dialog, expand the "Linker" options and choose
2474       "Input", and add to the "Additional Dependencies" these libraries:
2475
2476          C:\mongo-c-driver\lib\bson-1.0.lib
2477          C:\mongo-c-driver\lib\mongoc-1.0.lib
2478       [image]
2479
2480       Adding these libraries as dependencies provides linker symbols to build
2481       your  application,  but  to  actually run it, libbson's and libmongoc's
2482       DLLs must be in your executable path. Select "Debugging" in the Proper‐
2483       ties dialog, and set the "Environment" option to:
2484
2485          PATH=c:/mongo-c-driver/bin
2486       [image]
2487
2488       Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
2489
2490          #include <mongoc/mongoc.h>
2491
2492   Static linking
2493       Following  the  instructions  above,  you  have dynamically linked your
2494       application to the libbson and libmongoc  DLLs.  This  is  usually  the
2495       right  choice.  If  you  want  to  link statically instead, update your
2496       "Additional  Dependencies"  list  by  removing  bson-1.0.lib  and  mon‐
2497       goc-1.0.lib and replacing them with these libraries:
2498
2499          C:\mongo-c-driver\lib\bson-static-1.0.lib
2500          C:\mongo-c-driver\lib\mongoc-static-1.0.lib
2501          ws2_32.lib
2502          Secur32.lib
2503          Crypt32.lib
2504          BCrypt.lib
2505       [image]
2506
2507       (To  explain  the purpose of each library: bson-static-1.0.lib and mon‐
2508       goc-static-1.0.lib are static archives of the driver code.  The  socket
2509       library  ws2_32  is  required by libbson, which uses the socket routine
2510       gethostname to help guarantee ObjectId uniqueness. The  BCrypt  library
2511       is  used  by  libmongoc for SSL connections to MongoDB, and Secur32 and
2512       Crypt32 are required for enterprise authentication  methods  like  Ker‐
2513       beros.)
2514
2515       Finally,  define  two preprocessor symbols before including mongoc/mon‐
2516       goc.h in your stdafx.h:
2517
2518          #define BSON_STATIC
2519          #define MONGOC_STATIC
2520          #include <mongoc/mongoc.h>
2521
2522       Making these changes to your project is only required for static  link‐
2523       ing;  for  most people, the dynamic-linking instructions above are pre‐
2524       ferred.
2525
2526   Next Steps
2527       Now you can build and debug applications  in  Visual  Studio  that  use
2528       libbson  and  libmongoc. Proceed to making-a-connection in the tutorial
2529       to learn how connect to MongoDB and perform operations.
2530

CREATING INDEXES

2532       To create indexes on a MongoDB collection,  execute  the  createIndexes
2533       command   with   a  command  function  like  mongoc_database_write_com‐
2534       mand_with_opts or  mongoc_collection_write_command_with_opts.  See  the
2535       MongoDB Manual entry for the createIndexes command for details.
2536
2537   Example
2538       example-create-indexes.c.INDENT 0.0
2539
2540          /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
2541           * --libs libmongoc-1.0) */
2542
2543          /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */
2544
2545          #include <mongoc/mongoc.h>
2546          #include <stdio.h>
2547          #include <stdlib.h>
2548
2549          int
2550          main (int argc, char *argv[])
2551          {
2552             mongoc_client_t *client;
2553             const char *uri_string =
2554                "mongodb://127.0.0.1/?appname=create-indexes-example";
2555             mongoc_uri_t *uri;
2556             mongoc_database_t *db;
2557             const char *collection_name = "test";
2558             bson_t keys;
2559             char *index_name;
2560             bson_t *create_indexes;
2561             bson_t reply;
2562             char *reply_str;
2563             bson_error_t error;
2564             bool r;
2565
2566             mongoc_init ();
2567
2568             if (argc > 1) {
2569                uri_string = argv[1];
2570             }
2571
2572             if (argc > 2) {
2573                collection_name = argv[2];
2574             }
2575
2576             uri = mongoc_uri_new_with_error (uri_string, &error);
2577             if (!uri) {
2578                fprintf (stderr,
2579                         "failed to parse URI: %s\n"
2580                         "error message:       %s\n",
2581                         uri_string,
2582                         error.message);
2583                return EXIT_FAILURE;
2584             }
2585
2586             client = mongoc_client_new_from_uri (uri);
2587             if (!client) {
2588                return EXIT_FAILURE;
2589             }
2590
2591             mongoc_client_set_error_api (client, 2);
2592             db = mongoc_client_get_database (client, "test");
2593
2594             /* ascending index on field "x" */
2595             bson_init (&keys);
2596             BSON_APPEND_INT32 (&keys, "x", 1);
2597             index_name = mongoc_collection_keys_to_index_string (&keys);
2598             create_indexes = BCON_NEW ("createIndexes",
2599                                        BCON_UTF8 (collection_name),
2600                                        "indexes",
2601                                        "[",
2602                                        "{",
2603                                        "key",
2604                                        BCON_DOCUMENT (&keys),
2605                                        "name",
2606                                        BCON_UTF8 (index_name),
2607                                        "}",
2608                                        "]");
2609
2610             r = mongoc_database_write_command_with_opts (
2611                db, create_indexes, NULL /* opts */, &reply, &error);
2612
2613             reply_str = bson_as_json (&reply, NULL);
2614             printf ("%s\n", reply_str);
2615
2616             if (!r) {
2617                fprintf (stderr, "Error in createIndexes: %s\n", error.message);
2618             }
2619
2620             bson_free (index_name);
2621             bson_free (reply_str);
2622             bson_destroy (&reply);
2623             bson_destroy (create_indexes);
2624             mongoc_database_destroy (db);
2625             mongoc_uri_destroy (uri);
2626             mongoc_client_destroy (client);
2627
2628             mongoc_cleanup ();
2629
2630             return r ? EXIT_SUCCESS : EXIT_FAILURE;
2631          }
2632
2633

AIDS FOR DEBUGGING

2635   GDB
2636       This repository contains a .gdbinit file that contains helper functions
2637       to  aid  debugging  of  data  structures.  GDB  will  load  this   file
2638       automatically  if  you  have  added  the  directory  which contains the
2639       .gdbinit file to GDB's auto-load safe-path, and you start GDB from  the
2640       directory which holds the .gdbinit file.
2641
2642       You  can  see  the  safe-path  with  show  auto-load safe-path on a GDB
2643       prompt. You can configure it by setting it in ~/.gdbinit with:
2644
2645          add-auto-load-safe-path /path/to/mongo-c-driver
2646
2647       If you haven't added the path to your auto-load safe-path, or start GDB
2648       in another directory, load the file with:
2649
2650          source path/to/mongo-c-driver/.gdbinit
2651
2652       The  .gdbinit file defines the printbson function, which shows the con‐
2653       tents of a bson_t * variable.  If you have a  local  bson_t,  then  you
2654       must prefix the variable with a &.
2655
2656       An example GDB session looks like:
2657
2658          (gdb) printbson bson
2659          ALLOC [0x555556cd7310 + 0] (len=475)
2660          {
2661              'bool' : true,
2662              'int32' : NumberInt("42"),
2663              'int64' : NumberLong("3000000042"),
2664              'string' : "Stŕìñg",
2665              'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
2666              'utcDateTime' : UTCDateTime(1511277299031),
2667              'arrayOfInts' : [
2668                  '0' : NumberInt("1"),
2669                  '1' : NumberInt("2")
2670              ],
2671              'embeddedDocument' : {
2672                  'arrayOfStrings' : [
2673                      '0' : "one",
2674                      '1' : "two"
2675                  ],
2676                  'double' : 2.718280,
2677                  'notherDoc' : {
2678                      'true' : NumberInt("1"),
2679                      'false' : false
2680                  }
2681              },
2682              'binary' : Binary("02", "3031343532333637"),
2683              'regex' : Regex("@[a-z]+@", "im"),
2684              'null' : null,
2685              'js' : JavaScript("print foo"),
2686              'jsws' : JavaScript("print foo") with scope: {
2687                  'f' : NumberInt("42"),
2688                  'a' : [
2689                      '0' : 3.141593,
2690                      '1' : 2.718282
2691                  ]
2692              },
2693              'timestamp' : Timestamp(4294967295, 4294967295),
2694              'double' : 3.141593
2695          }
2696
2697   LLDB
2698       This  repository also includes a script that customizes LLDB's standard
2699       print command to print a bson_t or bson_t * as JSON:
2700
2701          (lldb) print b
2702          (bson_t) $0 = {"x": 1, "y": 2}
2703
2704       The custom bson command provides more options:
2705
2706          (lldb) bson --verbose b
2707          len=19
2708          flags=INLINE|STATIC
2709          {
2710            "x": 1,
2711            "y": 2
2712          }
2713          (lldb) bson --raw b
2714          '\x13\x00\x00\x00\x10x\x00\x01\x00\x00\x00\x10y\x00\x02\x00\x00\x00\x00'
2715
2716       Type help bson for a list of options.
2717
2718       The script requires a build of  libbson  with  debug  symbols,  and  an
2719       installation of PyMongo. Install PyMongo with:
2720
2721          python -m pip install pymongo
2722
2723       If  you  see  "No module named pip" then you must install pip, then run
2724       the previous command again.
2725
2726       Create a file ~/.lldbinit containing:
2727
2728          command script import /path/to/mongo-c-driver/lldb_bson.py
2729
2730       If you see "bson command installed by lldb_bson" at  the  beginning  of
2731       your LLDB session, you've installed the script correctly.
2732

AUTHOR

2734       MongoDB, Inc
2735
2737       2017-present, MongoDB, Inc
2738
2739
2740
2741
27421.13.1                           Jan 24, 2019                 MONGOC_GUIDES(3)
Impressum