Doctrine2 - 使用全文和 MyIsam

发布于 2024-12-01 21:42:18 字数 232 浏览 1 评论 0原文

我正在 Symfony2 中构建一个应用程序,使用 Doctrine2 和 mysql。我想使用全文搜索。我找不到太多关于如何实现这一点的信息 - 现在我陷入了如何将表引擎设置为 myisam 的困境。

似乎无法使用注释设置表类型。另外,如果我通过运行“ALTER TABLE”查询手动执行此操作,我不确定 Doctrine2 是否会继续正常工作 - 它是否依赖于 InnoDB 外键?

有更好的地方可以问这些问题吗?

I am building an app in Symfony2, using Doctrine2 with mysql. I would like to use a fulltext search. I can't find much on how to implement this - right now I'm stuck on how to set the table engine to myisam.

It seems that it's not possible to set the table type using annotations. Also, if I did it manually by running an "ALTER TABLE" query, I'm not sure if Doctrine2 will continue to work properly - does it depend on the InnoDB foreign keys?

Is there a better place to ask these questions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

难忘№最初的完美 2024-12-08 21:42:18

简介

Doctrine2 使用 InnoDB,它支持 Doctrine 关联中使用的外键。但由于MyISAM还不支持这一点,所以你不能使用MyISAM来管理Doctrine Entities。

另一方面,目前正在开发的MySQL v5.6将带来InnoDB FTS的支持,因此将启用InnoDB表中的全文搜索。

解决方案

因此有两种解决方案:

  1. 使用 MySQL v5.6,风险自负,并修改一点 Doctrine 来实现 MATCH AGAINST 方法:链接法语...(如果需要的话我可以翻译,但仍然存在错误,我不会推荐这个解决方案)

  2. 如quickshifti所述,创建带有全文索引的MyISAM表只是为了执行搜索。由于 Doctrine2 允许本机 SQL 请求,并且您可以将此请求映射到实体 (详细信息在这里)。

第二个解决方案的示例

考虑下表:

table 'user' : InnoDB [id, name, email]
table 'search_user : MyISAM [user_id, name -> FULLTEXT]

然后您只需编写带有 JOIN 和映射(在存储库中)的搜索请求:

<?php

public function searchUser($string) {

    // 1. Mapping
    $rsm = new ResultSetMapping();
    $rsm->addEntityResult('Acme\DefaultBundle\Entity\User', 'u');
    $rsm->addFieldResult('u', 'id', 'id');
    $rsm->addFieldResult('u', 'name', 'name');
    $rsm->addFieldResult('u', 'email', 'email');

    // 2. Native SQL
    $sql = 'SELECT u.id, u.name FROM search_user AS s JOIN user AS u ON s.user_id = u.id  WHERE MATCH(s.name) AGAINST($string IN BOOLEAN MODE)> 0;

    // 3. Run the query
    $query = $this->_em->createNativeQuery($sql, $rsm);

    // 4. Get the results as Entities !
    $results = $query->getResult();

    return $results;
}
?>

但是 FULLTEXT 索引需要保持最新。您可以像这样添加触发器(INSERT、UPDATE 和 DELETE),而不是使用 cron 任务:

CREATE TRIGGER trigger_insert_search_user
AFTER INSERT ON user
FOR EACH ROW
INSERT INTO search_user SET user_id=NEW.id, name=NEW.name;

CREATE TRIGGER trigger_update_search_user
AFTER UPDATE ON user
FOR EACH ROW
UPDATE search_user SET name=name WHERE user_id=OLD.id;

CREATE TRIGGER trigger_delete_search_user
AFTER DELETE ON user
FOR EACH ROW
DELETE FROM search_user WHERE user_id=OLD.id;

这样您的 search_user 表将始终获得最后的更改。

当然,这只是一个例子,我想保持简单,而且我知道这个查询可以用 LIKE 来完成。

INTRODUCTION

Doctrine2 uses InnoDB which supports Foreign Keys used in Doctrine associations. But as MyISAM does not support this yet, you can not use MyISAM to manage Doctrine Entities.

On the other side, MySQL v5.6, currently in development, will bring the support of InnoDB FTS and so will enable the Full-Text search in InnoDB tables.

SOLUTIONS

So there are two solutions :

  1. Using the MySQL v5.6 at your own risks and hacking a bit Doctrine to implement a MATCH AGAINST method : link in french... (I could translate if needed but there still are bugs and I would not recommend this solution)

  2. As described by quickshifti, creating a MyISAM table with fulltext index just to perform the search on. As Doctrine2 allows native SQL requests and as you can map this request to an entity (details here).

EXAMPLE FOR THE 2nd SOLUTION

Consider the following tables :

table 'user' : InnoDB [id, name, email]
table 'search_user : MyISAM [user_id, name -> FULLTEXT]

Then you just have to write a search request with a JOIN and mapping (in a repository) :

<?php

public function searchUser($string) {

    // 1. Mapping
    $rsm = new ResultSetMapping();
    $rsm->addEntityResult('Acme\DefaultBundle\Entity\User', 'u');
    $rsm->addFieldResult('u', 'id', 'id');
    $rsm->addFieldResult('u', 'name', 'name');
    $rsm->addFieldResult('u', 'email', 'email');

    // 2. Native SQL
    $sql = 'SELECT u.id, u.name FROM search_user AS s JOIN user AS u ON s.user_id = u.id  WHERE MATCH(s.name) AGAINST($string IN BOOLEAN MODE)> 0;

    // 3. Run the query
    $query = $this->_em->createNativeQuery($sql, $rsm);

    // 4. Get the results as Entities !
    $results = $query->getResult();

    return $results;
}
?>

But the FULLTEXT index needs to stay up-to-date. Instead of using a cron task, you can add triggers (INSERT, UPDATE and DELETE) like this :

CREATE TRIGGER trigger_insert_search_user
AFTER INSERT ON user
FOR EACH ROW
INSERT INTO search_user SET user_id=NEW.id, name=NEW.name;

CREATE TRIGGER trigger_update_search_user
AFTER UPDATE ON user
FOR EACH ROW
UPDATE search_user SET name=name WHERE user_id=OLD.id;

CREATE TRIGGER trigger_delete_search_user
AFTER DELETE ON user
FOR EACH ROW
DELETE FROM search_user WHERE user_id=OLD.id;

So that your search_user table will always get the last changes.

Of course, this is just an example, I wanted to keep it simple, and I know this query could be done with a LIKE.

夏了南城 2024-12-08 21:42:18

Doctrine 在迁移到 Doctrine2 时放弃了 v1 中的全文可搜索功能。您可能必须在 Doctrine2 中推出自己的全文搜索支持。

我正在考虑使用迁移来生成表本身,使用本机 SQL 查询选项运行搜索查询来获取引用 Doctrine 管理的表的 id 集,然后使用所述 id 集通过 Doctrine 正常水合记录。

可能会定期执行一些任务来更新全文表。

Doctrine ditched the fulltext Searchable feature from v1 on the move to Doctrine2. You will likely have to roll your own support for a fulltext search in Doctrine2.

I'm considering using migrations to generate the tables themselves, running the search queries w/ the native SQL query option to get sets of ids that refer to tables managed by Doctrine, then using said sets of ids to hydrate records normally through Doctrine.

Will probly cron something periodic to update the fulltext tables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文