0
我有一個有點令人費解的搜索查詢,我想使效率更高(如果可能)。如何讓此搜索查詢更高效?
下面是該查詢的全部代碼:
Route::post('api/search/{startRow}', function($startRow)
{
$category = Category::where('name', '=', Input::get('category'))->first();
// Initialize query
$query = Resource::with('alerts', 'alerts.type', 'user', 'category', 'comments', 'comments.comments', 'ratings')
->where('duplicate', '=', 0);
// Limit search results
if(Input::get('show'))
{
$show = Input::get('show');
switch ($show) {
case 'verified':
$query->where('verified', '=', true);
break;
case 'unverified':
$query->where('verified', '=', false);
break;
case 'alerted':
$query->has('alerts');
break;
case 'unalerted':
$query->has('alerts', '=', 0);
break;
default:
// The default will be 'all' (show all results)
break;
}
}
if($category->name != "everything")
$query->where('category_id', '=', $category->id);
// Sort the search results
if(Input::get('sort_type'))
{
$sort_by = Input::get('sort_type');
switch ($sort_by)
{
case 'relevance':
break;
case 'name_asc':
$query->orderBy('name', 'asc');
break;
case 'name_desc':
$query->orderBy('name', 'desc');
break;
case 'rating_high':
$query
->leftJoin('ratings', 'ratings.ratable_id', '=', 'resources.id')
->where('ratings.ratable_type', '=', 'Resource')
->orderBy(DB::raw('avg(ratings.score)'), 'desc')
->orderBy(DB::raw('count(ratings.score)'), 'desc')
->select('resources.*')
->groupBy('resources.id');
break;
case 'rating_low':
$query
->leftJoin('ratings', 'ratings.ratable_id', '=', 'resources.id')
->where('ratings.ratable_type', '=', 'Resource')
->orderBy(DB::raw('avg(ratings.score)'), 'asc')
->orderBy(DB::raw('count(ratings.score)'), 'asc')
->select('resources.*')
->groupBy('resources.id');
break;
case 'date_new':
$query->orderBy('created_at', 'desc');
break;
case 'date_old':
$query->orderBy('created_at', 'asc');
break;
default:
break;
}
}
// Search by keyword(s)
if(Input::get('keyword'))
{
$search = Input::get('keyword');
$searchTerms = explode(' ', $search);
$fields = array(
'resources.description',
'resources.website',
'resources.additional_info');
foreach ($searchTerms as $term)
{
$query->where('resources.name', 'LIKE', '%'. $term .'%');
foreach ($fields as $field)
{
$query->orWhere($field, 'LIKE', '%'. $term .'%');
}
}
}
// Search by tag(s)
if(Input::get('tags'))
{
$tags = Input::get('tags');
$query
->select('resources.*')
->join('taggables', 'taggables.taggable_id', '=', 'resources.id')
->join('tags', 'taggables.tag_id', '=', 'tags.id')
->whereIn('tags.id', $tags)
->groupBy('resources.id')
->havingRaw('COUNT(resources.id)=?', array(count($tags)));
}
// Total number of results
$count = $query->get()->count();
// Page number and offset for infinite scroll
$query->skip($startRow)->take(10);
// Get our first set of tiles
$tiles = $query->get();
return Response::json(array(
'count' => $count,
'tiles' => $tiles->toArray()));
});
你看,我都充滿了「資源」,這(通過數據透視表)的數據庫相關的標記,註釋和提醒,我想這些資源可以通過以下任何標準進行搜索: 資源模型本身包含的文本,與資源關聯的標記以及關聯的警報數量。
我遇到的一個問題是關鍵字搜索似乎不夠「準確」。當我搜索「風險投資公司」時,在包含「風險投資公司」這一短語之前會返回一些結果 - 用戶絕對不會期望這一點。
我與選擇「顯示」類型有關的另一個問題(即$query->has('alerts')
,如果用戶只想查看帶有警報的資源)。如果我輸入關鍵字搜索和顯示類型(如上所述),結果仍將包含沒有警報的資源(即使我指定了我只希望具有警報的資源)。
謝謝 - 這有幫助!查看[http://laravel.com/docs/queries#advanced-wheres](http://laravel.com/docs/queries#advanced-wheres)也很有用。你的代碼中有幾個語法錯誤,但我明白。 – chipit24 2014-08-30 18:09:53
@ cornflakes24我不認爲這裏有任何語法錯誤,除了'$ q'和'$ query',這確實是錯誤的,並且也缺少了parens。假設這就是你的意思 – 2014-08-30 19:22:51
是的,這就是我的意思!我想''q'和'$ query'的混淆會是一個語義錯誤,缺少的括號會是一個語法錯誤,不是嗎? – chipit24 2014-08-31 16:47:01