我有两个关系一对多的表。我的任务很简单,我需要关联条件表中的每个父项最后一个条件。
第一个表为状态:
async function updateUuid() {
try {
const users = await Users.find({});
for (const user of users) {
const uuid = uuid();
await User.findByIdAndUpdate(user._id, { $set: { newId: uuid } });
}
} catch (e) {
console.error(e);
}
}
关系是
| id | partner_id | status | created_at |
|----|------------|--------|---------------------|
| 1 | 1 | 1 | 2018-01-01 00:00:00 |
| 2 | 1 | 5 | 2018-02-01 00:00:00 |
| 3 | 2 | 1 | 2018-01-01 00:00:00 |
第二个伙伴:
public function partner()
{
return $this->belongsTo(Partner::class, 'partner_id');
}
关系是
| id | name |
|----|-----------|
| 1 | partner_1 |
| 2 | partner_2 |
假设我想让所有合作伙伴的最近状态为1。我尝试过:
public function status()
{
return $this->hasMany(Status::class, 'partner_id')->orderBy('id', 'desc');
}
结果是这样的:
Partner::with('status')
->whereHas('status', function ($query) use ($status) {
$query->where('status', $status);
})
->get();
但是有了它,即使他的最后一个状态为5,但我也会得到partner_1,但历史上他的状态为1。
我创建了sql查询来获取此信息,但是我认为完成这样一个简单的任务相当复杂。而且我认为必须有一些简单的Laravel方法:
"select * from `partners` where exists (select * from `status` where `partners`.`id` = `status`.`partner_id` and `status` = 1)"
我的目标是只获得partner_2,因为只有他的最后状态为1。
答案 0 :(得分:0)
一种方法是自定义关系方法以包括一些排序(如@ yrv16所建议)
但是,要提高效率,最好的方法是子查询。一个非常good article by J. Reinink的人很好地解释了这一点。
简而言之,是这样的:
class Partner extends Model {
// ...
public function scopeWithLastStatus($query)
{
$query->addSubSelect('last_status', Status::select('status')->latest());
}
// ...
这会将“虚拟”属性last_status
添加到模型中。
然后您可以执行以下操作:
Partner::withLastStatus()->get()->where('last_status', 'idle');
答案 1 :(得分:0)
您可以使用此:
Partner::select('partners.*')
->join('status', 'partners.id', 'status.partner_id')
->where('status.status', $status)
->where('status.id', function($query) {
$query->select('id')
->from('status')
->whereColumn('partner_id', 'partners.id')
->orderByDesc('id')
->limit(1);
})->get();