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

ADVANCED CONNECTIONS

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

CONNECTION POOLING

573       The  MongoDB  C  driver  has  two connection modes: single-threaded and
574       pooled. Single-threaded mode is  optimized  for  embedding  the  driver
575       within  languages  like  PHP. Multi-threaded programs should use pooled
576       mode: this mode minimizes the total connection  count,  and  in  pooled
577       mode  a  background thread monitors the MongoDB server topology, so the
578       program need not block to scan it.
579
580   Single Mode
581       In single mode, your program creates a mongoc_client_t directly:
582
583          mongoc_client_t *client = mongoc_client_new (
584             "mongodb://hostA,hostB/?replicaSet=my_rs");
585
586       The client connects on demand when your program first  uses  it  for  a
587       MongoDB  operation. Using a non-blocking socket per server, it begins a
588       check on each server concurrently, and uses the  asynchronous  poll  or
589       select  function  to  receive  events  from the sockets, until all have
590       responded or timed out. Put another way, in single-threaded mode the  C
591       Driver fans out to begin all checks concurrently, then fans in once all
592       checks have completed or timed out. Once the scan completes, the client
593       executes your program's operation and returns.
594
595       In  single  mode,  the client re-scans the server topology roughly once
596       per minute. If more than a minute has elapsed since the previous  scan,
597       the  next operation on the client will block while the client completes
598       its scan. This interval is configurable  with  heartbeatFrequencyMS  in
599       the connection string. (See mongoc_uri_t.)
600
601       A single client opens one connection per server in your topology: these
602       connections are used both for scanning the topology and performing nor‐
603       mal operations.
604
605   Pooled Mode
606       To activate pooled mode, create a mongoc_client_pool_t:
607
608          mongoc_uri_t *uri = mongoc_uri_new (
609             "mongodb://hostA,hostB/?replicaSet=my_rs");
610
611          mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
612
613       When your program first calls mongoc_client_pool_pop, the pool launches
614       a background thread for monitoring. The thread fans out and connects to
615       all  servers in the connection string, using non-blocking sockets and a
616       simple event loop. As it receives ismaster responses from the  servers,
617       it  updates  its view of the server topology. Each time the thread dis‐
618       covers a new server it begins connecting to it, and adds the new socket
619       to the list of non-blocking sockets in the event loop.
620
621       Each  thread  that  executes MongoDB operations must check out a client
622       from the pool:
623
624          mongoc_client_t *client = mongoc_client_pool_pop (pool);
625
626          /* use the client for operations ... */
627
628          mongoc_client_pool_push (pool, client);
629
630       The  mongoc_client_t  object  is  not  thread-safe,   only   the   mon‐
631       goc_client_pool_t is.
632
633       When  the  driver  is  in  pooled  mode,  your program's operations are
634       unblocked as soon as monitoring discovers a usable server. For example,
635       if  a  thread  in your program is waiting to execute an "insert" on the
636       primary, it is unblocked as soon as the primary is  discovered,  rather
637       than waiting for all secondaries to be checked as well.
638
639       The  pool  opens  one  connection  per  server for monitoring, and each
640       client opens its own connection to each server it uses for  application
641       operations.  The background thread re-scans the server topology roughly
642       every 10 seconds. This interval is configurable with  heartbeatFrequen‐
643       cyMS in the connection string. (See mongoc_uri_t.)
644
645       See  connection_pool_options  to  configure pool size and behavior, and
646       see mongoc_client_pool_t for an extended example  of  a  multi-threaded
647       program that uses the driver in pooled mode.
648

CURSORS

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

BULK WRITE OPERATIONS

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

AGGREGATION FRAMEWORK EXAMPLES

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

DISTINCT AND MAPREDUCE

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

USING LIBMONGOC IN A MICROSOFT VISUAL STUDIO PROJECT

