2021.07.18 技術シェア
【技术浅谈】Laravel中如何结合原生Mongo语句做聚合查询

前言


使用Laravel在MongoDB中做查询的时候,一般会使用Laravel Eloquent ORM构建查询语句,再使用Laravel自带的一些方法,例如:get(), select(), chunk()等。但是在做一些复杂的联表查询的时候,Laravel自带的一些方法会不太适用,或者会有查询性能不高等问题,所以这时需要结合原生Monogo语句来做复杂查询。本文主要记录如何通过aggregate()来进行聚合查询, 包括如何进行联表查询,联表查询求和,如何添加日期过滤器(date filter)到数据中。网上关于这方面的资料很多,但是坑也很多,记录一下这次经历希望能帮到大家。

 

#在看这篇文章之前,你需要了解


MongoDB的基本查询方式及aggregate()的使用方法


Laravel框架基本结构


Laravel Eloquent ORM


 

#本文使用的版本及工具


Laravel 5.x


MongoDB 4.4.2


Robo 3T -> MongoDB可视化工具


 


图片


 

解决思路


要想在Laravel中结合原生Monogo语句来做复杂查询,首先需要在Robo 3T中查询到希望的数据,在Robo 3T中写好了查询语句后,再将MongoDB查询语句改写成Laravel的aggregate()查询形式。


在调试过程中可以使用以下语句查询Laravel中运行的MongoDB查询语句~


在Robo 3T中写好查询语句后,在第4行中写入查询语句。之后便可以在storage->logs中查看Log::info()打印出来的查询信息。


图片


 

实例


我们现在有两张表,Campaign和Dailyinsight表。一个活动(campaign)有很多天的贩卖数据(dailyinsight),某个dailyinsight只属于一个活动,他们通过相同的provider_campaign_id相连。


他们在Model中的结构如下:


图片


在以上表结构的基础上,我们现在想求每一个Campaign他们在某个时间段内spend的总和是多少,这就需要加上一个时间过滤器。但是MongoDB中的时间类型和Laravel中的不太一样,所以要做一个时间类型的转换,下面我们会讲到。首先看如何在MongoDB中实现联表查询,联表查询求和以及日期过滤器


关于MongoDB中aggregate()的详细使用方法可以参照这下面篇文章,这里不做详述:https://www.jianshu.com/p/c10ce6792d25


 


在MongoDB中构建好查询语句后,就可以进行下一步了,构建好的查询语句形式应该如下:


图片


这里可以在MongoDB中实现对关联表的某列求和sum(Line26),除此之外,还可以实现对关联表的min,max,avg等操作。在MongoDB中实现我们想要的聚合查询后,就可以在Laravel中进行聚合查询了。


关于如何在Laravel中使用aggregate()可以参考下面这篇文章,这里不做详述:https://learnku.com/articles/53545


 


在Laravel中构建好的查询语句如下:


图片


这里new\MongoDB\BSON\UTCDateTime在vscode里可能会提示undefined type,但是不影响运行。至此,通过aggregate(),$match,$lookup,$unwind和$group,我们已经将查询到的每一个campaign在某个时间段内的spend总和返回到了调用的函数中。


 


总的来说,这次构建查询语句踩了很多坑,特别是在添加日期过滤器这一块,尝试了网上很多方法,也是通过这个方法实现了。最后代码可能还有不足之处,希望和大家多多交流。


 


参考资料:


https://learnku.com/articles/53545


https://blog.csdn.net/vierhang/article/details/92982810


https://www.jianshu.com/p/c10ce6792d25


 


图片