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
and copydb
commands.
Setup¶
First we’ll write some code to insert sample data:
/* 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_with_opts (collection, 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)
{
char *str;
BSON_ASSERT (reply);
str = bson_as_canonical_extended_json (reply, NULL);
printf ("%s\n", str);
bson_free (str);
}
“explain” Command¶
This is how to use the explain
command in MongoDB 3.2+:
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:
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;
}
Running the Examples¶
/*
* 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/mongoc.h>
#include <stdio.h>
const char *COLLECTION_NAME = "things";
#include "../doc-common-insert.c"
#include "explain.c"
#include "copydb.c"
int
main (int argc, char *argv[])
{
mongoc_database_t *database = NULL;
mongoc_client_t *client = NULL;
mongoc_collection_t *collection = NULL;
mongoc_uri_t *uri = NULL;
bson_error_t error;
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 EXIT_FAILURE;
}
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;
uri = mongoc_uri_new_with_error (host_and_port, &error);
if (!uri) {
fprintf (stderr,
"failed to parse URI: %s\n"
"error message: %s\n",
host_and_port,
error.message);
res = EXIT_FAILURE;
goto cleanup;
}
client = mongoc_client_new_from_uri (uri);
if (!client) {
res = EXIT_FAILURE;
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 = EXIT_FAILURE;
goto cleanup;
}
printf ("explain\n");
if (!explain (collection)) {
res = EXIT_FAILURE;
goto cleanup;
}
if (other_host_and_port) {
printf ("copydb\n");
if (!copydb (client, other_host_and_port)) {
res = EXIT_FAILURE;
goto cleanup;
}
}
cleanup:
if (collection) {
mongoc_collection_destroy (collection);
}
if (database) {
mongoc_database_destroy (database);
}
if (client) {
mongoc_client_destroy (client);
}
if (uri) {
mongoc_uri_destroy (uri);
}
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 }