запустить whereHas метод laravel на больших наборах данных mysql

у меня есть Conversation модель как это:

class Conversation extends Model
{
use SoftDeletes;

protected $primaryKey = 'conversation_id';
protected $dates      = ['deleted_at', 'expert_read_at', 'expert_admin_read_at'];
protected $fillable   = ['code', 'expert', 'expert_read_at', 'expert_admin', 'expert_admin_read_at'];

public function questions (){
return $this->hasMany('App\Question','conversation_id','conversation_id');
}
}

И модель вопроса, как это:

class Question extends Model
{
use SoftDeletes;

protected $primaryKey = 'question_id';
protected $dates      = ['deleted_at', 'confirmed_expert_admin_at'];
protected $fillable   = ['text', 'answer', 'conversation_id', 'confirmed', 'is_private', 'email', 'confirmed_expert_admin_at'];

public function conversation ()
{
return $this->belongsTo('App\Conversation', 'conversation_id', 'conversation_id');
}
}

Как вы можете видеть, есть hasMany отношения между Conversation а также Question моделей.

В базе данных MySQL о 34000 записи для Conversation и каждый из них имеет по крайней мере один связанный Question,

С другой стороны, на фронте есть форма, в которую пользователь может ввести текст для поиска по вопросу. text поле.

Теперь я хочу выбрать разговоры, в которых есть хотя бы вопрос. В соответствии с пользовательским вводом, а затем разбить результаты на страницы.

Для этого я написал:

function SearchQuestion (Request $request)
{
$page            = $request->get('page');
$questionPerPage = $request->get('question-per-page');
$text            = $request->get('question-search-text');

$conversations =
Conversation::whereHas('questions', function ($q) use ($text) {
if (!empty($text)) {
if (!is_numeric($text)) {
$q->where('text', 'LIKE', '%' . $text . '%')
->where('is_private', 0)
->where('answer', '<>', '')
->where(function ($q1) {
$q1->where('confirmed', 1)
->orWhere('confirmed_expert_admin_at', '<=', Carbon::now()->subDay());
});
}
} else {
$q
->where('is_private', 0)
->where('answer', '<>', '')
->where(function ($q1) {
$q1->where('confirmed', 1)
->orWhere('confirmed_expert_admin_at', '<=', Carbon::now()->subDay());
});
}
}
);

if (!empty($text) and is_numeric($text)) {
$conversations->whereCode($text);
}

$conversations->orderBy('created_at', 'desc');

$conversations = $conversations->paginate(5);

return $conversations;
}

Как вы можете видеть, я использовал whereHas() метод поиска в вопросах каждого разговора.

Но каждый раз, когда я запускаю запрос выше, с первой попытки требуется много времени для выполнения запроса о 12 секунд и в следующих попытках не возвращает никакого результата и MySQL падает, и я должен перезапустить WAMP.

Тем не менее, я хотел бы затем выбрать вопросы каждого выбранного разговора, используя with() метод Ларавелла. В этом случае я не знаю, сколько времени займет выполнение запроса?

я использую Laravel 5.3 и вамп 3.0.6 (Apache 2.4.23 — PHP 5.6.25 / 7.0.10 — MySQL 5.7.14) в Windows 8, 64-разрядная версия.

В чем проблема? Что я могу сделать?

ОБНОВИТЬ:
Я добавляю индекс к первичным ключам и внешним ключам для двух таблиц, и все работает нормально.

0

Решение

Попробуй это. добавлять with() до того, где.

 Conversation::with('questions')->whereHas('questions', function ($q) use ($text) {
//your conditions on questions rows
});
0

Другие решения

Вы можете попытаться адаптировать Eagerloading следующим образом.

$conversations = Conversation::with(['questions' => function ($q) use ($text) {
if (!empty($text)) {
if (!is_numeric($text)) {
$q->where('text', 'LIKE', '%' . $text . '%')
->where('is_private', 0)
->where('answer', '<>', '')
->where(function ($q1) {
$q1->where('confirmed', 1)
->orWhere('confirmed_expert_admin_at', '<=', Carbon::now()->subDay());
});
}
} else {
$q
->where('is_private', 0)
->where('answer', '<>', '')
->where(function ($q1) {
$q1->where('confirmed', 1)
->orWhere('confirmed_expert_admin_at', '<=', Carbon::now()->subDay());
});
}
}]);

Попробуйте это и посмотрите, уменьшится ли нагрузка на сервер.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector