mongocxx c++ 14标准,进行多表联合查询
#include <iostream> #include <vector> #include <map> #include <mongocxx/client.hpp> #include <mongocxx/instance.hpp> #include <mongocxx/uri.hpp> #include <bsoncxx/builder/stream/document.hpp> #include <bsoncxx/json.hpp> #include <bsoncxx/types.hpp> using bsoncxx::builder::stream::document; using bsoncxx::builder::stream::finalize; using bsoncxx::builder::stream::open_array; using bsoncxx::builder::stream::close_array; using bsoncxx::builder::stream::open_document; using bsoncxx::builder::stream::close_document; using bsoncxx::builder::stream::concatenate; using bsoncxx::builder::basic::make_document; using bsoncxx::builder::basic::kvp; void get_data() { mongocxx::instance inst{}; // 实例化 Mongocxx 库 mongocxx::uri uri("mongodb://localhost:27017"); // 连接 MongoDB URI mongocxx::client conn(uri); // 创建连接实例 mongocxx::database db = conn["test_sh"]; mongocxx::collection teacher_1 = db["teacher_20230417_0_60"]; mongocxx::collection teacher_2 = db["teacher_20230417_120_180"]; // mongocxx::collection teacher_3 = db["teacher_20230417_180_240"]; auto pipeline = mongocxx::pipeline{}; pipeline.lookup({ make_document( kvp("from", "teacher_20230417_120_180"), // b表的表名 kvp("localField", "teacher_1.index_join_id"), // a表的关联外键 kvp("foreignField", "teacher_2.index_join_id"), // b表的关联外键 kvp("as", "teacher_2") // 别名 ) }); pipeline.unwind("$teacher_2"); // 如果有多个,这里需要写多个 /*pipeline.unwind("$array_field1"); pipeline.unwind("$array_field2"); pipeline.unwind("$array_field3");*/ // 这里是做展示代码 pipeline.project({ make_document( kvp("_id", 0), kvp("index", 1), kvp("time", 1), kvp("TPE02", "$teacher_2.TPE02") ) }); // 排序 // pipeline.sort(make_document(kvp("time", 1))); pipeline.limit(10); // 使用.limit()操作符限制结果数量 auto cursor = teacher_1.aggregate(pipeline); for (auto&& doc : cursor) { std::cout << bsoncxx::to_json(doc) << std::endl; }
增加复杂情况下,动态获取表和字段,进行多表联合查询代码
#ifndef GET_DATA_HPP #define GET_DATA_HPP #include <iostream> #include <vector> #include <map> #include <mongocxx/client.hpp> #include <mongocxx/instance.hpp> #include <mongocxx/uri.hpp> #include <bsoncxx/builder/stream/document.hpp> #include <bsoncxx/json.hpp> #include <bsoncxx/types.hpp> using bsoncxx::builder::stream::document; using bsoncxx::builder::stream::finalize; using bsoncxx::builder::stream::open_array; using bsoncxx::builder::stream::close_array; using bsoncxx::builder::stream::open_document; using bsoncxx::builder::stream::close_document; using bsoncxx::builder::stream::concatenate; using bsoncxx::builder::basic::make_document; using bsoncxx::builder::basic::kvp; int get_data() { mongocxx::instance inst{}; mongocxx::client conn{mongocxx::uri{"mongodb://localhost:27017"}}; auto db = conn["test_sh"]; std::map<std::string, std::vector<std::string>> return_dict; return_dict["teacher_20230417_0_60"] = { "index","time" }; return_dict["teacher_20230417_120_180"] = { "TPE02" }; return_dict["teacher_20230417_180_240"] = { "TBFTCT08" }; // 获取return_dict的第二个值,for循环中使用 std::string previous_key; //所以previous_key存储的都是上一个key值 auto pipeline = mongocxx::pipeline{}; for (const auto& item : return_dict) { // teacher_20230417_0_60 可以用begin来获取 if (item.first != "teacher_20230417_0_60") { /* * 示例 pipeline.lookup({ make_document( kvp("from", item.first), // b表的表名 kvp("localField", "index_join_id"), // a表的关联外键 kvp("foreignField", "index_join_id"), // b表的关联外键 kvp("as", "from_" + item.first) // 别名 ) });*/ // 这里需要增加一个判断,因为有可能a 和b的关联外键是a.aid,b.bid,和c的情况不是a和c,可能是b的bbid和c的ccid了 // 如果second_element.first == 第二个表,localfield就是第一个表的外键 std::string foreign_key_a = previous_key + ".index_join_id"; std::string foreign_key_b = item.first + ".index_join_id"; std::string as_name = "from_" + item.first; pipeline.lookup({ make_document( kvp("from", item.first), // b表的表名 kvp("localField", "index_join_id"), // a表的关联外键 kvp("foreignField", foreign_key_b), // b表的关联外键 kvp("as", as_name) // 别名 ) }); } // 在这里,element.first 是当前循环的键 // previous_key 是上一个循环的键(如果有的话) // 在第一次循环时,previous_key 是空的 // 在这里处理当前循环的逻辑 // 更新 previous_key previous_key = item.first; } bsoncxx::builder::stream::document projection_doc; for (const auto& item : return_dict) { for (const auto& field : item.second) { projection_doc << field << 1; } } pipeline.limit(10); // 使用.limit()操作符限制结果数量 pipeline.project(projection_doc.view()); auto cursor = db["teacher_20230417_0_60"].aggregate(pipeline); for (auto&& doc : cursor) { std::cout << bsoncxx::to_json(doc) << std::endl; } return 0; } #endif // GET_DATA_HPP
最终形成的代码逻辑
#ifndef GET_DATA_HPP #define GET_DATA_HPP #include <iostream> #include <vector> #include <map> #include <mongocxx/client.hpp> #include <mongocxx/instance.hpp> #include <mongocxx/uri.hpp> #include <bsoncxx/builder/stream/document.hpp> #include <bsoncxx/json.hpp> #include <bsoncxx/types.hpp> using bsoncxx::builder::stream::document; using bsoncxx::builder::stream::finalize; using bsoncxx::builder::stream::open_array; using bsoncxx::builder::stream::close_array; using bsoncxx::builder::stream::open_document; using bsoncxx::builder::stream::close_document; using bsoncxx::builder::stream::concatenate; using bsoncxx::builder::basic::make_document; using bsoncxx::builder::basic::kvp; int get_data() { mongocxx::instance inst{}; mongocxx::client conn{mongocxx::uri{"mongodb://localhost:27017"}}; auto db = conn["test_sh"]; std::map<std::string, std::vector<std::string>> return_dict; return_dict["teacher_20230417_0_60"] = { "index","time" }; return_dict["teacher_20230417_120_180"] = { "TPE02" }; return_dict["teacher_20230417_180_240"] = { "TBFTCT08" }; // 获取return_dict的第二个值,for循环中使用 std::string previous_key; //所以previous_key存储的都是上一个key值 bsoncxx::builder::stream::document projection_doc; projection_doc << "_id" << 0; auto pipeline = mongocxx::pipeline{}; for (const auto& item : return_dict) { // teacher_20230417_0_60 可以用begin来获取 if (item.first != "teacher_20230417_0_60") { /* * 示例 pipeline.lookup({ make_document( kvp("from", item.first), // b表的表名 kvp("localField", "index_join_id"), // a表的关联外键 kvp("foreignField", "index_join_id"), // b表的关联外键 kvp("as", "from_" + item.first) // 别名 ) });*/ // 这里需要增加一个判断,因为有可能a 和b的关联外键是a.aid,b.bid,和c的情况不是a和c,可能是b的bbid和c的ccid了 // 如果second_element.first == 第二个表,localfield就是第一个表的外键 std::string foreign_key_a = previous_key + ".index_join_id"; std::cout << foreign_key_a << std::endl; std::string foreign_key_b = item.first + ".index_join_id"; std::string as_name = "from_" + item.first; pipeline.lookup({ make_document( kvp("from", item.first), // b表的表名 kvp("localField", foreign_key_a), // a表的关联外键 kvp("foreignField", foreign_key_b), // b表的关联外键 kvp("as", as_name) // 别名 ) }); pipeline.unwind("$" + as_name); // 这里要是别名才可以 for (const auto& field : item.second) { std::string field_name = "$" + as_name + "." + field; projection_doc << field << field_name; // kvp("TPE02", "$teacher_2.TPE02") 类似这种写法 } } else { for (const auto& field : item.second) { projection_doc << field << 1; } } // 在这里,element.first 是当前循环的键 // previous_key 是上一个循环的键(如果有的话) // 在第一次循环时,previous_key 是空的 // 在这里处理当前循环的逻辑 // 更新 previous_key previous_key = item.first; } pipeline.limit(10); // 使用.limit()操作符限制结果数量 pipeline.project(projection_doc.view()); auto cursor = db["teacher_20230417_0_60"].aggregate(pipeline); for (auto&& doc : cursor) { std::cout << bsoncxx::to_json(doc) << std::endl; } return 0; } #endif // GET_DATA_HPP
等等,看似对的,但实际上数据是错的。
修改后的代码
#ifndef GET_DATA_HPP #define GET_DATA_HPP #include <iostream> #include <vector> #include <map> #include <mongocxx/client.hpp> #include <mongocxx/instance.hpp> #include <mongocxx/uri.hpp> #include <bsoncxx/builder/stream/document.hpp> #include <bsoncxx/json.hpp> #include <bsoncxx/types.hpp> using bsoncxx::builder::stream::document; using bsoncxx::builder::stream::finalize; using bsoncxx::builder::stream::open_array; using bsoncxx::builder::stream::close_array; using bsoncxx::builder::stream::open_document; using bsoncxx::builder::stream::close_document; using bsoncxx::builder::stream::concatenate; using bsoncxx::builder::basic::make_document; using bsoncxx::builder::basic::kvp; int get_data() { mongocxx::instance inst{}; mongocxx::client conn{mongocxx::uri{"mongodb://localhost:27017"}}; auto db = conn["test_sh"]; std::map<std::string, std::vector<std::string>> return_dict; return_dict["teacher_20230417_0_60"] = { "index","time" }; return_dict["teacher_20230417_120_180"] = { "TPE02" }; return_dict["teacher_20230417_180_240"] = { "TBFTCT08" }; // 获取return_dict的第二个值,for循环中使用 std::string previous_key; //所以previous_key存储的都是上一个key值 bsoncxx::builder::stream::document projection_doc; projection_doc << "_id" << 0; projection_doc << "index_join_id" << 1; auto pipeline = mongocxx::pipeline{}; for (const auto& item : return_dict) { // teacher_20230417_0_60 可以用begin来获取 if (item.first != "teacher_20230417_0_60") { /* * 示例 pipeline.lookup({ make_document( kvp("from", item.first), // b表的表名 kvp("localField", "index_join_id"), // a表的关联外键 kvp("foreignField", "index_join_id"), // b表的关联外键 kvp("as", "from_" + item.first) // 别名 ) });*/ // 这里需要增加一个判断,因为有可能a 和b的关联外键是a.aid,b.bid,和c的情况不是a和c,可能是b的bbid和c的ccid了 // 如果second_element.first == 第二个表,localfield就是第一个表的外键 std::string foreign_key_a = previous_key + ".index_join_id"; std::cout << foreign_key_a << std::endl; std::string foreign_key_b = item.first + ".index_join_id"; std::string as_name = "from_" + item.first; pipeline.lookup({ make_document( kvp("from", item.first), // b表的表名 //kvp("localField", foreign_key_a), // a表的关联外键 //kvp("foreignField", foreign_key_b), // b表的关联外键 // 如果用类似sql的left join a.id=b.id的形式,数据有问题,所以暂时注释掉了 kvp("localField", "index_join_id"), // a表的关联外键 kvp("foreignField", "index_join_id"), // b表的关联外键 kvp("as", as_name) // 别名 ) }); pipeline.unwind("$" + as_name); // 这里要是别名才可以 for (const auto& field : item.second) { std::string field_name = "$" + as_name + "." + field; projection_doc << field << field_name; // kvp("TPE02", "$teacher_2.TPE02") 类似这种写法 } } else { for (const auto& field : item.second) { projection_doc << field << 1; } } // 在这里,element.first 是当前循环的键 // previous_key 是上一个循环的键(如果有的话) // 在第一次循环时,previous_key 是空的 // 在这里处理当前循环的逻辑 // 更新 previous_key previous_key = item.first; } // pipeline.match(make_document(kvp("index", "TAB000002"))); pipeline.limit(10); // 使用.limit()操作符限制结果数量 pipeline.project(projection_doc.view()); auto cursor = db["teacher_20230417_0_60"].aggregate(pipeline); for (auto&& doc : cursor) { std::cout << bsoncxx::to_json(doc) << std::endl; } return 0; } #endif // GET_DATA_HPP
问题在这里
增加过滤条件
您好!如果您想在 pipeline.match 中使用大于或小于条件,可以使用 $gt 和 $lt 操作符。例如,如果您想限定 index 的数据大于 1,可以使用以下代码: pipeline.match(make_document(kvp("index", make_document(kvp("$gt", 1))))); 如果您想限定 index 的数据小于 1,可以使用以下代码: pipeline.match(make_document(kvp("index", make_document(kvp("$lt", 1)))));
这样,在执行 pipeline.match 时,只有满足条件的文档才会被处理。
等于 pipeline.match(make_document(kvp("index", "TAB000002")));
作者:沐禹辰
出处:http://www.cnblogs.com/renfanzi/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
出处:http://www.cnblogs.com/renfanzi/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。