This page provides you with a little help getting started with the new MongoDB C driver.
For more information on the C API, please refer to the online API Documentation for the C driver.
See the relevant section below for your given operating system. This tutorial will install the newest version of the driver available from the github git repository.
First, ensure you have the required dependencies installed. We will assume a Fedora based operating system, but it should not be much different on your platform. OS X users often use brew
, FreeBSD has pkg
, and Solaris has pkgin
.
sudo yum install git gcc automake autoconf libtool pkg-config
If you would like SSL support, make sure you have openssl installed.
sudo yum install openssl-devel
If you would like Kerberos support, make sure you have cyrus-sasl installed.
sudo yum install cyrus-sasl-devel
Now let's fetch the code, build, and install it. You may want to replace --prefix
and --libdir
with where you want the driver installed. The default is /usr/local
and /usr/local/lib
. However, many systems do not include this in LD_LIBRARY_PATH
(or DYLD_LIBRARY_PATH
in the case of OS X).
After running ./autogen.sh
, you will see the newly generated ./configure
script. It is automatically run for you by ./autogen.sh
. If you run ./configure --help
, you can see the full set of options to customize your build for your exact requirements.
git clone git://github.com/mongodb/mongo-c-driver.git
cd mongo-c-driver
./autogen.sh --prefix=/usr --libdir=/usr/lib64
gmake
sudo gmake install
Install the dependencies for Windows. You will need git
to fetch the code, and cmake
to bootstrap the build. You will also need Visual Studio 2010 or newer. The free express version should work fine. The following assumes Visual Studio 2010.
git clone git://github.com/mongodb/mongo-c-driver.git
cd src\libbson
cmake -DCMAKE_INSTALL_PREFIX=C:\usr -G "Visual Studio 10 Win64" .
msbuild.exe ALL_BUILD.vcxproj
msbuild.exe INSTALL.vcxproj
cd ..\..
cmake -DCMAKE_INSTALL_PREFIX=C:\usr -DBSON_ROOT_DIR=C:\usr -G "Visual Studio 10 Win64" .
msbuild.exe ALL_BUILD.vcxproj
msbuild.exe INSTALL.vcxproj
The mongo-c-driver provides a convenient way to access MongoDB regardless of your cluster configuration. It will handle connecting to single servers, replica sets, and sharded clusters.
In the following, we will create a new mongoc_client_t
that will be used to connect to localhost:27017
.
#include <mongoc.h>
int
main (int argc,
char *argv[])
{
mongoc_client_t *client;
/* create a new client instance */
client = mongoc_client_new ("mongodb://localhost:27017");
/* now release it */
mongoc_client_destroy (client);
return 0;
}
And to compile it:
gcc -o test1 test.c $(pkg-config --cflags --libs libmongoc-1.0)
Alternatively, if you don't have pkg-config
on your system, you can manually manage your include paths and libraries.
gcc -o test1 test.c -I/usr/local/include -lmongoc-1.0
It is important to note that creating a new instance of mongoc_client_t
does not immediately connect to your MongoDB instance. This is performed lazily as needed.
To connect to a replica set, specify the replica set name using the ?replicaSet=mysetname
URI option. You can also specify a seed list if you would like to be able to connect to multiple nodes in the case that one is down when initializing the connection.
mongoc_uri_t *uri = mongoc_uri_new ("mongodb://host1:27017,host2:27017/?replicaSet=mysetname");
This is just like connecting to a replica set, but you do not need to specify a replica set name.
mongoc_uri_t *uri = mongoc_uri_new ("mongodb://host1:27017,host2:27017/");
You can specify a path to a Unix domain socket instead of an IPv4 or IPv6 address. Simply pass the path to the socket. The socket path MUST end in ".sock".
mongoc_uri_t *uri = mongoc_uri_new ("mongodb:///tmp/mysocket.sock");
The mongo-c-driver will automatically resolved IPv6 address from host names. But if you would like to specify the IPv6 address directly, wrap the address in []
.
mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017/");
If you would like to use authentication with your MongoDB instance, you can simply provide the credentials as part of the URI string.
mongoc_uri_t *uri = mongoc_uri_new ("mongodb://username:password@localhost/");
To enable SSL from your client, simply add the ?ssl=true
option to the URI.
mongoc_uri_t *uri = mongoc_uri_new ("mongodb://localhost/?ssl=true");
If you are one of the people on planet Earth lucky enough to use Kerberos, you can enable that simply with the following URI. Note the escaping of the principal as it would duplicate the @
sign in the URI.
mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user%40realm.cc@localhost:27017/?authmechanism=GSSAPI");
See the full variety of connection URI options at http://docs.mongodb.org/manual/reference/connection-string/.
Now that we have a client, we can fetch a handle to the collection or database using the following. Keep in mind that these functions return newly allocated structures, and therefore they need to be released when we are done using them.
mongoc_collection_t *collection;
mongoc_database_t *database;
database = mongoc_client_get_database (client, "test");
collection = mongoc_client_get_collection (client, "test", "test");
mongoc_collection_destroy (collection);
mongoc_database_destroy (database);
Now that we know how to get a handle to a database and collection, let's insert a document and then query it back!
#include <mongoc.h>
#include <stdio.h>
#include <stdlib.h>
int
main (int argc,
char *argv[])
{
mongoc_collection_t *collection;
mongoc_client_t *client;
mongoc_cursor_t *cursor;
const bson_t *item;
bson_error_t error;
bson_oid_t oid;
bson_t query;
bson_t doc;
char *str;
bool r;
/* get a handle to our collection */
client = mongoc_client_new ("mongodb://localhost:27017");
collection = mongoc_client_get_collection (client, "test", "test");
/* insert a document */
bson_init (&doc);
bson_oid_init (&oid, NULL);
BSON_APPEND_OID (&doc, "_id", &oid);
BSON_APPEND_UTF8 (&doc, "hello", "world!");
r = mongoc_collection_insert (collection, MONGOC_INSERT_NONE, &doc, NULL, &error);
if (!r) {
fprintf (stderr, "%s\n", error.message);
return EXIT_FAILURE;
}
/* build a query to execute */
bson_init (&query);
BSON_APPEND_OID (&query, "_id", &oid);
/* execute the query and iterate the results */
cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, NULL, NULL);
while (mongoc_cursor_next (cursor, &item)) {
str = bson_as_json (item, NULL);
printf ("%s\n", str);
bson_free (str);
}
/* release everything */
mongoc_cursor_destroy (cursor);
mongoc_collection_destroy (collection);
mongoc_client_destroy (client);
bson_destroy (&query);
bson_destroy (&doc);
return 0;
}
Creating BSON documents in the imperative way is time consuming and can be prone to error. BSON C Notation, or BCON
for short, is a way to create documents that looks much closer to the document format you are trying to create. While the type safety is less than your typical imperative code, it can make for much cleaner C code.
#include <bcon.h>
#include <bson.h>
#include <stdio.h>
int
main (int argc,
char *argv[])
{
bson_t *doc;
doc = BCON_NEW ("$set", "{",
"name", BCON_UTF8 ("bambino"),
"$push", "{",
"wins", BCON_INT32 (1),
"}",
"}");
str = bson_as_json (doc, NULL);
printf ("%s\n", str);
bson_free (str);
bson_destroy (doc);
return 0;
}
To count the number of documents in a collection we need to build a query selector. An empty query selector would count all documents in a collection.
#include <mongoc.h>
#include <stdio.h>
#include <stdlib.h>
int
main (int argc,
char *argv[])
{
mongoc_collection_t *collection;
mongoc_client_t *client;
bson_error_t error;
int64_t count;
bson_t query;
bool r;
/* get a handle to our collection */
client = mongoc_client_new ("mongodb://localhost:27017");
collection = mongoc_client_get_collection (client, "test", "test");
/* count all documents matching {hello: "world!"} */
bson_init (&query);
BSON_APPEND_UTF8 (&query, "hello", "world!");
count = mongoc_collection_count (collection, MONGOC_QUERY_NONE, &query, 0, 0, NULL, &error);
if (count < 0) {
fprintf (stderr, "%s\n", error.message);
return EXIT_FAILURE;
}
printf ("Found %"PRId64" documents in %s\n",
count,
mongoc_collection_get_name (collection));
/* release everything */
mongoc_collection_destroy (collection);
mongoc_client_destroy (client);
bson_destroy (&query);
return 0;
}
The mongo-c-driver is threading unaware for the vast majority of things. This means it is up to you to guarantee thread-safety. However, mongoc_client_pool_t
is thread-safe. It is used to fetch a mongoc_client_t
in a thread-safe manner. After retrieving a client from the pool, the client structure should be considered owned by the calling thread. When the thread is finished, it should be placed back into the pool.
#include <mongoc.h>
#include <pthread.h>
#define N_THREADS 10
static void *
worker (void *data)
{
mongoc_client_pool_t *pool = data;
mongoc_client_t *client;
client = mongoc_client_pool_pop (pool);
/* do something */
mongoc_client_pool_push (pool, client);
return NULL;
}
int
main (int argc,
char *argv[])
{
mongoc_client_pool_t *pool;
mongoc_uri_t *uri;
pthread_t threads[N_THREADS];
uri = mongoc_uri_new ("mongodb://localhost/");
pool = mongoc_client_pool_new (uri);
for (i = 0; i < N_THREADS; i++) {
pthread_create (&threads[i], NULL, worker, pool);
}
for (i = 0; i < N_THREADS; i++) {
pthread_join (threads[i], NULL);
}
mongoc_client_pool_destroy (pool);
mongoc_uri_destroy (uri);
return 0;
}
There are helpers to make it easy to execute commands. The helper exists for client, database, and collection structures. Alternatively, you can use the _simple()
variant if you do not need a cursor back from the result. This is convenient for commands that return a single document.
#include <bcon.h>
#include <bson.h>
#include <mongoc.h>
#include <stdio.h>
int
main (int argc,
char *argv[])
{
mongoc_client_t *client;
bson_t *command;
bson_t reply;
char *str;
bool r;
client = mongoc_client_new ("mongodb://localhost:27017/");
command = BCON_NEW ("ping", BCON_INT32 (1));
r = mongoc_client_command_simple (client, "admin", command, NULL, &reply, &error);
if (!r) {
printf ("%s\n", error.message);
return 1;
}
str = bson_as_json (&reply, NULL);
printf ("%s\n", str);
bson_free (str);
bson_destroy (&reply);
bson_destroy (command);
mongoc_client_destroy (client);
return 0;
}