Skip to content

Commit 7ddaa1b

Browse files
authored
CXX-2840 Add docs example: Projection with aggregation expressions
1 parent b78767d commit 7ddaa1b

File tree

2 files changed

+134
-27
lines changed

2 files changed

+134
-27
lines changed

examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
## Building code examples
88

99
1. Run `git clone https://github.com/mongodb/mongo-cxx-driver && cd mongo-cxx-driver/build`
10-
2. Follow the instructions [here](https://www.mongodb.com/docs/languages/cpp/drivers/current/installation/) to install the driver
10+
2. Follow the instructions [here](https://www.mongodb.com/docs/languages/cpp/cpp-driver/current/installation/) to install the driver
1111
3. Run `make examples`
1212
4. cd `examples/mongocxx`
1313
5. Start up `mongod` running on the default port (i.e. 27017)

examples/mongocxx/mongodb.com/documentation_examples.cpp

Lines changed: 133 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,23 @@
3737
// corresponding page on mongodb.com/docs. See CXX-1249 and DRIVERS-356 for more info.
3838

3939
template <typename T>
40-
void check_field(const T& document, const char* field, bool should_have, int example_no) {
40+
void check_field(const T& document,
41+
const char* field,
42+
bool should_have,
43+
int example_no,
44+
const char* example_type = NULL) {
45+
std::string example_type_formatted = example_type ? example_type + std::string(" ") : "";
4146
if (should_have) {
4247
if (!document[field]) {
43-
throw std::logic_error(std::string("document in example ") +
44-
std::to_string(example_no) + " should have field " + field);
48+
throw std::logic_error(std::string("document in ") + example_type_formatted +
49+
std::string("example ") + std::to_string(example_no) +
50+
" should not have field " + field);
4551
}
4652
} else {
4753
if (document[field]) {
48-
throw std::logic_error(std::string("document in example ") +
49-
std::to_string(example_no) + " should not have field " + field);
54+
throw std::logic_error(std::string("document in ") + example_type_formatted +
55+
std::string("example ") + std::to_string(example_no) +
56+
" should not have field " + field);
5057
}
5158
}
5259
}
@@ -61,6 +68,22 @@ void check_has_no_field(const T& document, const char* field, int example_no) {
6168
check_field(document, field, false, example_no);
6269
}
6370

71+
template <typename T>
72+
void check_has_field(const T& document,
73+
const char* field,
74+
int example_no,
75+
const char* example_type) {
76+
check_field(document, field, true, example_no, example_type);
77+
}
78+
79+
template <typename T>
80+
void check_has_no_field(const T& document,
81+
const char* field,
82+
int example_no,
83+
const char* example_type) {
84+
check_field(document, field, false, example_no, example_type);
85+
}
86+
6487
bool should_run_client_side_encryption_test(void) {
6588
const char* const vars[] = {
6689
"MONGOCXX_TEST_AWS_SECRET_ACCESS_KEY",
@@ -187,6 +210,46 @@ static bool is_replica_set(const mongocxx::client& client) {
187210
return static_cast<bool>(reply.view()["setName"]);
188211
}
189212

213+
static bool version_at_least(mongocxx::database& db,
214+
int minimum_major,
215+
int minimum_minor,
216+
int minimum_patch) {
217+
using bsoncxx::builder::basic::kvp;
218+
using bsoncxx::builder::basic::make_document;
219+
220+
auto resp = db.run_command(make_document(kvp("buildInfo", 1)));
221+
auto version = resp.find("version")->get_string().value;
222+
std::string major_string;
223+
std::string minor_string;
224+
std::string patch_string;
225+
int split = 0;
226+
for (auto i : version) {
227+
if (i == '.') {
228+
split += 1;
229+
continue;
230+
}
231+
if (split == 0) {
232+
major_string += i;
233+
} else if (split == 1) {
234+
minor_string += i;
235+
} else if (split == 2) {
236+
patch_string += i;
237+
}
238+
}
239+
240+
std::vector<int> server_semver{
241+
std::stoi(major_string), std::stoi(minor_string), std::stoi(minor_string)};
242+
std::vector<int> minimum_semver{minimum_major, minimum_minor, minimum_patch};
243+
for (size_t i = 0; i < server_semver.size(); i++) {
244+
if (server_semver[i] < minimum_semver[i]) {
245+
return false;
246+
} else if (server_semver[i] > minimum_semver[i]) {
247+
return true;
248+
}
249+
}
250+
return true;
251+
}
252+
190253
void insert_examples(mongocxx::database db) {
191254
db["inventory"].drop();
192255

@@ -869,7 +932,7 @@ void query_null_missing_fields_examples(mongocxx::database db) {
869932
}
870933
}
871934

872-
void projection_examples(mongocxx::database db) {
935+
void projection_insertion_example(mongocxx::database db) {
873936
db["inventory"].drop();
874937

875938
{
@@ -915,6 +978,10 @@ void projection_examples(mongocxx::database db) {
915978
throw std::logic_error("wrong count in example 42");
916979
}
917980
}
981+
}
982+
983+
void projection_examples(mongocxx::database db) {
984+
projection_insertion_example(db);
918985

919986
{
920987
// Start Example 43
@@ -1092,6 +1159,63 @@ void projection_examples(mongocxx::database db) {
10921159
}
10931160
}
10941161

1162+
void projection_with_aggregation_example(mongocxx::database db) {
1163+
{
1164+
if (!version_at_least(db, 4, 4, 0)) {
1165+
return;
1166+
}
1167+
1168+
projection_insertion_example(db);
1169+
1170+
// Start Aggregation Projection Example 1
1171+
using bsoncxx::builder::basic::kvp;
1172+
using bsoncxx::builder::basic::make_array;
1173+
using bsoncxx::builder::basic::make_document;
1174+
1175+
auto cursor = db["inventory"].find(
1176+
make_document(),
1177+
mongocxx::options::find{}.projection(make_document(
1178+
kvp("_id", 0),
1179+
kvp("item", 1),
1180+
kvp("status",
1181+
make_document(kvp(
1182+
"$switch",
1183+
make_document(
1184+
kvp("branches",
1185+
make_array(
1186+
make_document(
1187+
kvp("case",
1188+
make_document(kvp("$eq", make_array("$status", "A")))),
1189+
kvp("then", "Available")),
1190+
make_document(
1191+
kvp("case",
1192+
make_document(kvp("$eq", make_array("$status", "D")))),
1193+
kvp("then", "Discontinued")))),
1194+
kvp("default", "No status found"))))),
1195+
kvp("area",
1196+
make_document(kvp(
1197+
"$concat",
1198+
make_array(
1199+
make_document(kvp(
1200+
"$toString",
1201+
make_document(kvp("$multiply", make_array("$size.h", "$size.w"))))),
1202+
" ",
1203+
"$size.uom")))),
1204+
kvp("reportNumber", make_document(kvp("$literal", 1))))));
1205+
// End Aggregation Projection Example 1
1206+
1207+
for (auto&& document : cursor) {
1208+
check_has_no_field(document, "_id", 1, "aggregation projection");
1209+
check_has_field(document, "item", 1, "aggregation projection");
1210+
check_has_field(document, "status", 1, "aggregation projection");
1211+
check_has_no_field(document, "size", 1, "aggregation projection");
1212+
check_has_no_field(document, "instock", 1, "aggregation projection");
1213+
check_has_field(document, "area", 1, "aggregation projection");
1214+
check_has_field(document, "reportNumber", 1, "aggregation projection");
1215+
}
1216+
}
1217+
}
1218+
10951219
void update_examples(mongocxx::database db) {
10961220
db["inventory"].drop();
10971221

@@ -1467,24 +1591,6 @@ static void snapshot_example2(mongocxx::client& client) {
14671591
}
14681592
}
14691593

1470-
static bool version_at_least(mongocxx::database& db, int minimum_major) {
1471-
using bsoncxx::builder::basic::kvp;
1472-
using bsoncxx::builder::basic::make_document;
1473-
1474-
auto resp = db.run_command(make_document(kvp("buildInfo", 1)));
1475-
auto version = resp.find("version")->get_string().value;
1476-
std::string major_string;
1477-
for (auto i : version) {
1478-
if (i == '.') {
1479-
break;
1480-
}
1481-
major_string += i;
1482-
}
1483-
int server_major = std::stoi(major_string);
1484-
1485-
return server_major >= minimum_major;
1486-
}
1487-
14881594
// https://jira.mongodb.com/browse/CXX-2505
14891595
static void queryable_encryption_api(mongocxx::client& client) {
14901596
// Start Queryable Encryption Example
@@ -1610,14 +1716,15 @@ int main() {
16101716
query_array_embedded_documents_examples(db);
16111717
query_null_missing_fields_examples(db);
16121718
projection_examples(db);
1719+
projection_with_aggregation_example(db);
16131720
update_examples(db);
16141721
delete_examples(db);
1615-
if (is_replica_set(conn) && version_at_least(db, 5)) {
1722+
if (is_replica_set(conn) && version_at_least(db, 5, 0, 0)) {
16161723
snapshot_example1(conn);
16171724
snapshot_example2(conn);
16181725
}
16191726
if (should_run_client_side_encryption_test() && is_replica_set(conn) &&
1620-
version_at_least(db, 7)) {
1727+
version_at_least(db, 7, 0, 0)) {
16211728
queryable_encryption_api(conn);
16221729
}
16231730
} catch (const std::logic_error& e) {

0 commit comments

Comments
 (0)