2394       Download and install libmongoc on your system, then open Visual Studio,
2395       select "File→New→Project...", and create a new Win32  Console  Applica‐
2396       tion.  [image]
2397
2398       Remember to switch the platform from 32-bit to 64-bit: [image]
2399
2400       Right-click  on  your  console application in the Solution Explorer and
2401       select "Properties". Choose to  edit  properties  for  "All  Configura‐
2402       tions",  expand  the  "C/C++"  options and choose "General". Add to the
2403       "Additional Include Directories" these paths:
2404
2405          C:\mongo-c-driver\include\libbson-1.0
2406          C:\mongo-c-driver\include\libmongoc-1.0
2407       [image]
2408
2409       (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
2410       include paths will be different.)
2411
2412       Also  in  the Properties dialog, expand the "Linker" options and choose
2413       "Input", and add to the "Additional Dependencies" these libraries:
2414
2415          C:\mongo-c-driver\lib\bson-1.0.lib
2416          C:\mongo-c-driver\lib\mongoc-1.0.lib
2417       [image]
2418
2419       Adding these libraries as dependencies provides linker symbols to build
2420       your  application,  but  to  actually run it, libbson's and libmongoc's
2421       DLLs must be in your executable path. Select "Debugging" in the Proper‐
2422       ties dialog, and set the "Environment" option to:
2423
2424          PATH=c:/mongo-c-driver/bin
2425       [image]
2426
2427       Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
2428
2429          #include <mongoc/mongoc.h>
2430
2431   Static linking
2432       Following  the  instructions  above,  you  have dynamically linked your
2433       application to the libbson and libmongoc  DLLs.  This  is  usually  the
2434       right  choice.  If  you  want  to  link statically instead, update your
2435       "Additional  Dependencies"  list  by  removing  bson-1.0.lib  and  mon‐
2436       goc-1.0.lib and replacing them with these libraries:
2437
2438          C:\mongo-c-driver\lib\bson-static-1.0.lib
2439          C:\mongo-c-driver\lib\mongoc-static-1.0.lib
2440          ws2_32.lib
2441          Secur32.lib
2442          Crypt32.lib
2443          BCrypt.lib
2444       [image]
2445
2446       (To  explain  the purpose of each library: bson-static-1.0.lib and mon‐
2447       goc-static-1.0.lib are static archives of the driver code.  The  socket
2448       library  ws2_32  is  required by libbson, which uses the socket routine
2449       gethostname to help guarantee ObjectId uniqueness. The  BCrypt  library
2450       is  used  by  libmongoc for SSL connections to MongoDB, and Secur32 and
2451       Crypt32 are required for enterprise authentication  methods  like  Ker‐
2452       beros.)
2453
2454       Finally,  define  two preprocessor symbols before including mongoc/mon‐
2455       goc.h in your stdafx.h:
2456
2457          #define BSON_STATIC
2458          #define MONGOC_STATIC
2459          #include <mongoc/mongoc.h>
2460
2461       Making these changes to your project is only required for static  link‐
2462       ing;  for  most people, the dynamic-linking instructions above are pre‐
2463       ferred.
2464
2465   Next Steps
2466       Now you can build and debug applications  in  Visual  Studio  that  use
2467       libbson  and  libmongoc. Proceed to making-a-connection in the tutorial
2468       to learn how connect to MongoDB and perform operations.
2469

CREATING INDEXES

2471       To create indexes on a MongoDB collection,  execute  the  createIndexes
2472       command   with   a  command  function  like  mongoc_database_write_com‐
2473       mand_with_opts or  mongoc_collection_write_command_with_opts.  See  the
2474       MongoDB Manual entry for the createIndexes command for details.
2475
2476   Example
2477       example-create-indexes.c.INDENT 0.0
2478
2479          /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
2480           * --libs libmongoc-1.0) */
2481
2482          /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */
2483
2484          #include <mongoc/mongoc.h>
2485          #include <stdio.h>
2486          #include <stdlib.h>
2487
2488          int
2489          main (int argc, char *argv[])
2490          {
2491             mongoc_client_t *client;
2492             const char *uri_string =
2493                "mongodb://127.0.0.1/?appname=create-indexes-example";
2494             mongoc_uri_t *uri;
2495             mongoc_database_t *db;
2496             const char *collection_name = "test";
2497             bson_t keys;
2498             char *index_name;
2499             bson_t *create_indexes;
2500             bson_t reply;
2501             char *reply_str;
2502             bson_error_t error;
2503             bool r;
2504
2505             mongoc_init ();
2506
2507             if (argc > 1) {
2508                uri_string = argv[1];
2509             }
2510
2511             if (argc > 2) {
2512                collection_name = argv[2];
2513             }
2514
2515             uri = mongoc_uri_new_with_error (uri_string, &error);
2516             if (!uri) {
2517                fprintf (stderr,
2518                         "failed to parse URI: %s\n"
2519                         "error message:       %s\n",
2520                         uri_string,
2521                         error.message);
2522                return EXIT_FAILURE;
2523             }
2524
2525             client = mongoc_client_new_from_uri (uri);
2526             if (!client) {
2527                return EXIT_FAILURE;
2528             }
2529
2530             mongoc_client_set_error_api (client, 2);
2531             db = mongoc_client_get_database (client, "test");
2532
2533             /* ascending index on field "x" */
2534             bson_init (&keys);
2535             BSON_APPEND_INT32 (&keys, "x", 1);
2536             index_name = mongoc_collection_keys_to_index_string (&keys);
2537             create_indexes = BCON_NEW ("createIndexes",
2538                                        BCON_UTF8 (collection_name),
2539                                        "indexes",
2540                                        "[",
2541                                        "{",
2542                                        "key",
2543                                        BCON_DOCUMENT (&keys),
2544                                        "name",
2545                                        BCON_UTF8 (index_name),
2546                                        "}",
2547                                        "]");
2548
2549             r = mongoc_database_write_command_with_opts (
2550                db, create_indexes, NULL /* opts */, &reply, &error);
2551
2552             reply_str = bson_as_json (&reply, NULL);
2553             printf ("%s\n", reply_str);
2554
2555             if (!r) {
2556                fprintf (stderr, "Error in createIndexes: %s\n", error.message);
2557             }
2558
2559             bson_free (index_name);
2560             bson_free (reply_str);
2561             bson_destroy (&reply);
2562             bson_destroy (create_indexes);
2563             mongoc_database_destroy (db);
2564             mongoc_uri_destroy (uri);
2565             mongoc_client_destroy (client);
2566
2567             mongoc_cleanup ();
2568
2569             return r ? EXIT_SUCCESS : EXIT_FAILURE;
2570          }
2571
2572

