Laravel Eloquent 相当于 QueryBuilder 查询

Posted

技术标签:

【中文标题】Laravel Eloquent 相当于 QueryBuilder 查询【英文标题】:Laravel Eloquent equivalent of a QueryBuilder query 【发布时间】:2020-10-06 02:48:06 【问题描述】:

我有一个 Laravel 7 项目和这个数据库结构:

 races      participants      bibs      coords
-------    --------------    ------    --------
 id         id                id        id
            race_id                     bib_id
            bib_id                      [...]

关系是:

1 race        =>  N participants  ( races.id = participants.race_id )
1 participant =>  1 bib           ( participants.bib_id = bibs.id )
1 bib         =>  N coords        ( bibs.id = coords.bib_id )

所以也表示:participants.bib_id = coords.bib_id

我想获取与特定种族相关的所有坐标。 我这样做的方式是使用这样的查询生成器:

class Race extends Model

    public function getCoords()
    
        return Coord::join('participants', 'participants.bib_id', '=', 'coords.bib_id')
            ->where('participants.race_id', $this->id)->select('coords.*')->get();
    

在这里我可以做到:

$coords = Race::find(1)->getCoords();

它按预期工作,但我正在寻找一种使用 Eloquent 的方法,以便更容易与更多的关系和东西链接。 我用belongsToManyhasManyThrough 尝试了很多东西,但没有任何效果。我想知道这是否可能?

【问题讨论】:

【参考方案1】:
// Race
public function participants()

    return $this->hasMany(Participant::class);


// Participant
public function bib()

    return $this->belongsTo(Bib::class);

public function race()

    return $this->belongsTo(Race::class);


// Bib
public function coords()

    return $this->hasMany(Coord::class);


// Coord
public function bib()

    return $this->belongsTo(Bib::class);

现在,您想要的是找到给定种族的坐标。

$race = Race::find($id)->with('participants.bib.coords');

现在,从中提取坐标。

$coords = $race->participants->map(function($participant)
              return $participant->bib->coords;
          );

让我在下面的 cmets 中发布。干杯!

【讨论】:

我需要写Race::with('participants.bib.coords')->find(1) 而不是Race::find($id)->with('participants.bib.coords')。但这很酷。 您认为此解决方案会导致性能问题吗?想象一下像 500 个参与者有 100 000 个坐标(总共)。获取坐标的请求将用于 Openlayers 地图,该地图旨在让大约 10,000 个用户一目了然。我不知道 Web 和数据库服务器的收费是多少。 另外,在这张地图上,将有另一个 http 请求刷新所有比赛参与者的最后“坐标”(时间戳列上会有一个过滤器)。每分钟都有一个 AJAX 调用。如果有大约 10,000 名用户在观看地图,您认为这可能是您提议的方式有问题吗? 是的,目前您正在从每个关系中选择所有列。请通过此链接 (***.com/a/60015685/5326191)。这将引导您完成优化。 好的,如果我按照你写的,我应该考虑为这种操作保留我的查询生成器函数,因为它减少了执行的 SQL 查询的数量(从我的测试 => 减少从 4 到 1 [但有一个 JOIN])。我应该和select() 一起做,以便只获取我需要的列。对吗?

以上是关于Laravel Eloquent 相当于 QueryBuilder 查询的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Eloquent 关系——相当于 MYSQL “join”

Laravel Eloquent 相当复杂的关系

如何在 Laravel 5.8 中使用 Eloquent 进行查询?

Laravel 5.2 pluck() 来自 Eloquent 模型集合的多个属性

如何在 Eloquent 模型中使用 Laravel Livewire?

用 Laravel/Eloquent 为 Yajra DataTables 编写连接查询的慢 MySQL