у меня есть 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-разрядная версия.
В чем проблема? Что я могу сделать?
ОБНОВИТЬ:
Я добавляю индекс к первичным ключам и внешним ключам для двух таблиц, и все работает нормально.
Попробуй это. добавлять with()
до того, где.
Conversation::with('questions')->whereHas('questions', function ($q) use ($text) {
//your conditions on questions rows
});
Вы можете попытаться адаптировать 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());
});
}
}]);
Попробуйте это и посмотрите, уменьшится ли нагрузка на сервер.