为了支持Symfony2中的全文索引,我使用MyISAM镜像表。我们定期将生产数据集复制到该表,并创建一个映射表结构的SearchEntity,并与真实实体相关联。因此,我们可以在SearchRepository上执行搜索查询(使用自定义MATCH AGAINST语句构建器),并通过解析关联来检索找到的实体。
现在,当我执行doctrine:schema:update
时,Doctrine2无法识别该表上的(手动添加的)索引,并希望删除它们。不幸的是,没有建议注释说“但保持这个索引完整!”。
我已经尝试使用@Index
注释使用与全文索引(前缀为ft_)相同的字段来欺骗Doctrine,然后手动执行一些SQL以用我的FT索引替换它们但是也失败了: Doctrine最初使用那些失败的伪索引创建表,因为索引键长度大于1000字节(这是MySQL中明显原因的硬限制)
问题是:我可以建议Doctrine在schema:update命令中保留它在表上找到的索引吗?有没有办法将其破解到框架中?在每次架构更新后重新创建全文索引非常麻烦:(
SearchEntity:
/**
* @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);
答案 0 :(得分:2)
我能够使用迁移解决此问题,然后添加具有相同名称的假索引。
迁移使用原始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将不再删除它们。
答案 1 :(得分:0)
答案 2 :(得分:0)
就像其他人回答的那样,在生产中使用doctrine:schema:update
不是一个好主意,因为代码中的任何小错误都可能导致数据库的一半丢失。
我处理一个相当大的项目,我们使用doctrine:schema:update --dump-sql
查找需要执行的查询并手动执行。
编辑:我还有另外一个建议是,如果你不想手动执行查询,你可以处理doctrine:schema:update --dump-sql
的输出过滤你不想执行的查询并运行其余的查询在数据库上。或者创建一个在更新模式后创建索引的命令,例如myproject:schema:createIndexes
(或其他)