Reputation: 3782
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.
Upvotes: 2
Views: 454
Reputation: 559
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
Upvotes: 1