File: tutorial.md

package info (click to toggle)
mongo-cxx-driver 4.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 13,832 kB
  • sloc: cpp: 61,365; python: 1,436; sh: 356; xml: 253; perl: 215; makefile: 21
file content (340 lines) | stat: -rw-r--r-- 10,621 bytes parent folder | download
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
+++
date = "2016-08-15T16:11:58+05:30"
title = "Legacy driver tutorial"
[menu.main]
  identifier = 'legacy-tutorial'
  weight = 15
  parent="legacy"
+++

### Getting started with the Legacy C++ Driver

This is an introduction to usage of the MongoDB database from a C++ program.

NOTE: this tutorial is for the legacy and 26compat versions of the C++ driver.

First, install MongoDB – see the
[installation](https://www.mongodb.com/docs/manual/installation/) page for
details.

Next, you may wish to take a look at the [MongoDB
Manual](https://www.mongodb.com/docs/manual/) for a language independent look at
how to use MongoDB. Also, we suggest some basic familiarity with the [mongo
shell](https://www.mongodb.com/docs/mongodb-shell/) – the shell is the primary
database administration tool and is useful for manually inspecting the
contents of a database after your C++ program runs.

### Installing the Driver Library and Headers

Please see [Installation]({{< ref "/legacy-v1/installation" >}}) for
instructions on how to download, build, and install the C++ client driver.

### Initializing the Driver Library

Please see [Configuration]({{< ref "/legacy-v1/configuration" >}}) for
instructions on how to properly initialize and terminate the driver:

### Connecting

#### DBClientConnection

The C++ driver includes several classes for managing collections under the parent class `DBClientInterface`.

 - `DBClientConnection` is the connection class for connecting to a single MongoDB database server (or mongos)
 - `DBClientReplicaSet` is the connection class for connecting to a replica set.

See the [API documentation](https://mongodb.github.io/api/1.0.2/) for
details on each of the above classes.

#### A simple program that connects to the database

```cpp
#include <cstdlib>
#include <iostream>
#include "mongo/client/dbclient.h" // for the driver

void run() {
  mongo::DBClientConnection c;
  c.connect("localhost");
}

int main() {
    mongo::client::initialize();
    try {
        run();
        std::cout << "connected ok" << std::endl;
    } catch( const mongo::DBException &e ) {
        std::cout << "caught " << e.what() << std::endl;
    }
    return EXIT_SUCCESS;
}
```

(Note that in a production environment, the return value of `mongo::client::initialize()` must be checked)

If you are using gcc on Linux, you would compile with something like this, depending on location of your include files and libraries:

```sh
$ g++ tutorial.cpp -pthread -lmongoclient -lboost_thread-mt -lboost_system -lboost_regex -o tutorial
$ ./tutorial
connected ok
```

> **Warning**

 - Since the tutorial program attempts to connect to a MongoDB database server, you must start it by running mongod before running the tutorial.
 - You may need to append -mt to boost_filesystem and boost_program_options. If using a recent boost, -mt is not needed anymore.
 - You may need to use -I and -L to specify the locations of your mongo and boost headers and libraries.
 - If using the 26compat branch you need to additionally specify `-lboost_filesystem` and `-lboost_program_options`

### BSON

The MongoDB database stores data in BSON format. BSON is a binary object
format that is JSON-like in terms of the data which can be stored (some
extensions exist, for example, a Date datatype).

To save data in the database we must create objects of class BSONObj. The
components of a BSONObj are represented as BSONElement objects. We use
BSONObjBuilder to make BSON objects, and BSONObjIterator to enumerate BSON
objects.

#### The C++ BSON Library

Include bson/bson.h in your application. See
[bsondemo](https://github.com/mongodb/mongo-cxx-driver/blob/legacy/src/mongo/bson/bsondemo/bsondemo.cpp)
for example usage.

##### Key classes

```cpp
mongo::BSONObj: a BSON object
mongo::BSONElement: a single element in a BSON object. This is a key and a value.
mongo::BSONObjBuilder: used to make BSON objects
mongo::BSONObjIterator: used to enumerate BSON objects
```

##### Working with BSON

Let’s now create a BSON “person” object which contains name and age. We might invoke:

```cpp
BSONObjBuilder b;
b.append("name", "Joe");
b.append("age", 33);
BSONObj p = b.obj();
```

Or more concisely:

```cpp
BSONObj p = BSONObjBuilder().append("name", "Joe").append("age", 33).obj();
```

We can also create BSON objects using the stream oriented syntax:

```cpp
BSONObjBuilder b;
b << "name" << "Joe" << "age" << 33;
BSONObj p = b.obj();
```

The BSON Macro lets us be even more compact:

```cpp
BSONObj p = BSON( "name" << "Joe" << "age" << 33 );
```

Use the GENOID helper to add an object id to your object. The server will
add an \_id automatically if it is not included explicitly.

```cpp
BSONObj p = BSON( GENOID << "name" << "Joe" << "age" << 33 );
// result is: { _id : ..., name : "Joe", age : 33 }
```

GENOID should be at the beginning of the generated object. We can do something similar with the non-stream builder syntax:

```cpp
BSONObj p = BSONObjBuilder().genOID().append("name","Joe").append("age",33).obj();
```

Other helpers are listed in [Working with BSON]({{< ref "/legacy-v1/working-with-bson" >}}).

### Inserting

We now save our person object in a persons collection in the database:

```cpp
c.insert("tutorial.persons", p);
```
The first parameter to insert is the namespace. tutorial is the database and persons is the collection name.

#### getLastError

In order to ensure the write succeeded we need to call getLastError.

Get error result from the last operation on this connection:

```cpp
string mongo::DBClientWithCommands::getLastError(); // Empty string if no error
```

Get the full last error object:

```cpp
BSONObj DBClientWithCommands::getLastErrorDetailed();
```

For an example, see [this demo](https://github.com/mongodb/mongo-cxx-driver/blob/legacy/src/mongo/client/examples/simple_client_demo.cpp).

For additional background information on getLastError see the [write
operations documentation](https://www.mongodb.com/docs/manual/core/write-operations/#write-concern).

### Count

Let’s now fetch all objects from the persons collection, and display them. We’ll also show here how to use count().

```cpp
cout << "count:" << c.count("tutorial.persons") << endl;
```

### Query

```cpp
auto_ptr<DBClientCursor> cursor = c.query("tutorial.persons", BSONObj());

while (cursor->more())
   cout << cursor->next().toString() << endl;
```

`BSONObj()` is an empty BSON object – it represents `{}` which indicates an
empty query pattern (an empty query is a query for all objects).

We use `BSONObj::toString()` above to print out information about each
object retrieved. `BSONObj::toString` is a diagnostic function which prints
an abbreviated JSON string representation of the object. For full JSON
output, use `BSONObj::jsonString`.

Let’s now write a function which prints out the name (only) of all persons
in the collection whose age is a given value:

```cpp
void printIfAge(DBClientConnection& c, int age) {
    auto_ptr<DBClientCursor> cursor =
        c.query("tutorial.persons", MONGO_QUERY("age" << age));
    while (cursor->more()) {
        BSONObj p = cursor->next();
        cout << p.getStringField("name") << endl;
    }
}
```

`getStringField()` is a helper that assumes the name field is of type
string. To manipulate an element in a more generic fashion we can retrieve
the particular BSONElement from the enclosing object:

```cpp
BSONElement name = p["name"];
// or:
BSONElement name = p.getField("name");
```

See the api docs, and jsobj.h, for more information.

Our query above, written as JSON, is of the form

`{ age : <agevalue> }`

Queries are BSON objects of a particular format – in fact, we could have
used the BSON() macro above instead of MONGO_QUERY(). See class Query in
dbclient.h for more information on Query objects, and the Sorting section
below.

In the mongo shell (which uses javascript), we could invoke:

```js
use tutorial;
db.persons.find({age : 33});
```

### Indexing

Let’s suppose we want to have an index on age so that our queries are fast. We would use:

```cpp
c.createIndex("tutorial.persons", fromjson("{age:1}"));
```

In the above example we use a new function, fromjson. fromjson converts a
JSON string to a BSONObj. This is sometimes a convenient way to specify
BSON. Alternatively, we could have written:

```cpp
c.createIndex("tutorial.persons", BSON( "age" << 1 ));
```

While calling createIndex multiple times won't result in duplicate index
creation on the server, it will cause an extra network round-trip and
server operation for each call. It's best practice to use this method
sparingly, for example once at the beginning of your code, or perhaps in an
external setup script that configures the database for your application.
For more information about indexing, see the [MongoDB Indexing
docs](https://www.mongodb.com/docs/manual/indexes/).

### Sorting

Let’s now make the results from printIfAge sorted alphabetically by name.
To do this, we change the query statement from:

```cpp
auto_ptr<DBClientCursor> cursor = c.query("tutorial.persons", MONGO_QUERY("age" << age));
```

to

```cpp
auto_ptr<DBClientCursor> cursor = c.query("tutorial.persons", MONGO_QUERY("age" << age ).sort("name"));
```

Here we have used `Query::sort()` to add a modifier to our query expression for sorting.

### Updating

Use the `update()` method to perform a database update. For example the
following update in the mongo shell:

```js
> use tutorial
> db.persons.update(
    { name : 'Joe', age : 33 },
    { $inc : { visits : 1 } }
)
```

is equivalent to the following C++ code:

```cpp
db.update("tutorial.persons",
    BSON("name" << "Joe" << "age" << 33),
    BSON("$inc" << BSON( "visits" << 1))
);
```

The `update()` method can be used to modify specific fields, replace the
entire existing document, insert new documents or update multiple
documents.  In the MongoDB Manual, examples are provided in the [Modify
Documents Tutorial](https://www.mongodb.com/docs/manual/tutorial/modify-documents/).

### Arrays

A simple example illustrating usage of BSON arrays and the `$nin` operator
is available [here](https://github.com/mongodb/mongo-cxx-driver/blob/legacy/src/mongo/client/examples/arrayExample.cpp).

### Further Reading

This overview just touches on the basics of using MongoDB from C++. There
are many more capabilities. For further exploration:

 - See the language-independent [MongoDB Manual](https://www.mongodb.com/docs/manual/)
 - Experiment with the [mongo shell](https://www.mongodb.com/docs/mongodb-shell/)
 - Review the [API docs](https://mongodb.github.io/api/1.0.2)