summaryrefslogtreecommitdiff
path: root/docs/tutorial/tut_bson_traverse.h
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tutorial/tut_bson_traverse.h')
-rw-r--r--docs/tutorial/tut_bson_traverse.h135
1 files changed, 135 insertions, 0 deletions
diff --git a/docs/tutorial/tut_bson_traverse.h b/docs/tutorial/tut_bson_traverse.h
new file mode 100644
index 0000000..712ff71
--- /dev/null
+++ b/docs/tutorial/tut_bson_traverse.h
@@ -0,0 +1,135 @@
+/** @page tut_bson_traverse Traversing BSON objects
+ *
+ * Now that we can build BSON objects (see the @ref tut_bson_build
+ * "previous section"), it is time that we learn how to find things in
+ * them!
+ *
+ * We will use the same JSON structure as in the previous example.
+ *
+ * @dontinclude tut_bson_traverse.c
+ * First, we include our stuff, and create a function that gives us a
+ * BSON object to work with:
+ * @until return b
+ * @line }
+ *
+ * @until {
+ * First, we need a variable to hold our BSON object, and a cursor,
+ * with which we can find the keys we're looking for.
+ * @until bson_cursor
+ *
+ * Then we need a few variables to store the retrieved information
+ * in. Extracting data out of a BSON object involves storing them in a
+ * variable of our own.
+ * @until v_str
+ *
+ * @until doc = tut_bson
+ *
+ * In order to find something in a BSON object, we must know the keys
+ * name. There's two ways to find information within a BSON object:
+ * bson_find() and bson_cursor_next() and its friends.
+ *
+ * The first takes a BSON object, and returns a cursor that points to
+ * the key we wanted to find (or to NULL, if it was not found, of
+ * course). We can then extract that value, and either close the
+ * cursor, or use bson_cursor_next() to iterate over the rest of the
+ * keys.
+ *
+ * The advantage of bson_find() is that we can jump to a specific key
+ * easily, but at the cost of having to use a new cursor every time,
+ * which in turn will start searching from the beginning of a BSON
+ * document.
+ *
+ * On the other hand, bson_cursor_next() remembers its position, and
+ * jumping to the next key is straightforward. It can also be used in
+ * conjunction with bson_find() to locate the first key we're
+ * interested in, and move on to the next until we're done.
+ *
+ * For our first traversal example, lets say we want to see who the
+ * author of our BSON object is! We can extract that information by
+ * locating the "author" key, and retrieving the string contents:
+ * @until printf
+ *
+ * Now, if we also want to know whether the 'inline' key is set to
+ * true or false, we have two options: if we know the exact order of
+ * keys, we can use the appropriate amount of bson_cursor_next()
+ * calls:
+ * @until printf
+ *
+ * But this is not only ugly, it's very sensitive to the order of the
+ * keys, and it's hard to understand aswell, without being familiar
+ * with the document's structure.
+ *
+ * So, while it is a little more inconvenient, it's better to find the
+ * key in some other way. But first, let's close our cursor, as we'll
+ * need to start again anyway...
+ * @until bson_cursor_free
+ *
+ * First, we'll go the easy route, and use bson_find():
+ * @until printf
+ *
+ * Now, the downside of this, is that we ran through the BSON object
+ * twice. Well, once and a little, since the "author" key was the
+ * first. But using bson_find() this way has the potential of
+ * traversing through a document multiple times.
+ *
+ * Now, if we know the one key always comes after another, then we can
+ * use bson_cursor_next() to help us find it, without having to
+ * restart from the beginning. We do this by extracting the key name
+ * from the cursor, and comparing it to whatever we're searching for:
+ * @until printf
+ *
+ * Now the above is still picky about key order, but it's at least
+ * more flexible: we can put any number of keys between author and
+ * inline, and it will work. In most cases, that's good enough. In
+ * every other case, where we have no idea about key ordering,
+ * bson_find() is still there for us.
+ *
+ * Even better, the library itself provides a function that does
+ * something similar: it takes a cursor and a key name, and attempts
+ * to find the key past the cursor's current position. So if we
+ * already have the author, we can use this function to find the next
+ * inline key aswell:
+ * @until printf
+ *
+ * However, if we suspect that a key might come after the current
+ * position, but we're not sure, and still want to find the key with
+ * as little code as possible, we shall not despair! The
+ * bson_cursor_find() function does just that: it will try to find the
+ * key starting from the current position, and wrap over once if it
+ * can't.
+ *
+ * Lets see how it works! First, we find a key in the middle:
+ * @until bson_find
+ *
+ * Now that we have a key in the middle, lets find a key after it:
+ * @until get_boolean
+ *
+ * And once we have that - and we're at the end of our BSON object -,
+ * lets try finding the author key aswell:
+ * @until get_string
+ *
+ * That works, just like that! To verify, we go ahead and print the
+ * results, which should be the same as it was in the previous
+ * examples:
+ *
+ * @until cursor_free
+ *
+ * @until printf
+ *
+ * One thing we did not explore yet, is bson_cursor_new(): this will
+ * create a new cursor, and point to to the very beginning of our BSON
+ * object, just before the first key. Thus, the first
+ * bson_cursor_next() done afterwards will yield the first key.
+ * @until bson_cursor_free
+ *
+ * Very well! But what if we want to see the title of the second page
+ * within the pages array? Unfortunately, that is a bit more work to
+ * accomplish: we'll need to extract the pages array from our
+ * document, and then extract its second element, and then we can find
+ * stuff in that:
+ * @until printf
+ *
+ * And that concludes our BSON traversing tutorial!
+ *
+ * @until }
+ */