AIDS FOR DEBUGGING

2574   GDB
2575       This repository contains a .gdbinit file that contains helper functions
2576       to  aid  debugging  of  data  structures.  GDB  will  load  this   file
2577       automatically  if  you  have  added  the  directory  which contains the
2578       .gdbinit file to GDB's auto-load safe-path, and you start GDB from  the
2579       directory which holds the .gdbinit file.
2580
2581       You  can  see  the  safe-path  with  show  auto-load safe-path on a GDB
2582       prompt. You can configure it by setting it in ~/.gdbinit with:
2583
2584          add-auto-load-safe-path /path/to/mongo-c-driver
2585
2586       If you haven't added the path to your auto-load safe-path, or start GDB
2587       in another directory, load the file with:
2588
2589          source path/to/mongo-c-driver/.gdbinit
2590
2591       The  .gdbinit file defines the printbson function, which shows the con‐
2592       tents of a bson_t * variable.  If you have a  local  bson_t,  then  you
2593       must prefix the variable with a &.
2594
2595       An example GDB session looks like:
2596
2597          (gdb) printbson bson
2598          ALLOC [0x555556cd7310 + 0] (len=475)
2599          {
2600              'bool' : true,
2601              'int32' : NumberInt("42"),
2602              'int64' : NumberLong("3000000042"),
2603              'string' : "Stŕìñg",
2604              'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
2605              'utcDateTime' : UTCDateTime(1511277299031),
2606              'arrayOfInts' : [
2607                  '0' : NumberInt("1"),
2608                  '1' : NumberInt("2")
2609              ],
2610              'embeddedDocument' : {
2611                  'arrayOfStrings' : [
2612                      '0' : "one",
2613                      '1' : "two"
2614                  ],
2615                  'double' : 2.718280,
2616                  'notherDoc' : {
2617                      'true' : NumberInt("1"),
2618                      'false' : false
2619                  }
2620              },
2621              'binary' : Binary("02", "3031343532333637"),
2622              'regex' : Regex("@[a-z]+@", "im"),
2623              'null' : null,
2624              'js' : JavaScript("print foo"),
2625              'jsws' : JavaScript("print foo") with scope: {
2626                  'f' : NumberInt("42"),
2627                  'a' : [
2628                      '0' : 3.141593,
2629                      '1' : 2.718282
2630                  ]
2631              },
2632              'timestamp' : Timestamp(4294967295, 4294967295),
2633              'double' : 3.141593
2634          }
2635
2636   LLDB
2637       This  repository also includes a script that customizes LLDB's standard
2638       print command to print a bson_t or bson_t * as JSON:
2639
2640          (lldb) print b
2641          (bson_t) $0 = {"x": 1, "y": 2}
2642
2643       The custom bson command provides more options:
2644
2645          (lldb) bson --verbose b
2646          len=19
2647          flags=INLINE|STATIC
2648          {
2649            "x": 1,
2650            "y": 2
2651          }
2652          (lldb) bson --raw b
2653          '\x13\x00\x00\x00\x10x\x00\x01\x00\x00\x00\x10y\x00\x02\x00\x00\x00\x00'
2654
2655       Type help bson for a list of options.
2656
2657       The script requires a build of  libbson  with  debug  symbols,  and  an
2658       installation of PyMongo. Install PyMongo with:
2659
2660          python -m pip install pymongo
2661
2662       If  you  see  "No module named pip" then you must install pip, then run
2663       the previous command again.
2664
2665       Create a file ~/.lldbinit containing:
2666
2667          command script import /path/to/mongo-c-driver/lldb_bson.py
2668
2669       If you see "bson command installed by lldb_bson" at  the  beginning  of
2670       your LLDB session, you've installed the script correctly.
2671

AUTHOR

2673       MongoDB, Inc
2674
2676       2017-present, MongoDB, Inc
2677
2678
2679
2680
26811.14.0                           Feb 22, 2019                 MONGOC_GUIDES(3)
Impressum