Symfony2 / Doctrine2:不要在模式上删除全文索引:更新
Posted
技术标签:
【中文标题】Symfony2 / Doctrine2:不要在模式上删除全文索引:更新【英文标题】:Symfony2 / Doctrine2: Don't drop fulltext index on schema:update 【发布时间】:2013-11-09 22:01:29 【问题描述】:为了在 Symfony2 中支持全文索引,我使用了 MyISAM 镜像表。我们会定期将生产数据集复制到该表中,并创建一个 SearchEntity 来映射表的结构并与真实实体相关联。因此,我们可以在 SearchRepository 上执行搜索查询(使用自定义 MATCH AGAINST 语句构建器)并通过解析关联来检索找到的实体。
现在,当我执行 doctrine:schema:update
Doctrine2 时,它无法识别该表上的(手动添加的)索引并想要删除它们。不幸的是,没有建议注释说“但保持这个索引不变!”。
我已经尝试使用@Index
注释来欺骗 Doctrine,其字段与全文索引(前缀 ft_)中的字段相同,然后手动执行一些 SQL 以用我的 FT 索引替换它们,但同样失败:当 Doctrine 最初使用那些虚拟索引创建表失败,因为索引键长度大于 1000 字节(这是 mysql 中明显原因的硬限制)
问题是:我可以建议 Doctrine 将它在表中找到的索引原封不动地保留在 schema:update 命令上吗?有没有办法将其破解到框架中?每次模式更新后重新创建全文索引非常麻烦:(
搜索实体:
/**
* @ORM\Table(name="tmp_search2",options="engine"="MyISAM",
* uniqueConstraints=@ORM\UniqueConstraint(name="uq",columns="language_id","product_offer_id","product_group_id","retailer_id" ),
* indexes=@Index(name="price_idx", columns="product_offer_price"),
* @Index(name="started_at_idx", columns="product_offer_started_at"),
* @Index(name="ended_at_idx", columns="product_offer_ended_at"),
* @Index(name="ft_products", columns="product_name"),
* @Index(name="ft_product_group", columns="product_group_name"),
* @Index(name="ft_product_retailer", columns="retailer_name")
*
* )
* @ORM\Entity(repositoryClass="SearchRepository")
*/
class SearchEntity
/**
* This field is only here to satisfy doctrine's need for a non-composite primary key.
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $searchId;
/**
* @ORM\ManyToOne(targetEntity="ProductOffer")
* @ORM\JoinColumn(name="product_offer_id", referencedColumnName="id")
*/
private $productOffer;
/**
* @var integer
*
* @ORM\Column(name="product_offer_price", type="integer")
*/
private $price;
创建 tmp_search 索引的 SQL(首先删除学说留下的内容,然后创建我们的)
DROP INDEX ft_products ON tmp_search2;
DROP INDEX ft_product_group ON tmp_search2;
DROP INDEX ft_product_retailer ON tmp_search2;
# import product data and then...
CREATE FULLTEXT INDEX ft_products ON tmp_search2 (product_name,product_short_text,product_long_text);
CREATE FULLTEXT INDEX ft_product_group ON tmp_search2 (product_group_name);
CREATE FULLTEXT INDEX ft_product_retailer ON tmp_search2 (retailer_name);
【问题讨论】:
这不是直接的解决方案,但您可以创建自己的控制台命令,该命令在内部执行doctrine:schema:update
,然后运行您的自定义 SQL 以创建附加索引
所以我永远不会再执行教义:模式:更新自身?不,我认为它属于框架并且在那里很好(每个人都知道它应该如何工作:如果它说,一切都很好,一切都很好)。我认为 Doctrine 方面需要做一些工作来真正解决这个问题。但也许有一些方法可以扩展 Doctrine 的类型(最好使用包),以便正确识别全文索引
在 Doctrine 2.5 中有一个“标志”选项。设置为“全文”,它将能够自动创建 ft 索引:***.com/questions/23448266/…
【参考方案1】:
我能够使用迁移解决此问题,然后添加具有相同名称的虚假索引。
迁移使用原始 SQL 添加了实际全文索引:
$this->addSql('ALTER TABLE content ADD FULLTEXT fulltext_content(title, description)');
然后我将索引添加到实体定义中:
@ORM\Table(name="content", indexes=@ORM\Index(name="fulltext_content",columns="title","description"))
只要你先生成全文索引,Doctrine 就不会再删除它们了。
【讨论】:
这实际上是在不久前开始工作的(我不知道,什么时候)。现在也在用这个。【参考方案2】:就像其他人回答的那样,在生产环境中使用 doctrine:schema:update
不是一个好主意,因为代码中的任何小错误都可能导致一半的数据库被丢弃。
我在一个相当大的项目上工作,我们使用doctrine:schema:update --dump-sql
来查找需要执行的查询并手动执行它们。
编辑:我另外唯一的建议是,如果您不想手动执行查询,您可以处理 doctrine:schema:update --dump-sql
的输出,过滤您不想执行的查询并在数据库。或者创建一个在更新架构后创建索引的命令,例如myproject:schema:createIndexes
(或其他)
【讨论】:
【参考方案3】:-
不应在生产环境中使用学说:模式:更新。请改用迁移。
我记得 Doctrine 2 没有完全支持 MyIsam,但您可以手动创建表并使用它
Mysql 全文搜索不是搜索的最佳选择。也许 Sphinx 或 Lucene 更适合您的任务?
【讨论】:
1.我们正处于一个大型迁移过程中,并且每天都迁移我们的数据 -> 它可能会发生很大变化,因此无论如何我们都必须导入大部分数据,因此重新创建数据库不是问题。 2. Doctrine 只允许你注释一个实体的表来使用 MyISAM。该表是自动生成的,但明显缺少的外键会刺激命令。 3. 当然可以,但是只要您的管理团队不愿意支持它,您就必须使用您所拥有的 :)以上是关于Symfony2 / Doctrine2:不要在模式上删除全文索引:更新的主要内容,如果未能解决你的问题,请参考以下文章
在 Doctrine2/Symfony2 中的重复条目上插入忽略
如何在 Doctrine2 (Symfony2) 中按案例排序
Doctrine2 自定义类型不像主键 Symfony2 那样工作