我在Laravel 4中实现了以下关键字搜索:
// Search by keyword(s)
if(Input::get('keyword'))
{
$search = Input::get('keyword');
$searchTerms = explode(' ', $search);
$fields = array(
'resources.name',
'resources.description',
'resources.website',
'resources.additional_info');
$query->where(function($query) use ($searchTerms, $fields) {
foreach ($searchTerms as $term)
{
foreach ($fields as $field)
{
$query->orWhere($field, 'LIKE', '%'. $term .'%');
}
}
});
}
问题:
我们假设我的表中有两个资源,一个名称为foo
,一个名称为bar
,另一个名称为foo bar
。它们是按顺序创建并放入我的表中的。现在,如果我搜索" foo bar",我得到的前两个结果将是foo
和bar
(因为它们在我的表中是拳头以匹配foo或bar) ,我的第三个结果将是foo bar
。如何进行此搜索,以便根据匹配的关键字数量对结果进行排序?因此foo bar
将是第一个结果。
答案 0 :(得分:1)
您应该使用FULLTEXT搜索来实现此目的。您没有指定您正在使用的数据库引擎,因此我将给出一个MySQL示例。
首先,您需要对要搜索的字段启用全文索引。
ALTER TABLE resources ADD FULLTEXT search (name,description,website,additional_info);
然后,您需要在查询中得到以下内容:
SELECT
*, MATCH(name,description,website,additional_info) AGAINST(SEARCH_TERMS) AS score
WHERE
MATCH(name,description,website,additional_info) AGAINST(SEARCH_TERMS)
我会在Laravel Query Builder中使用类似的东西(未经测试)来做到这一点:
if(Input::get('keyword'))
{
$search = Input::get('keyword');
$searchTerms = explode(' ', $search);
$fields = array(
'`resources.name`',
'`resources.description`',
'`resources.website`',
'`resources.additional_info`'
);
$fields_str = implode(',', $fields);
$query->whereRaw("match ($fields_str) against (? in boolean mode)")
$query->addSelect(DB::raw("match ($fields_str) against (? in boolean mode)")
// Need to bind twice because there are two question marks...
$query->setBindings(array($searchTerms, $searchTerms))
}
根据您的搜索,您可能需要或可能不需要in boolean mode
,或者您可能想要指定其他模式。有关详细信息,请参阅MySQL手册。
注意:大多数关系型数据库引擎在搜索方面并不是那么擅长;这不是他们最初设计的目的。如果您发现搜索需求比这个简单示例更复杂,您应该考虑运行Lucene,Sphinx,Elasticsearch或Solr等搜索服务器
(有关详细信息,请参阅http://blog.oneiroi.co.uk/mysql/php/mysql-full-text-search-with-percentage-scoring/和http://www.mullie.eu/mysql-as-a-search-engine/)
答案 1 :(得分:0)
我最终使用以下解决方案进行搜索:
if(Input::get('keyword')) {
$search = Input::get('keyword');
$query->whereRaw("MATCH(resources.name, resources.description, resources.website, resources.additional_info) AGAINST(? IN BOOLEAN MODE)",
array($search)
);
}
通过阅读以下页面,我找到了这个解决方案:
How to sort MYSQL fulltext search results by relevancy
http://creative-punch.net/2013/12/implementing-laravel-4-full-text-search/
我升级到MySQL 5.6,所以我可以为我的InnoDB表添加全文索引。我必须按照我在MATCH
语句中指定的顺序将全文索引添加到我想要运行whereRaw
的所有字段。