userver: MongoDB
Loading...
Searching...
No Matches
MongoDB

The mongo asynchronous driver provides an interface to work with MongoDB databases and the BSON format.

Main features

  • Building and reading BSON documents with support for most of the C++ types;
  • Support for basic operations with collections via storages::mongo::Collection;
  • Support for bulk operations;
  • Dynamic management of database sets;
  • Aggregation support;
  • Timeouts;
  • Congestion control to work smoothly under heavy load and to restore from metastable failure state;
  • Deadline propagation .

Metrics

Most important ones:

Metric name Description
mongo.pool.current-size current number of open connections
mongo.pool.max-size limit on the number of open connections
mongo.pool.overloads counter of requests that could not get a connection
mongo.pool.queue-wait-timings waiting timings in the queue to receive a connection
mongo.pool.conn-request-timings connection receipt timings (includes queue-wait)
mongo.pool.conn-created/closed open/closed connection counters
mongo.success counter of successfully executed requests
mongo.errors counter of failed requests
mongo.timings query timings

See Service Statistics and Metrics (Prometheus/Graphite/...) for info on how to get the metrics.

Usage

To use MongoDB you have to add the component components::Mongo and configure it according to the documentation. After that you can work with a collection via storages::mongo::Collection:

inline void SampleMongoPool(storages::mongo::Pool pool) {
auto in_coll = pool.GetCollection("aggregate_in");
in_coll.InsertMany({
formats::bson::MakeDoc("_id", 1, "x", 0),
formats::bson::MakeDoc("_id", 2, "x", 1),
formats::bson::MakeDoc("_id", 3, "x", 2),
});
auto cursor = in_coll.Aggregate(
MakeArray(MakeDoc("$match", MakeDoc("_id", MakeDoc("$gte", 2))),
MakeDoc("$addFields", MakeDoc("check", true)),
MakeDoc("$out", "aggregate_out")),
EXPECT_FALSE(cursor);
auto out_coll = pool.GetCollection("aggregate_out");
EXPECT_EQ(2, out_coll.CountApprox());
for (const auto& doc : out_coll.Find({})) {
EXPECT_EQ(doc["_id"].As<int>(), doc["x"].As<int>() + 1);
EXPECT_TRUE(doc["check"].As<bool>());
}
}

Methods and options correspond to the standard MongoDB Collections API.

Timeouts

It is recommended to set timeouts on the server side using storages::mongo::options::MaxServerTime as for other cancellation mechanisms MongoDB does not guarantee that the cancelled operation was not applied.

For client-side timeouts consider setting socket and/or connection timeouts in pool configuration as native task cancellation is not supported in the current implementation.

Write results

Methods that modify a collection return an object storages::mongo::WriteResult containing information about the result of the operation:

inline void UpdateOneDoc(storages::mongo::Collection& coll) {
auto result =
coll.UpdateOne(MakeDoc("_id", 1), MakeDoc("$set", MakeDoc("x", 10)));
EXPECT_EQ(1, result.MatchedCount());
EXPECT_EQ(1, result.ModifiedCount());
EXPECT_EQ(0, result.UpsertedCount());
EXPECT_TRUE(result.UpsertedIds().empty());
EXPECT_TRUE(result.ServerErrors().empty());
EXPECT_TRUE(result.WriteConcernErrors().empty());
}

Packaging operations

In cases where the same operation is performed with the same arguments many times, it can be stored into a variable and reused. The finished operation can be passed to the collection method Execute().

inline const storages::mongo::operations::Find& Top3ScoresOp() {
static const auto kGetTop = [] {
"score",
storages::mongo::options::Sort::kDescending,
}});
return op;
}();
return kGetTop;
}
inline std::string GetWinners(storages::mongo::Collection& mongo_coll) {
std::string result;
for (const auto& doc : mongo_coll.Execute(Top3ScoresOp())) {
result += doc["name"].As<std::string>("<anonymous>") + ' ';
}
return result;
}

BSON

BSON follows the common formats interface that is described in detail at Formats (JSON, YAML, BSON, ...).

Since BSON is a binary format, it is not human readable. Differences in the BSON and JSON formats type systems do not always allow you to perform conversions between them unambiguously. In this regard, we do not provide conversion functions between BSON and text formats by default, but they are available in <userver/formats/bson/serialize.hpp>. These functions are provided without guarantees for the stability of the conversion, and are primarily intended for debugging.

Mongo Congestion Control

Extra database load may lead to database overload. To protect Mongo from this happening userver has Congestion Control. In case of fast timings increase, the Congestion Control limits the number of concurrent connections to Mongo and eliminates the extra load. On the one hand, it leads to extra error responses, but on the other hand, it greatly lowers the timings of the rest of the database requests and helps Mongo to return to the normal state with lower response timings.