Symfony2/Doctrine2: не отбрасывать полный текст в схеме: update

Чтобы поддерживать полнотекстовую индексацию в Symfony2, я использую зеркальную таблицу MyISAM. Мы регулярно копируем наш производственный набор данных в эту таблицу и создаем SearchEntity, который отображает структуру таблицы и связан с реальными объектами. Таким образом, мы можем выполнять наши поисковые запросы в нашем SearchRepository (используя собственный конструктор операторов MATCH AGAINST) и извлекать найденные объекты, разрешая ассоциации.

Теперь, когда я выполняю doctrine:schema:update, Doctrine2 не распознает (добавленные вручную) индексы на этой таблице и хочет их удалить. К сожалению, нет аннотации к советам, в которой говорится: "Но не оставляйте этот индекс без изменений!".

Я уже пытался обмануть Doctrine с помощью аннотации @Index с теми же полями, что и в полнотекстовом индексе (prefixed ft_), а затем выполнить некоторый SQL вручную, чтобы заменить их моим индексом FT, но это также не срабатывает: когда первоначально была Doctrine создает таблицу с теми фиктивными индексами, которые она терпит неудачу, потому что длина ключа ключа больше 1000 байтов (что является жестким пределом по очевидным причинам в MySQL)

Вопрос: могу ли я посоветовать Доктрине оставить индексы, которые она находит в таблице, нетронутой в схеме: команда обновления? Есть ли способ взломать это в рамки? Крайне громоздко воссоздать индекс полного текста после каждого обновления схемы: (

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 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;

SQL для создания индексов tmp_search (сначала отбросьте, какая учение останется там, а затем создайте наш)

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);

Ответ 1

Я смог решить это с помощью миграции, а затем добавить поддельные индексы с тем же именем.

Миграция добавила фактический полнотекстовый индекс с использованием необработанного SQL:

$this->addSql('ALTER TABLE content ADD FULLTEXT fulltext_content(title, description)');

Затем я добавил индекс к определению Entity:

@ORM\Table(name="content", indexes={@ORM\Index(name="fulltext_content",columns={"title","description"})})

Пока вы сначала генерируете индексы полнотекстового кода, Doctrine больше не будет их удалять.

Ответ 2

  • Вам не следует использовать doctrine: schema: update on production. Вместо этого используйте миграции.
  • Насколько я помню, Doctrine 2 не имеет полной поддержки MyIsam, но вы можете создать таблицу вручную и использовать ее
  • Mysql Полнотекстовый поиск - не лучший выбор для поиска. Возможно, Sphinx или Lucene являются более подходящим решением для вашей задачи?

Ответ 3

Как и кто-то другой, это не очень хорошая идея использовать doctrine:schema:update для производства, потому что любая незначительная ошибка в вашем коде потенциально может привести к тому, что половина вашей базы данных будет удалена.

Я работаю над довольно большим проектом, и мы используем doctrine:schema:update --dump-sql для поиска запросов, которые нужно выполнить, и выполняйте их вручную.

Изменить: Единственное другое предложение, которое у меня есть, - это если вы не хотите выполнять запросы вручную, вы можете обработать выходные данные doctrine:schema:update --dump-sql, фильтровать запросы, которые вы не хотите выполнять, и запускать оставшиеся на база данных. Или создайте команду, которая создает ваши индексы после обновления вашей схемы, например myproject:schema:createIndexes (или что-то еще)