【问题标题】:Laravel - Full Text Search on Multiple TablesLaravel - 在多个表上进行全文搜索
【发布时间】:2014-02-19 19:48:55
【问题描述】:

我正在为我们正在进行的项目使用 Laravel 4 和 Eloquent 模型。 数据库符合 3NF,一切正常。此外,所有 MySQL 表都从 InnoDB 切换回 MyISAM,因为 MySQL 版本

在创建一些数据库搜索过滤器时,我发现使用 Eloquent 模型与 Query Builder 存在一些不足。具体而言,尤其是在尝试对多个表中的列进行全文搜索时(并保持在 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.nameprojects.descriptionnotes.note。 当试图找到如何使用 Eloquent 实现它时,我们会继续返回 Query Builder 并运行自定义查询,这会正常工作,但随后我们将面临这些问题/缺点:

  1. 查询生成器返回一个数组,而 Eloquent 返回模型对象。由于我们正在扩展每个模型以包含方法,因此我们真的不想放弃 Eloquent 模型的强大功能。而且我们真的不想在返回结果上使用 Eloquent Project::find($id) 只是为了再次获取对象。
  2. 我们正在链接“where”方法以获得任意数量的过滤器 分配给它以及代码可重用性。好像混合 Eloquent 和 Query Builder 语句一起会破坏我们的链接。
  3. 为了这个项目的一致性,我们希望所有的数据库查询 停留在雄辩的内涵中。

阅读 Laravel 的文档和 API,我找不到使用 Eloquent 运行原始 SQL 查询的方法。有whereRAW(),但不够广泛。我认为这是一个设计限制,但它仍然是一个限制。

所以我的问题是:

  1. 是否可以对多个表中的列进行全文搜索,仅在 Eloquent 中。我在网上看到的每条信息都使用查询生成器提及。
  2. 如果没有,是否可以使用查询生成器搜索并返回 Eloquent 对象? (无需在数组结果上运行Project::find($id))。
  3. 最后,是否可以将 Eloquent 和 Query Builder where 方法链接在一起,而仅在稍后使用 get()paginate(10) 进行提交。

我知道 Eloquent 和 Query Builder 是不同的生物。但是,如果可以将两者混合使用,或者使用 Eloquent 运行原始 SQL 查询,我相信 Eloquent 模型会变得更加健壮。在我看来,仅使用 Query Builder 有点像未充分使用 Laravel 框架。

希望对此有所了解,因为 Laravel 的论坛/社区似乎仍在发展,尽管我发现它是一个了不起的框架!

谢谢,感谢您的任何意见:)

【问题讨论】:

    标签: php mysql laravel laravel-4 eloquent


    【解决方案1】:

    首先,您可以在模型中使用查询范围

    public function scopeSearch($query, $q) 
    {        
       $match = "MATCH(`name`, `description`) AGAINST (?)";
       return $query->whereRaw($match, array($q))
                    ->orderByRaw($match.' DESC', array($q));  
    }
    

    这样你就可以得到“雄辩的收藏”作为回报

    $projects = Project::search(Input::get('search'))->get();
    

    然后,要同时搜索笔记,您可以创建一个更复杂的范围来连接笔记并在那里搜索。

    【讨论】:

    • 你能举个例子来说明更复杂的范围想法吗? @felice
    【解决方案2】:

    不确定这是否会有所帮助,但 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(?)
    

    【讨论】:

    • 谢谢,但这是一个原始 SQL,Laravel 的 Eloquent 不允许使用原始 SQL (AFAIK)。我将不得不为此使用查询生成器,但这就是我从一开始就提出问题的原因:) 它还使用 Active Record,所以我相信它禁止我在外部表列上运行匹配...跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    相关资源
    最近更新 更多