Индексирование связанных объектов с помощью Zend Lucene - PullRequest
2 голосов
/ 25 июля 2011

Я настроил поиск в своем приложении, но хочу расширить его до свойств индекса, связанных «один ко многим». Например, человек может иметь много имен пользователей, поэтому они должны храниться отдельно, как в следующем примере:

person:
  id:         ~
  name:       {type: varchar(100), required: true}

username:
  person_id:  {type: integer, foreignTable: person, foreignReference: id}
  username:   {type: varchar(20), primaryKey: true, required: true}

До сих пор я следовал примеру Jobeet , чтобы использовать Zend Lucene в своем приложении, и я могу искать свойства name в Person, такие как Name.

Я не смог найти способ сделать это автоматически через Symfony или Lucene, поэтому я попытался добавить элементы в индекс Person следующим образом:

foreach ($this->getUsernames() as $i => $username)
{
  $doc->addField(Zend_Search_Lucene_Field::Text('username' . $i,
      $username->getUsername(), 'utf-8'));
}

Затем я попытался обновить этот индекс при каждом добавлении нового имени пользователя, обновив функцию сохранения имени пользователя:

public function save(PropelPDO $con = null)
{
  $ret = parent::save($con);

  // reindex the person
  $person = $this->getPerson();
  $person->save();

  return $ret;
}

Это прекрасно работает, пока человек создается во время выполнения, но если загружено из приборов, getUsernames() ничего не возвращает. Код выполняется дважды (один раз при загрузке Person и один раз при добавлении имени пользователя). Есть ли причина для этого? Можно ли как-то обойти это?

Другой способ сделать это также был бы оценен. Похоже, что Lucene может выполнять поиск по нескольким индексам, используя класс Zend_Lucene_Search_Interface_MultiSearcher, как описано в этот вопрос . Однако я не могу заставить это работать.

Я нашел похожий вопрос здесь , но не нашел указателей.

Я сейчас использую Propel 1.6.

1 Ответ

1 голос
/ 05 августа 2011

Вы не указали, какую версию Propel вы используете.Видя, что вы используете PDO, вы, скорее всего, используете 1.3 +.

, если объект Username инициализирован правильно, то есть:

<?php
$username = new Username();
$username->setUsername('foobar');
$username->setPerson($person);

Вызов $ username-> save ();должен также вызывать save () для $ person, а также объект $ person должен содержать объект Username.

Но что касается инициализации $ person, здесь есть «особенность».(некоторые могут назвать это ошибкой ..)

Если вы инициализируете $ person как:

$person = PersonPeer::retrieveByPk(123);
//or for 1.5+
$person = PersonQuery::create()->findPk(123);

, список имен $ person будет пуст.И когда вы вызываете

 $username->setPerson($person);

, $ username будет добавлено в список имен $ person, что, в свою очередь, означает, что вызов $ person-> getUsernames () не будет автоматически извлекать имена пользователей из db, так каксписок уже не пустой.

Так что вам нужно инициализировать $ person с именами пользователей.Либо как

<?php
$person = PersonQuery::create()->joinWith('Person.Usernames')->filterById(123)->findOne();

или

<?php
$person = PersonPeer::retrieveByPk(123);
$person->getUsernames(); //trigger list fetch
...