summaryrefslogtreecommitdiff
path: root/docs/tutorial/tut_bson_traverse.h
blob: 712ff71aaef17cb8436d63c64e1c29164065322f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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 }
 */