Loading...
Searching...
No Matches
Running custom commands

Sometimes it is necessary to run custom commands against a database, commands for which the library does not provide a convenience wrapper for.

In this tutorial, we will explore how to run server-side evaluations, using the $eval command.

#include <mongo.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int
main (void)
{
mongo_sync_connection *conn;
mongo_packet *p;
mongo_sync_cursor *cursor;
bson *eval;

First, we connect to the database, and create a BSON object that will hold our command, one that creates a function server side, that takes one argument, and returns the argument plus 4.2. The BSON object will also set up the arguments passed to this function, which, in our case, will be the number 1.

conn = mongo_sync_connect ("localhost", 27017, FALSE);
mongo_sync_connect
mongo_sync_connection * mongo_sync_connect(const gchar *address, gint port, gboolean slaveok)
Synchronously connect to a MongoDB server.
Definition mongo-sync.c:201
if (!conn)
{
perror ("mongo_sync_connect()");
exit (1);
}
eval = bson_build_full (BSON_TYPE_JS_CODE, "$eval", FALSE,
bson_build_full
bson * bson_build_full(bson_type type, const gchar *name, gboolean free_after,...)
Build a BSON object in one go, with full control.
Definition bson.c:484
BSON_TYPE_JS_CODE
@ BSON_TYPE_JS_CODE
4byte length + NULL terminated string
Definition bson.h:80
"function(x){return x + 4.2;}", -1,
BSON_TYPE_ARRAY, "args", TRUE,
bson_build (BSON_TYPE_INT32, "0", 1,
BSON_TYPE_NONE),
BSON_TYPE_NONE);
bson_finish (eval);
bson_finish
gboolean bson_finish(bson *b)
Finish a BSON object.
Definition bson.c:521
bson_build
bson * bson_build(bson_type type, const gchar *name,...)
Build a BSON object in one go.
Definition bson.c:448
BSON_TYPE_ARRAY
@ BSON_TYPE_ARRAY
4byte length + NULL terminated document
Definition bson.h:69
BSON_TYPE_NONE
@ BSON_TYPE_NONE
Only used for errors.
Definition bson.h:65
BSON_TYPE_INT32
@ BSON_TYPE_INT32
4byte integer
Definition bson.h:84

Once we have the connection and the query established, it is time to send the command:

p = mongo_sync_cmd_custom (conn, "test", eval);
mongo_sync_cmd_custom
mongo_packet * mongo_sync_cmd_custom(mongo_sync_connection *conn, const gchar *db, const bson *command)
Send a custom command to MongoDB.
Definition mongo-sync.c:1115
if (!p)
{
gchar *error = NULL;
mongo_sync_cmd_get_last_error (conn, "test", &error);
fprintf (stderr, "Can't run db.eval: %s\n", error);
g_free (error);
exit (1);
}
mongo_sync_cmd_get_last_error
gboolean mongo_sync_cmd_get_last_error(mongo_sync_connection *conn, const gchar *db, gchar **error)
Get the last error from MongoDB.
Definition mongo-sync.c:1399

We then create a cursor from the returned packet, and iterate over it (in case there are multiple documents returned - which will not be the case here):

cursor = mongo_sync_cursor_new (conn, "test", p);
mongo_sync_cursor_new
mongo_sync_cursor * mongo_sync_cursor_new(mongo_sync_connection *conn, const gchar *ns, mongo_packet *packet)
Create a new MongoDB Cursor.
Definition mongo-sync-cursor.c:28
if (!cursor)
{
perror ("mongo_sync_cursor_new()");
exit (1);
}
while (mongo_sync_cursor_next (cursor))
{
bson *result;
bson_cursor *c;
gdouble r;
mongo_sync_cursor_next
gboolean mongo_sync_cursor_next(mongo_sync_cursor *cursor)
Iterate a MongoDB cursor.
Definition mongo-sync-cursor.c:56

We want to retrieve each document, and find the retval key in them, because that's where $eval returns the results to us.

result = mongo_sync_cursor_get_data (cursor);
mongo_sync_cursor_get_data
bson * mongo_sync_cursor_get_data(mongo_sync_cursor *cursor)
Retrieve the BSON document at the cursor's position.
Definition mongo-sync-cursor.c:99
if (!result)
{
perror ("mongo_sync_cursor_get_data()");
exit (1);
}
c = bson_find (result, "retval");
if (!bson_cursor_get_double (c, &r))
{
perror ("bson_cursor_get_double()");
exit (1);
}
bson_cursor_get_double
gboolean bson_cursor_get_double(const bson_cursor *c, gdouble *dest)
Get the value stored at the cursor, as a double.
Definition bson.c:1021
bson_find
bson_cursor * bson_find(const bson *b, const gchar *name)
Create a new cursor positioned at a given key.
Definition bson.c:956

At this point, we have successfully extracted the data, so we can free up the BSON and cursor objects.

bson_cursor_free (c);
bson_cursor_free
void bson_cursor_free(bson_cursor *c)
Delete a cursor, and free up all resources used by it.
Definition bson.c:800
bson_free (result);
bson_free
void bson_free(bson *b)
Free the memory associated with a BSON object.
Definition bson.c:579

And finally, print the result:

printf ("Result: %2.1f\n", r);
}

And that's it! We clean up, disconnect, and that's all there is to running custom commands!

mongo_sync_cursor_free (cursor);
mongo_sync_cursor_free
void mongo_sync_cursor_free(mongo_sync_cursor *cursor)
Free a MongoDB cursor.
Definition mongo-sync-cursor.c:83
mongo_sync_disconnect (conn);
return 0;
}
mongo_sync_disconnect
void mongo_sync_disconnect(mongo_sync_connection *conn)
Close and free a synchronous MongoDB connection.
Definition mongo-sync.c:396