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