QT编译mongodb进行聚合函数的查询

2023-09-28 11:38 李志远 822

一、简介

本篇文章主要讲述如何使用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?

知识产权问题

二、环境

Windows10

Visual Studio 2017

CMAKE 3.26.0

MongoDB 1.23.2

mongo-c-driver

mongo-cxx-driver

boost 1.81.0

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/