我正在使用Laravel 4和Eloquent模型进行我们正在开发的项目。 数据库符合3NF,一切都很好。从MySQL版本开始,所有MySQL表都从InnoDB切换回MyISAM。 5.6(InnoDB中的全文搜索仅支持5.6及更高版本。)
在创建一些数据库搜索过滤器时,我发现使用Eloquent模型与查询生成器相比存在一些不足。具体而言,特别是在尝试对多个表中的列进行全文搜索时(并保留在Eloquent的对象上下文中)。
为简单起见,我们有以下数据库结构:
--projects
--id
--name
--status
--...
--users
--id
--...
--roles
--id
--project_id
--user_id
--...
--notes
--id
--project_id
--user_id
--note
--....
以下代码(问题的简化和最小化)目前工作正常,但全文搜索仅适用于一个表(projects
表)。
if (Request::isMethod('post'))
{
$filters = array('type_id','status','division','date_of_activation','date_of_closure');
foreach ($filters as $filter) {
$value = Input::get($filter);
if (!empty($value) && $value != -1) {//-1 is the value of 'ALL' option
$projects->where($filter,'=',$value);
}
}
$search = Input::get('search');
if (!empty($search)) {
$projects->whereRAW("MATCH(name,description) AGAINST(? IN BOOLEAN MODE)",array($search));
}
}
// more code here...
// some more filters...
// and at the end I am committing the search by using paginate(10)
return View::make('pages/projects/listView',
array(
"projects" => $projects->paginate(10)
)
);
我需要扩展全文搜索以包含以下列:projects.name
,projects.description
和notes.note
。
在试图找到如何使用Eloquent时,我们继续回到查询生成器并运行自定义查询,这将工作正常,但我们将面临这些问题/缺点:
Project::find($id)
来重新获得对象。阅读Laravel的文档和API,我找不到使用Eloquent运行原始SQL查询的方法。有whereRAW()
,但不够广泛。我认为这是设计所造成的限制,但它仍然是一种限制。
所以我的问题是:
Project::find($id)
。)where
方法链接在一起,而仅在稍后使用get()
或paginate(10)
提交。据我所知,Eloquent和Query Builder是不同的生物。但是如果混合两者都可以,或者使用Eloquent来运行原始SQL查询,我相信Eloquent模型将变得更加健壮。在我看来,仅使用查询生成器有点像使用Laravel框架。
希望得到一些有关这方面的见解,因为Laravel的论坛/社区似乎仍在不断发展,尽管我发现它是一个了不起的框架!
谢谢,感谢您提出的任何意见:)
答案 0 :(得分:4)
首先,您可以在模型中使用查询范围
public function scopeSearch($query, $q)
{
$match = "MATCH(`name`, `description`) AGAINST (?)";
return $query->whereRaw($match, array($q))
->orderByRaw($match.' DESC', array($q));
}
通过这种方式,您可以获得“eloquent collection”作为回报
$projects = Project::search(Input::get('search'))->get();
然后,要搜索笔记,你可以制作一个更复杂的范围,加入笔记并在那里搜索。
答案 1 :(得分:1)
不确定这是否有帮助,但innoDB中有一种解决方法(在支持全文搜索的版本中),也许它适用于你。
让我们使用'笔记'作为第二个表格
SELECT MATCH(name,description) AGAINST(? IN BOOLEAN MODE),
MATCH(notes.note) AGAINST(? IN BOOLEAN MODE)
FROM ...
WHERE
MATCH(name,description) AGAINST(?) OR
MATCH(notes.note) AGAINST(?)