libmongo-client 0.1.8
Querying documents, part two

We learned how to make simple queries in the previous section, we'll be brave and do something much more advanced this time: we'll limit the query to documents that have their "yes?" field set to FALSE, and sort the results by the "n" field, in ascending order.

void
tut_sync_query_complex (void)
{
mongo_sync_connection *conn;
mongo_packet *p;
mongo_sync_cursor *cursor;
bson *query, *select;
gint i = 0;
conn = mongo_sync_connect ("localhost", 27017, FALSE);
if (!conn)
{
perror ("mongo_sync_connect()");
exit (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

After our routine connect, we build the query and select BSON objects:

query = bson_build_full (BSON_TYPE_DOCUMENT, "$query", TRUE,
bson_build (BSON_TYPE_BOOLEAN, "yes?", FALSE,
BSON_TYPE_DOCUMENT, "$orderby", TRUE,
bson_finish (query);
select = bson_build (BSON_TYPE_INT32, "hello", 1,
BSON_TYPE_INT32, "n", 1,
BSON_TYPE_INT32, "yes?", 1,
bson_finish (select);
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 * 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_DOCUMENT
4byte length + NULL terminated document
Definition: bson.h:68
@ BSON_TYPE_NONE
Only used for errors.
Definition: bson.h:65
@ BSON_TYPE_INT32
4byte integer
Definition: bson.h:84
@ BSON_TYPE_BOOLEAN
1byte boolean value
Definition: bson.h:73

Then we launch the query:

p = mongo_sync_cmd_query (conn, "tutorial.docs", 0,
0, 10, query, select);
if (!p)
{
perror ("mongo_sync_cmd_query()");
exit (1);
}
bson_free (query);
bson_free (select);
void bson_free(bson *b)
Free the memory associated with a BSON object.
Definition: bson.c:579
mongo_packet * mongo_sync_cmd_query(mongo_sync_connection *conn, const gchar *ns, gint32 flags, gint32 skip, gint32 ret, const bson *query, const bson *sel)
Send a query command to MongoDB.
Definition: mongo-sync.c:986

And make a cursor, just like last time:

cursor = mongo_sync_cursor_new (conn, "tutorial.docs", p);
if (!cursor)
{
perror ("mongo_sync_cursor_new()");
exit (1);
}
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

And that's pretty much the bulk of what we wanted to do: we just constructed our query and select BSON objects appropriately, and mongo_sync_cmd_query() does the rest.

But just to make sure our results are sane, we iterate over the returned documents, and print the fields we're interested in:

while (mongo_sync_cursor_next (cursor))
{
const char *hello;
gint32 n;
gboolean yes;
bson *result;
bson_cursor *c;
result = mongo_sync_cursor_get_data (cursor);
if (!result)
{
perror ("mongo_sync_cursor_get_data()");
exit (1);
}
c = bson_find (result, "hello");
if (!bson_cursor_get_string (c, &hello))
{
perror ("bson_cursor_get_string()");
exit (1);
}
c = bson_find (result, "n");
if (!bson_cursor_get_int32 (c, &n))
{
perror ("bson_cursor_get_int32()");
exit (1);
}
c = bson_find (result, "yes?");
if (!bson_cursor_get_boolean (c, &yes))
{
perror ("bson_cursor_get_boolean()");
exit (1);
}
printf ("Document #%d: hello=%s; n=%d; yes?=%s\n",
i, hello, n, (yes) ? "TRUE" : "FALSE");
bson_free (result);
i++;
gboolean bson_cursor_get_boolean(const bson_cursor *c, gboolean *dest)
Get the value stored at the cursor, as a boolean.
Definition: bson.c:1114
gboolean bson_cursor_get_string(const bson_cursor *c, const gchar **dest)
Get the value stored at the cursor, as string.
Definition: bson.c:1008
gboolean bson_cursor_get_int32(const bson_cursor *c, gint32 *dest)
Get the value stored at the cursor, as a 32-bit integer.
Definition: bson.c:1213
void bson_cursor_free(bson_cursor *c)
Delete a cursor, and free up all resources used by it.
Definition: bson.c:800
bson_cursor * bson_find(const bson *b, const gchar *name)
Create a new cursor positioned at a given key.
Definition: bson.c:956
gboolean mongo_sync_cursor_next(mongo_sync_cursor *cursor)
Iterate a MongoDB cursor.
Definition: mongo-sync-cursor.c:56
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
}

And when that is done, all that is left, is to clean up after ourselves:

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