We will learn about the basics of MongoDB C++ leagcy driver here and how to implement it
Connecting to MongoDB
-
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.
-
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:
- timestamp
- date
- time
- latitude
- longitude
- speed
-
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.
Leave a Reply