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:1021
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.
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