一、简介
本篇文章主要讲述如何使用C++调用MongoDB数据库并实现mongodb的高级聚合函数的写法。
1.什么是MongoDB?
MongoDB是一个基于分布式文件存储的数据库,由C++语言编写,一般多用于WEB应用进行可扩展的高性能数据存储
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持
的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
(1)MongoDB文档
MongoDB中的记录是一个文档,它是由字段和值对组成的数据结构。
多个键及其关联的值有序地放在一起就构成了文档。
MongoDB文档类似于JSON对象。字段的值可以包括其他文档,数组和文档数组。
{
name: "admin",
password: "123456",
}
(2)MongoDB集合
MongoDB的集合就类似数据的表,数据库中的每行数据就是一个文档,及集合是一组文档的集合。
1.什么是QT?
Qt 是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非
GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object
Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。
2.为什么QT要调用mongodb?
知识产权问题
二、环境
MongoDB 1.23.2
Qt 5.15.2
三、目标
目标很清晰,记住只需要编译出来两个文件夹并在QTcreator中调用成功即可。
mongodb类库
boost文件夹
四、编译过程
1.安装vs2017
(1)进入Microsoft下载官网
https://learn.microsoft.com/zh-cn/visualstudio/releases/2019/release-notes
(2)选择需要安装的版本并下载
Visual Studio 2019有社区版、专业版和企业版,社区版可免费使用,我安装的为社区版。
(3)点击运行安装程序,进入安装
提取文件后进入正常安装后,选择个人所需的开发负载、组件、语言包,选择安装位置(默认C盘)。
2.安装CMAKE
从【官网】下载CMAKE,解压后,将bin文件夹的路径,加入到windows的环境变量之中,随后一路点击“确定”即可。
3.安装mongo-c-driver
(1)在安装mongo的c++库之前,需要先安装c-driver,可参考【官网】。
(2)下载好后解压至mongo-c-driver-1.23.2文件夹中,并新建Build文件夹。 整个文件夹的上下级关系如:
(3)进入Build目录,打开cmd窗口
cmake -G "Visual Studio 15 2017" "-DCMAKE_INSTALL_PREFIX=E:workWorkFileMongoDBmongo-c-driver-1.23.2Build" "-DCMAKE_PREFIX_PATH=E:workWorkFileMongoDBmongo-c-driver-1.23.2Build" ..mongo-c-driver-1.23.2
注意:如果你的是其他版本的vs,命令就需要稍微修改一下,不然命令不会成功,路径也要注意,最好跟博主路径一样,这里面有很多坑。对应关系如下
Generators
Visual Studio 17 2022 = Generates Visual Studio 2022 project files.
Use -A option to specify architecture.
Visual Studio 16 2019 = Generates Visual Studio 2019 project files.
Use -A option to specify architecture.
* Visual Studio 15 2017 [arch] = Generates Visual Studio 2017 project files.
Optional [arch] can be "Win64" or "ARM".
Visual Studio 14 2015 [arch] = Generates Visual Studio 2015 project files.
Optional [arch] can be "Win64" or "ARM".
Visual Studio 12 2013 [arch] = Generates Visual Studio 2013 project files.
Optional [arch] can be "Win64" or "ARM".
Visual Studio 11 2012 [arch] = Deprecated. Generates Visual Studio 2012
project files. Optional [arch] can be
"Win64" or "ARM".
Visual Studio 9 2008 [arch] = Generates Visual Studio 2008 project files.
Optional [arch] can be "Win64" or "IA64".
(4)如果没有报错的话,Build文件中会生成一个文件mongo-c-driver.sln。
然后打开Visual Studio 2019,打开刚生成的项目mongo-c-driver.sln,把debug模式改为release模式,并右键
“ALL_BUILD”,选择“生成”。这里要等几分钟,生成成功后,再右键“INSTALL”,选择“生成”。
(5)如此mongo-c-driver就安装完成了,可以看到在Build之外的install文件夹下,生成一个bin文件夹存放*.dll文件,lib文件夹
存放*.lib文件,include文件夹都是编码需要的头文件。
c驱动编译成功!
4、安装Boost
(1)因为mongo-cxx-driver的编译还需要Boost,所以我们需要先安装这一部分。
在【官网】下载最新版的boost。
注意下载zip包!
(2)把下载的zip解压,解压后双击文件【bootstrap.bat】,随后会看到在目录中生成一个【b2.exe】,再双击exe程序,
boost会自动进行编译,此过程需要耗时比较长,耐心等待。
(3)编译完成后,把boost的路径添加进入环境变量。
5.安装mongo-cxx-driver
下载zip代码文件,并解压在mongo-cxx-driver-r3.7.1目录下,同时在mongo-cxx-driver目录下新建一个Build文件夹。
进入Build文件夹,打开cmd窗口,输入:
cmake -G "Visual Studio 16 2019" "-DBOOST_ROOT=D:Usersoost_1_82_0" "-DCMAKE_PREFIX_PATH=E:workWorkFileMongoDBmongo-c-driver-1.23.2Build" "-DCMAKE_INSTALL_PREFIX=E:workWorkFileMongoDBmongo-cxx-driver-r3.7.1Build" -DBUILD_VERSION=1.23.2 ..mongo-cxx-driver-master
注意路径改一下,这里要加入“-DBUILD_VERSION=1.23.2”,我之前没加这句话一直报错。
成功后,会在Build文件夹下生成【MONGO_CXX_DRIVER.sln】文件
接着在cmd中输入:
cmake ..mongo-cxx-driver-master -DCMAKE_BUILD_TYPE=Release -DLIBMONGOC_DIR=E:workWorkFileMongoDBmongo-c-driver-1.23.2Build -DLIBBSON_DIR=E:workWorkFileMongoDBmongo-c-driver-1.23.2Build -DCMAKE_INSTALL_PREFIX=E:workWorkFileMongoDBmongo-cxx-driver-r3.7.1Build
注意路径!
完成后用Visual Studio 2017,打开刚生成的项目MONGO_CXX_DRIVER.sln,把debug模式改为release模式,并右键
“ALL_BUILD”,选择“生成”。
6.编译结束
至此,我们mongo的c++库就安装完成了,总体来说就是就是一个先操作C库,再编译C++库的一个过程,特别要注意的就是
路径和版本,编译工程这种事情,只要把路径和版本对应好了,基本上不会有太大问题,所以大家在这个过程中最好跟博主
路径匹配
接下来可以在QTcreator中通过引入外部库的方式进行调用,下面我们介绍写法。
五、MAC版本编译
直接上图
六、调用mongodb
1.引入库和依赖
我们新建一个qt工程,在pro文件中,使程序支持c++17的语法,加入语句:
CONFIG += c++17
(1)MongoDB库
同样是在Pro文件中添加
#LIBS += -L/usr/local/lib/ -lbsoncxx -lmongocxx
#INCLUDEPATH += /usr/local/include/
#INCLUDEPATH += /usr/local/include/mongocxx/v_noabi/
#INCLUDEPATH += /usr/local/include/bsoncxx/v_noabi/
LIBS += -LE:workWorkFileMongoDBmongo-cxx-driver-r3.7.1installlib -lbsoncxx -lmongocxx
INCLUDEPATH += E:workWorkFileMongoDBmongo-cxx-driver-r3.7.1installinclude
INCLUDEPATH += E:workWorkFileMongoDBmongo-cxx-driver-r3.7.1installincludesoncxx_noabi
INCLUDEPATH += E:workWorkFileMongoDBmongo-cxx-driver-r3.7.1installincludemongocxx_noabi
#INCLUDEPATH += E:workWorkFileMongoDBmongo-c-driver-1.23.2installincludelibmongoc-1.0
#INCLUDEPATH +=E:workWorkFileMongoDBmongo-c-driver-1.23.2installincludelibbson-1.0
#INCLUDEPATH += C:Boostincludeoost-1_66
INCLUDEPATH += D:/boost_1_82_0
# Default rules for deployment.
qnx: target.path = /tmp/{{{TARGET}/bin
else: unix:!android: target.path = /opt/{{{TARGET}/bin
!isEmpty(target.path): INSTALLS += target
(2)新建项目
在.h文件中引入依赖
#include <mongocxx/client.hpp>
#include <mongocxx/pool.hpp>
#include <mongocxx/change_stream.hpp>
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/builder/stream/array.hpp>
#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/builder/basic/kvp.hpp>
#include <bsoncxx/builder/basic/array.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/exception/exception.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/pool.hpp>
#include <mongocxx/uri.hpp>
#include <QJsonDocument>
在.cpp文件中添加
using namespace std;
using bsoncxx::builder::stream::document;
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::finalize;
using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;
using bsoncxx::builder::basic::make_array;
static mongocxx::instance s_instance;
2.增删改查
(1)创建文档
document <<"hello" << "world"
<<"name" <<"csr"
<<"No" <<34
<<"3D" <<bsoncxx::builder::stream::open_array
<<48<<32.123456789<<47
<<bsoncxx::builder::stream::close_array
<<"friends" <<bsoncxx::builder::stream::open_array
<<"zhangsan"<<"lisi"<<"wangwu"
<<bsoncxx::builder::stream::close_array
<<"address0" <<bsoncxx::builder::stream::open_document
<<"city"<<"shenzhen"
<<"nation"<<"china"
<<"phone"<<13524531211
<<bsoncxx::builder::stream::close_document
(2)插入文档
collection.insert_one(document.view());
(3)查询全部文档
auto cursor = collection.find({});
for (auto&& doc : cursor) {
std::cout << bsoncxx::to_json(doc) << std::endl;
}
std::cout<<"
after insert_one three times count:"<<collection.count({})<<std::endl;
(4)删除文档
collection.delete_one(document.view());
std::cout<<"
after delete_one once count:"<<collection.count({})<<std::endl;
3.聚合函数查询
创建于数据库的连接
const char* URI = "路径";
mongocxx::client client{ mongocxx::uri{URI} };//开启客户端
mongocxx::v_noabi::database db = client["111"];//连接数据库
mongocxx::v_noabi::collection collection = db["222"];//创建对集合的连接
注意111是mongodb的文档名称,222是集合名称
聚合函数的写法
mongocxx::pipeline pipelineInst;//创建一个聚合查询对象
//mongodb语句
db.device_stats_day.aggregate({{unwind : '{data_yc'},
{{match:{'device_type': 1, 'data_yc.n': {{in: ['电流平均值']}, 'stats_time': {{gte: '2023-4-1', {lte: '2023-4-30'}}},
{{group: { _id: {n: '{data_yc.n',t:'{stats_time'}, algo: { {max:
'{data.v' }}})
pipelineInst.unwind("{data_YC")
.match(make_document(kvp("device_id", 10), kvp("data_YC.n", make_document(kvp("{in", make_array(mongofield)))), kvp("stats_time", make_document(kvp("{gte", mongobeginmonth), kvp("{lte", mongoendmonth))))).group(make_document(kvp("_id", make_document(kvp("n","{data_YC.n"), kvp("t", "{stats_time"))), kvp("algo", make_document(kvp(mongoalgo, "{data_YC.v")))));//查询mongodb命令
auto results = collection.aggregate(pipelineInst);//查询到的结果
bsoncxx提供了2个很好用的方法用来转换json到bson,然后,加工一下就可以了
将结果进行循环取出再做数据处理,需要用到QT里面的QJsonDocument类,import即可
for (const auto& result_place : results) {//将数据进行循环
QJsonDocument qq = QJsonDocument::fromJson(QByteArray::fromStdString(bsoncxx::to_json((result_place))));//mongodb数据类型转换成qt数据类型
QJsonObject mongoobj = qq.object();//转换成qjosn进行处理
if (mongoobj.contains(QString("algo")) && (QVariant(mongoobj.value(QString("algo"))).canConvert<int>()))
{
ycv = QVariant(mongoobj.value(QString("algo"))).value<int>();
mongodbitem.data_num = QString::number(ycv);
}
}
内部处理逻辑,参考即可
这里需要提醒的是,unwind、match、group,这些其实都是pipeline的操作,可以看mongocxx源码里自带的例子,毕竟都开源了,这些都有涉及。
路径E:workWorkFileMongoDBmongo-cxx-driver-r3.7.1mongo-cxx-driver-r3.7.1srcmongocxx estcollection.cpp
七、总结
一、编译过程中的路径和版本号是坑,每一步都不能出错,不然报的错误让你看都看不懂。
二、Mongodb在qt中的写法跟其他与语言不一样,需要花一些时间去研究,最后在这里给大家安利一个mongo的编可视化
工具,Studio 3T,可以自动将Mongo的命令转换成其他语言语法,包括Java,python,c等等,唯独没有c++的,吐血
地址:https://studio3t.com/