필자는 다소 복잡한 회선 검색 쿼리를 사용하여 가능한 한 효율적으로 만들고 싶습니다. 여기 이 검색 쿼리를보다 효율적으로 만들 수 있습니까?
이 쿼리에 대한 전체 코드입니다 : 는 "자원"(피벗 테이블을 통해) 가득 데이터베이스가 태그, 코멘트 및 경고와 관련된 볼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()));
});
, 내가 있고, 내가 원하는 이 자원은 다음 기준 중 하나에서 검색 가능합니다. 자원 모델 자체에 포함 된 텍스트, 자원과 연관된 태그 및 연관된 경고 수.
키워드 검색이 "정확함"정도로 충분하지 않은 것 중 하나가 있습니다. "Venture Firm"이라는 단어를 검색 할 때 "Venture Firm"이라는 문구가 들어가기 전에 몇 가지 결과가 반환됩니다. 사용자는 확실히 이것을 예상하지 않을 것입니다.
또 다른 문제 "표시 유형"(즉, 사용자가 알림이있는 리소스 만보고 싶다면 $query->has('alerts')
)을 선택하는 것과 관련되어 있습니다. 위와 같이 키워드 검색 및 프로그램 유형을 입력하면 검색 결과에는 경고가없는 리소스가 포함됩니다 (알림이있는 리소스 만 필요함).
감사합니다. - 도움이되었습니다. [http://laravel.com/docs/queries#advanced-wheres](http://laravel.com/docs/queries#advanced-wheres)를 보는 것도 유용했습니다. 코드에 몇 가지 구문 오류가 있지만 이해합니다. – chipit24
@ cornflakes24 필자는'$ q'와'$ query'와는 별개로 거기에 구문 오류가 없다고 생각합니다. 잘못 입력했거나 괄호가 누락되었습니다. 이것이 당신이 의미하는 것이라고 가정합니다. –
네, 그게 제가 의미했던 것입니다! 나는'$ q'와'$ query'와의 혼동은 의미 론적 오류가 될 것이고 누락 된 괄호는 구문 오류가 될 것이라고 생각합니까? – chipit24