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.
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);
}
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
4byte length + NULL terminated string
Definition: bson.h:80
"function(x){return x + 4.2;}", -1,
gboolean bson_finish(bson *b)
Finish a BSON object.
Definition: bson.c:521
bson * bson_build(bson_type type, const gchar *name,...)
Build a BSON object in one go.
Definition: bson.c:448
@ BSON_TYPE_ARRAY
4byte length + NULL terminated document
Definition: bson.h:69
@ BSON_TYPE_NONE
Only used for errors.
Definition: bson.h:65
@ 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:
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;
fprintf (stderr, "Can't run db.eval: %s\n", error);
g_free (error);
exit (1);
}
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):
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);
}
{
bson *result;
bson_cursor *c;
gdouble r;
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.
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);
}
{
perror ("bson_cursor_get_double()");
exit (1);
}
gboolean bson_cursor_get_double(const bson_cursor *c, gdouble *dest)
Get the value stored at the cursor, as a double.
Definition: bson.c:1020
bson_cursor * bson_find(const bson *b, const gchar *name)
Create a new cursor positioned at a given key.
Definition: bson.c:955
At this point, we have successfully extracted the data, so we can free up the BSON and cursor objects.
void bson_cursor_free(bson_cursor *c)
Delete a cursor, and free up all resources used by it.
Definition: bson.c:800
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!
void mongo_sync_cursor_free(mongo_sync_cursor *cursor)
Free a MongoDB cursor.
Definition: mongo-sync-cursor.c:83
return 0;
}
void mongo_sync_disconnect(mongo_sync_connection *conn)
Close and free a synchronous MongoDB connection.
Definition: mongo-sync.c:396