We will learn about the basics of MongoDB C++ leagcy driver here and how to implement it

Connecting to MongoDB

  1. Normal Connection (Without Password)

    mongo::DBClientConnection conn;

    Mongo::Status status = mongo::client::initialize()

    if (!status.isOK()) {

    MongoException m(-1, “failed to initialize the client driver: ” + status.toString());

    return -1

    }

    string url = “localhost:27017”;

    if (!conn.connect(url, errmsg)) {

    MongoException m(0, “couldn’t connect : ” + errmsg);

    return -1;

    }

    This will establish a normal connection with MongoDB i.e. without performing any authentication work.

  2. Authentication

    conn.auth(BSON(

    “user” << “root” <<

    “db” << “mydatabase” <<

    “pwd” << “password” <<

    “mechanism” << “DEFAULT”

    ));

    You need to change the values passed to the function conn.auth according to your setup of MongoDB

Fetching rows from the collection

Suppose you have a collection with the following fields:

  1. timestamp
  2. date
  3. time
  4. latitude
  5. longitude
  6. speed
  7. direction

Making Query

Let us evaluate different conditions to make the Query object. MONGO_QUERY is a helper macro used for creating the Query object.

Case 1:

timestamp > 142400000 and timestamp < 142500000

mongo::Query b = MONGO_QUERY(“timestamp” << mongo::GT << (long long) 142400000 << “timestamp” << mongo::LT << (long long) 142500000);

Case 2:

timestamp > 142400000 and timestamp < 142500000

Sorted in ascending order

mongo::Query b = MONGO_QUERY(“timestamp” << mongo::GT << (long long) 142400000 << “timestamp” << mongo::LT << (long long) 142500000);

b.sort(“timestamp”,1)

Case 3:

timestamp > 142400000 and timestamp < 142500000

Sorted in descending order

mongo::Query b = MONGO_QUERY(“timestamp” << mongo::GT << (long long) 142400000 << “timestamp” << mongo::LT << (long long) 142500000);

b.sort(“timestamp”, -1)

Matching binary data

string tag = “Binary”;

mongo::BSONBinData be((void *) tag.c_str(), tag.length(), mongo::BinDataGeneral);

mongo::Query b = MONGO_QUERY(“description” << be);

Matching with all the parameters having speed 0

string tag = “Binary”;

mongo::BSONBinData be((void *) tag.c_str(), tag.length(), mongo::BinDataGeneral);

mongo::Query b = MONGO_QUERY(“timestamp” << mongo::GT << (long long) 142400000 << “timestamp” << mongo::LT << (long long) 142500000 <<“speed” << “0” << “description” << be);

b.sort(“timestamp”, 1);

Above query simply means that timestamp > 142400000 and timestamp < 142500000, speed = 0 and description having binary data equivalent to “Binary”. BSONBinData is the Object that is required to be passed to the MONGO_QUERY macro for performing the comparison.

Executing Query

Now we have made the connection and the query, next we will execute this query on the server. In this we shall be using the database “mydb” and collection name “Locations”

string collectionName = “mydb.Locations”

auto_ptr<mongo::DBClientCursor> cursor = conn.query(collectionName,b);

mongo::BSONObj p;

while (cursor->more()) {

p = cursor->next();

// Do something with the fetched record

}

We now declare a cursor variable which will return pointer to the records formatted in the BSONObj format. cursor->more() checks if we have any more rows to be retrieved from the server and if yes we call cursor->next() which returns BSONObj object.

Retrieving N records only

auto_ptr<mongo::DBClientCursor> cursor = conn.query(collectionName,b, 10);

In order to retrieve N number of records we can pass additional parameter to the query function with number of records required to be fetched from the server. This is equivalent to the LIMIT clause in WHERE statement of SQL

Data Retrieval from BSONObj

Finally we are required to retrieve various fields from the BSONObj given by the cursor->next()

string collectionName = “mydb.Locations”

auto_ptr<mongo::DBClientCursor> cursor = conn.query(collectionName,b);

mongo::BSONObj p;

while (cursor->more()) {

p = cursor->next();

// Do something with the fetched record

double latitude = p.getField(“latitude”).Double();

double longitude = p.getField(“longitude”).Double();

}

In the above case we always assume that the data is inserted in the Double format inside the collection. Sometimes it becomes necessary to evaluate the type and perform conversion as per your requirement. We can achieve it with the following code

double latitude;

while (cursor->more()) {

p = cursor->next();

// Do something with the fetched record

switch (p.getField(“latitude”)) {

case mongo::NumberDouble:

latitude = p.getField(“latitude”).Double();

break;

case mongo::String:

{

string lat = p.getField(“latitude”).String();

sscanf (lat.c_str(), “%lf”, &latitude);

}

break;

}

}

Count

Counting number of records present in the collection

cout << “count:” << conn.count(“mydb.Locations”) << endl;

Insert Rows into collection

Inserting rows into MongoDB required usage of BSONObjBuilder. Following code will illustrate on addition of 4 fields in the object and then inserting it into the collection

//Create BSONObjBuilder type Object

obj = new mongo::BSONObjBuilder();

//Append various fields and set their values

obj->append(“latitude”, 27.24424);

obj->append(“longitude”, 78.24242);

obj->append(“speed”, 0);

obj-appendBinData(“description”, 6, mongo::BinDataGeneral, “Binary”);

//Perform insertion command

conn.insert(dbCollection, obj->obj());

std::string e = conn.getLastError();

if (!e.empty()) {

MongoException m(1, “insert failed: ” + e);

return -1;

}

Indexing

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

conn.createIndex(“mydb.Locations”, fromjson(“{timestamp: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:

conn.createIndex(“mydb.Locations”, BSON( “timestamp” << 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.

Updating

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

> use tutorial

db.persons.update(
{ name : ‘Joe’, age : 33 },
{ $inc : { visits : 1 } }
)

is equivalent to the following C++ code:

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.

MongoDB C++ Tutorial

2 thoughts on “MongoDB C++ Tutorial

  • November 12, 2016 at 12:42 pm
    Permalink

    Nice tutorial, I want to learn more, so is there any way that we can communicate one to one.

    Reply

Leave a Reply