Details
-
Type:
Bug
-
Status:
Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: 1.2.1
-
Fix Version/s: None
-
Component/s: None
-
Labels:None
Description
I have the following:
<?php class JS_Page extends Doctrine_Record { public function setTableDefinition() { $this->setTableName('page'); $this->hasColumns(array( 'id' => array( 'type' => 'integer', 'length' => 4, 'primary' => true, 'autoincrement' => true, ), 'content' => array( 'type' => 'array', 'length' => 65536, 'notnull' => true, 'default' => array(), ), )); } public function setUp() { $this->actAs(new JS_Template_Meta()); $this->actAs('Searchable', array( 'fields' => array('title', 'description', 'keywords'), 'tableName' => 'page_index', )); } } class JS_Template_Meta extends Doctrine_Template { public function setTableDefinition() { $this->hasColumns(array( 'title' => array( 'type' => 'string', 'length' => 255, 'notnull' => true, ), 'description' => array( 'type' => 'string', ), 'keywords' => array( 'type' => 'string', 'length' => 255, ), )); } }
When a Page record is updated I get this error:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'application-title-0-3' for key 1
If I only index fields from Page it works.
I tracked this down to the code in Doctrine_Search that deletes the existing indexed data before re-indexing a record (I'm not using batchUpdate). For reasons I don't understand the DELETE query is not executing correctly before re-indexing, and so any unchanged data is being added to the index twice, causing the error.
I managed to work around this by adding my own template and listener before Searchable, with a preSave event that deletes the index data:
... $this->actAs(new JS_Template_Searchable()); $this->actAs('Searchable', array( 'fields' => array('title', 'description', 'keywords'), 'tableName' => 'page_index', )); ... class JS_Template_Searchable extends Doctrine_Template { public function setTableDefinition() { $this->addListener(new JS_Template_Searchable_Listener()); } } class JS_Template_Searchable_Listener extends Doctrine_Record_Listener { public function preSave(Doctrine_Event $event) { $invoker = $event->getInvoker(); $class = get_class($invoker) . 'Index'; $query = Doctrine_Query::create() ->delete() ->from("{$class} i") ->where("i.id = ?", $invoker['id']) ->execute(); } }
Obviously that's an ugly hack, but it works.