Common Tasks — MongoDB C Driver 1.6.3

- MongoDB C Driver 1.6.3 »
- Guides

# Common Tasks

Drivers for some other languages provide helper functions to perform certain common tasks. In the C Driver we must explicitly build commands to send to the server.

This snippet contains example code for the `explain`, `copydb` and `cloneCollection` commands.

## Setup

First we'll write some code to insert sample data:

doc-common-insert.c

    /* Don't try to compile this file on its own. It's meant to be #included
       by example code */

    /* Insert some sample data */
    bool
    insert_data (mongoc_collection_t *collection)
    {
       mongoc_bulk_operation_t *bulk;
       enum N { ndocs = 4 };
       bson_t *docs[ndocs];
       bson_error_t error;
       int i = 0;
       bool ret;

       bulk = mongoc_collection_create_bulk_operation (collection, true, NULL);

       docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
       docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
       docs[2] = BCON_NEW (
          "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
       docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");

       for (i = 0; i < ndocs; i++) {
          mongoc_bulk_operation_insert (bulk, docs[i]);
          bson_destroy (docs[i]);
          docs[i] = NULL;
       }

       ret = mongoc_bulk_operation_execute (bulk, NULL, &error);

       if (!ret) {
          fprintf (stderr, "Error inserting data: %s\n", error.message);
       }

       mongoc_bulk_operation_destroy (bulk);
       return ret;
    }

    /* A helper which we'll use a lot later on */
    void
    print_res (const bson_t *reply)
    {
       BSON_ASSERT (reply);
       char *str = bson_as_json (reply, NULL);
       printf ("%s\n", str);
       bson_free (str);
    }

## "explain" Command

This is how to use the `explain` command in MongoDB 3.2+:

explain.c

    bool
    explain (mongoc_collection_t *collection)
    {
       bson_t *command;
       bson_t reply;
       bson_error_t error;
       bool res;

       command = BCON_NEW ("explain",
                           "{",
                           "find",
                           BCON_UTF8 (COLLECTION_NAME),
                           "filter",
                           "{",
                           "x",
                           BCON_INT32 (1),
                           "}",
                           "}");
       res = mongoc_collection_command_simple (
          collection, command, NULL, &reply, &error);
       if (!res) {
          fprintf (stderr, "Error with explain: %s\n", error.message);
          goto cleanup;
       }

       /* Do something with the reply */
       print_res (&reply);

    cleanup:
       bson_destroy (&reply);
       bson_destroy (command);
       return res;
    }

## "copydb" Command

This example requires two instances of mongo to be running.

Here's how to use the `copydb` command to copy a database from another instance of MongoDB:

copydb.c

    bool
    copydb (mongoc_client_t *client, const char *other_host_and_port)
    {
       mongoc_database_t *admindb;
       bson_t *command;
       bson_t reply;
       bson_error_t error;
       bool res;

       BSON_ASSERT (other_host_and_port);
       /* Must do this from the admin db */
       admindb = mongoc_client_get_database (client, "admin");

       command = BCON_NEW ("copydb",
                           BCON_INT32 (1),
                           "fromdb",
                           BCON_UTF8 ("test"),
                           "todb",
                           BCON_UTF8 ("test2"),

                           /* If you want from a different host */
                           "fromhost",
                           BCON_UTF8 (other_host_and_port));
       res =
          mongoc_database_command_simple (admindb, command, NULL, &reply, &error);
       if (!res) {
          fprintf (stderr, "Error with copydb: %s\n", error.message);
          goto cleanup;
       }

       /* Do something with the reply */
       print_res (&reply);

    cleanup:
       bson_destroy (&reply);
       bson_destroy (command);
       mongoc_database_destroy (admindb);

       return res;
    }

## "cloneCollection" Command

This example requires two instances of mongo to be running.

Here's an example of the `cloneCollection` command to clone a collection from another instance of MongoDB:

clone-collection.c

    bool
    clone_collection (mongoc_database_t *database, const char *other_host_and_port)
    {
       bson_t *command;
       bson_t reply;
       bson_error_t error;
       bool res;

       BSON_ASSERT (other_host_and_port);
       command = BCON_NEW ("cloneCollection",
                           BCON_UTF8 ("test.remoteThings"),
                           "from",
                           BCON_UTF8 (other_host_and_port),
                           "query",
                           "{",
                           "x",
                           BCON_INT32 (1),
                           "}");
       res =
          mongoc_database_command_simple (database, command, NULL, &reply, &error);
       if (!res) {
          fprintf (stderr, "Error with clone: %s\n", error.message);
          goto cleanup;
       }

       /* Do something with the reply */
       print_res (&reply);

    cleanup:
       bson_destroy (&reply);
       bson_destroy (command);

       return res;
    }

## Running the Examples

common-operations.c

    /*
     * Copyright 2016 MongoDB, Inc.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    #include <mongoc.h>
    #include <stdio.h>

    const char *COLLECTION_NAME = "things";

    #include "../doc-common-insert.c"
    #include "explain.c"
    #include "copydb.c"
    #include "clone-collection.c"

    int
    main (int argc, char *argv[])
    {
       mongoc_database_t *database = NULL;
       mongoc_client_t *client = NULL;
       mongoc_collection_t *collection = NULL;
       char *host_and_port;
       int res = 0;
       char *other_host_and_port = NULL;

       if (argc < 2 || argc > 3) {
          fprintf (stderr,
                   "usage: %s MONGOD-1-CONNECTION-STRING "
                   "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
                   argv[0]);
          fprintf (stderr,
                   "MONGOD-1-CONNECTION-STRING can be "
                   "of the following forms:\n");
          fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
          fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
          fprintf (stderr,
                   "mongodb://user:pass@localhost:27017\t"
                   "local machine on port 27017, and authenticate with username "
                   "user and password pass\n");
          return 1;
       }

       mongoc_init ();

       if (strncmp (argv[1], "mongodb://", 10) == 0) {
          host_and_port = bson_strdup (argv[1]);
       } else {
          host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
       }
       other_host_and_port = argc > 2 ? argv[2] : NULL;

       client = mongoc_client_new (host_and_port);

       if (!client) {
          fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port);
          res = 2;
          goto cleanup;
       }

       mongoc_client_set_error_api (client, 2);
       database = mongoc_client_get_database (client, "test");
       collection = mongoc_database_get_collection (database, COLLECTION_NAME);

       printf ("Inserting data\n");
       if (!insert_data (collection)) {
          res = 3;
          goto cleanup;
       }

       printf ("explain\n");
       if (!explain (collection)) {
          res = 4;
          goto cleanup;
       }

       if (other_host_and_port) {
          printf ("copydb\n");
          if (!copydb (client, other_host_and_port)) {
             res = 5;
             goto cleanup;
          }

          printf ("clone collection\n");
          if (!clone_collection (database, other_host_and_port)) {
             res = 6;
             goto cleanup;
          }
       }

    cleanup:
       if (collection) {
          mongoc_collection_destroy (collection);
       }

       if (database) {
          mongoc_database_destroy (database);
       }

       if (client) {
          mongoc_client_destroy (client);
       }

       bson_free (host_and_port);
       mongoc_cleanup ();
       return res;
    }

First launch two separate instances of mongod (must be done from separate shells):

    $ mongod

    $ mkdir /tmp/db2$ mongod --dbpath /tmp/db2 --port 27018 # second instance

Now compile and run the example program:

    $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
    Inserting data
    explain
    {
       "executionStats" : {
          "allPlansExecution" : [],
          "executionStages" : {
             "advanced" : 19,
             "direction" : "forward" ,
             "docsExamined" : 76,
             "executionTimeMillisEstimate" : 0,
             "filter" : {
                "x" : {
                   "$eq" : 1
                }
             },
             "invalidates" : 0,
             "isEOF" : 1,
             "nReturned" : 19,
             "needTime" : 58,
             "needYield" : 0,
             "restoreState" : 0,
             "saveState" : 0,
             "stage" : "COLLSCAN" ,
             "works" : 78
          },
          "executionSuccess" : true,
          "executionTimeMillis" : 0,
          "nReturned" : 19,
          "totalDocsExamined" : 76,
          "totalKeysExamined" : 0
       },
       "ok" : 1,
       "queryPlanner" : {
          "indexFilterSet" : false,
          "namespace" : "test.things",
          "parsedQuery" : {
             "x" : {
                "$eq" : 1
             }
          },
          "plannerVersion" : 1,
          "rejectedPlans" : [],
          "winningPlan" : {
             "direction" : "forward" ,
             "filter" : {
                "x" : {
                   "$eq" : 1
                }
             },
             "stage" : "COLLSCAN"
          }
       },
       "serverInfo" : {
          "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
          "host" : "MacBook-Pro-57.local",
          "port" : 27017,
          "version" : "3.2.6"
       }
    }
    copydb
    { "ok" : 1 }
    clone collection
    { "ok" : 1 }

Created using Sphinx 1.5.3, based on Sphinx Readable Theme.