13

为了支持 Symfony2 中的全文索引,我使用了 MyISAM 镜像表。我们会定期将生产数据集复制到该表中,并创建一个 SearchEntity 来映射表的结构并与真实实体相关联。因此,我们可以在 SearchRepository 上执行搜索查询(使用自定义 MATCH AGAINST 语句构建器)并通过解析关联来检索找到的实体。

现在,当我执行doctrine:schema:updateDoctrine2 时,无法识别该表上的(手动添加的)索引并想要删除它们。不幸的是,没有建议注释说“但保持这个索引不变!”。

我已经尝试使用具有@Index与全文索引(前缀为 ft_)中相同字段的注释来欺骗 Doctrine,然后手动执行一些 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);
4

3 回答 3

3

我能够使用迁移解决这个问题,然后添加具有相同名称的虚假索引。

迁移使用原始 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 就不会再删除它们。

于 2015-06-18T15:54:30.867 回答
1

就像其他人回答的那样,在生产环境中使用它不是一个好主意,doctrine:schema:update因为代码中的任何小错误都可能导致一半的数据库被丢弃。

我在一个相当大的项目上工作,我们用它doctrine:schema:update --dump-sql来查找需要执行的查询并手动执行它们。

编辑:我另外的唯一建议是,如果您不想手动执行查询,您可以处理doctrine:schema:update --dump-sql过滤器的输出,您不想执行的查询并在数据库上运行剩余的查询。或者创建一个在更新架构后创建索引的命令,例如myproject:schema:createIndexes(或其他)

于 2014-07-10T11:27:03.357 回答
0
  1. 您不应该在生产中使用学说:模式:更新。改用迁移。
  2. 我记得 Doctrine 2 没有完全支持 MyIsam,但您可以手动创建表并使用它
  3. Mysql全文搜索不是搜索的最佳选择。也许 Sphinx 或 Lucene 更适合您的任务?
于 2014-02-14T07:46:24.397 回答