LaravelWhereHas 在数据透视表(大数据)上速度很慢

问题描述 投票:0回答:2

我想在 Laravel 中

Pivot
表中
Person
Topics
之间应用 where 条件。

我基本上有一张

Person
桌子和一张
Topics
桌子。

中间有一个数据透视表

person_topic
,其中包含两个外键(
person_id
topic_id
)以及
quantity

我放置了一个带有

::query()
whereHas
方法,该方法基于“主题 id”数组,在数据透视表中执行
whereIn
条件
person_topics

$from = request('from');
$to = request('to');
$topics = request('topics');
$unity = request('unity');
$limit = request('limit');

$eventsQuery = Event::query();

if (! is_null($topics) && $topics != "undefined") {
    $topics = array_map('intval', explode(',', $topics));
    $eventsQuery = $eventsQuery->whereHas('person.topics', function ($query) use ($topics) {
        return $query->whereIn('topic_id', $topics);
    });
}

$events = $eventsQuery->orderBy('date', 'DESC')
    ->whereIn('station_id', [$unity])
    ->whereBetween('date', [$from, $to])
    ->with('person')
    ->with('person.country')
    ->with('train')
    ->with('station')
    ->limit($limit)
    ->get();

return response()->json([
    'events' => $events,
    'message' => 'Success'
], 200);

该方法有效并返回了预期的结果,只是需要 2 分钟才能收到响应。

如何优化/修改我的代码以使我的请求执行得更好?


完整方法代码

$from = request('from');
$to = request('to');
$topics = request('topics');
$trains = request('trains');
$countries = request('countries');
$unity = request('unity');
$limit = request('limit');

if(is_null($trains) && $trains == "undefined" ){
    $limit = Event::count();
}

$eventsQuery = Event::query();

if(!is_null($countries) && $countries != "undefined" ){
    $countries = array_map('intval', explode(',', $countries));
    $eventsQuery = $eventsQuery->whereHas('person.country', function ($query) use ($countries) {
        return $query->whereIn('id', $countries);
    });
}
if(!is_null($trains) && $trains != "undefined" ){
    $trains = array_map('intval', explode(',', $trains));
    $eventsQuery = $eventsQuery->whereHas('train', function ($query) use ($trains) {
        return $query->whereIn('id', $trains);
    });
}
if(!is_null($topics) && $topics != "undefined" ){
    $topics = array_map('intval', explode(',', $topics));
    $eventsQuery = $eventsQuery->whereHas('person.topics', function ($query) use ($topics) {
        return $query->whereIn('topic_id', $topics);
    });
}

$events = $eventsQuery->orderBy('date','DESC')->whereIn('station_id', [$unity])->whereBetween('date',[$from, $to])->with('person')->with('person.country')->with('train')->with('station')->limit($limit)->get();

return response()->json([
    'events' => $events,
    'countries' => $countries,
    'message' => 'Success'
], 200);
php laravel pivot-table query-optimization laravel-query-builder
2个回答
0
投票

你可以试试这个:
确保您创建了 2 个模型:

Person
Topic

创建
PersonTopic
模型并定义 2 个这样的关系

public function person()
{
    return $this->belongsTo('App\Models\Person', 'person_id', 'id');
}

public function topic()
{
    return $this->belongsTo('App\Models\Topic', 'topic_id', 'id');
}

然后就可以查询了

if(!is_null($topics) && $topics != "undefined" ){
    $topicIds = array_map('intval', explode(',', $topics));
    $rows = PersonTopic::with(['person', 'topic'])
            ->whereIn('topic_id', $topicIds)
            //can use whereHas if you want
            ->whereHas('topic', function ($query) use ($request) {
               $query->where('topics.column', $request->column);
            })
            ->get();
}

使用

foreach
循环获取详细信息

foreach ($rows as $row) {
   //get person detail
   $person = $row->person;
   //get topic detail
   $topic = $row->topic;
}

0
投票

如果您将人员的外键放入事件表中,则可以使用连接到人员和主题表的数据透视表而不是 where has 来优化查询。

查询:

$eventsQuery = $eventsQuery->whereHas('person.topics', function ($query) use ($topics) {
    return $query->whereIn('topic_id', $topics);
});

可以替换为:

$eventsQuery->join(
  'person_topic',
  'person_topic.person_id',
  '=',
  'events.person_id'
)
    ->whereIn('person_topic.topic_id', $topics);
© www.soinside.com 2019 - 2024. All rights reserved.