2

I have set up search in my application, but wish to expand it to index properties related in a one-to-many way. For instance, a person can have many usernames, so they have to be kept separate, as in the following example:

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}

So far I have followed the Jobeet example to use Zend Lucene within my application, and I can search on properties of name within Person, such as Name.

I couldn't find any way to do this automatically through Symfony or Lucene, so I attempted to add the items in the Person's index like so:

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

I then attempted to update this index whenever a new Username is added by updating Username's save function:

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

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

  return $ret;
}

This works fine as long as the person is created at run-time, but if loaded from fixtures, getUsernames() returns nothing. The code is executed twice (once while loading Person, and once when adding the Username). Is there any reason for this? Can I get around this somehow?

Another way of doing this would also be appreciated. It appears that Lucene can search over multiple indices using the Zend_Lucene_Search_Interface_MultiSearcher class, as described in this question. However, I can't seem to get this working.

I found a similar question here, but found no pointers.

I am now using Propel 1.6.

Community
  • 1
  • 1
Druckles
  • 3,161
  • 2
  • 41
  • 65

1 Answers1

1

You didn't specify which propel version you are using. Seeing you are using PDO, you most likely are using 1.3+.

if the Username object is initialized right, that is:

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

Calling $username->save(); should trigger also save() for the $person, and also the $person object should contain the Username object.

But what comes to the $person initialization, there is a "feature". (some might call it a bug..)

If you initialize $person like:

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

the $person's Usernames-list will be empty. And when you call

 $username->setPerson($person);

the $username will be added to the $person's Usernames-list, which in turn means calling $person->getUsernames() won't automatically fetch the usernames from db, as the list is already non-empty.

So you need to initialize $person with the usernames. Either like

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

or

<?php
$person = PersonPeer::retrieveByPk(123);
$person->getUsernames(); //trigger list fetch
NiklasN
  • 559
  • 1
  • 7
  • 12
  • Thank you very much for the response. Unfortunately, I don't see how to apply this to my problem. The only function I am currently overriding in Username.php is `save()`, which currently looks exactly like I posted. If I don't call `$person->save()` myself, it doesn't at all. Are you suggesting it should? Where should I be putting the above initialisation of Person? In Username's `setPerson()`, or overriding `doSave()`? – Druckles Aug 05 '11 at 11:16
  • Hmm.. it seems I remembered wrong this behavior.. On my example case calling $username->setPerson($person); actually calls $person->addUsername($username); which actually then initializes the collection. At least on 1.5+. So for initializing the collection you shouldn't have to do anything special. Your code then should work. The username-collection should be fully initialized in your persons' save-method. The person's save-method is only called if the person is actually modified, so that you have to call manually, as you are doing. – NiklasN Aug 08 '11 at 07:25
  • Do you know why else the usernames might not have been initialised in Person? – Druckles Aug 08 '11 at 12:52