2011-07-25 14 views
2

私は自分のアプリケーションで検索を設定しましたが、関連するインデックスプロパティを1対多数の方法で展開したいと考えています。例えば、人は多くのユーザ名を持つことができますので、彼らは次の例のように、別々に保持する必要があります。Zend Luceneを使用したインデックス作成関連エンティティ

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} 

これまでのところ、私は自分のアプリケーション内のZend Luceneのを使用するようにJobeet exampleを踏襲している、と私は検索することができます名前のようなPerson内の名前のプロパティ。

私は自動的にsymfonyのか、Luceneを介してこれを行うにはどのような方法を見つけることができませんでしたので、私はそうのような人のインデックスに項目を追加しようとしました:

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()何も返さないからロードされた場合。コードは2回実行されます(Personをロードしているときと、Usernameを追加するときに1回)。これには何らかの理由がありますか?私は何とかこの周りに得ることができますか?

これを実行する別の方法もわかります。 Luceneは、this questionで説明されているように、Zend_Lucene_Search_Interface_MultiSearcherクラスを使用して複数のインデックスを検索できます。しかし、私はこれを動作させるように見えることはできません。

私は同様の質問hereを見つけましたが、ポインタが見つかりませんでした。

私は現在Propel 1.6を使用しています。

答えて

1

使用しているプロペルのバージョンを指定していません。あなたがPDOを使用しているのを見て、あなたはおそらく1.3+を使用しています。つまり

ユーザー名オブジェクトが右に初期化されている場合、:

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

>(セーブ$ username-を呼び出します)。 $ personのsave()も起動し、$ personオブジェクトにはUsernameオブジェクトが含まれている必要があります。

しかし、$人の初期化には、「機能」があります。 (いくつかのバグを呼ぶかもしれない...)

をあなたのような人$を初期化する場合:

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

$者のユーザ名リストが空になります。そして、あなたは自動的にリストとして、DBからユーザ名を取得しません$ユーザ名)が順番に($ person-> getUsernamesを呼び出すことを意味し、$人のユーザ名リストに追加されます

$username->setPerson($person); 

を呼び出すときすでに空ではありません。

したがって、$ personをユーザー名で初期化する必要があります。どちらかのような

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

または

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

応答をありがとうございました。残念ながら、私はこれを私の問題に適用する方法は見当たりません。私が現在Username.phpでオーバーライドしている唯一の関数は 'save()'です。これは現在私が投稿したのとまったく同じです。私が '$ person-> save()'を自分で呼び出さなければ、それはまったくありません。あなたはそれを示唆していますか? 私はPersonの上記の初期設定をどこに置くべきですか? Usernameの 'setPerson()'や 'doSave()'をオーバーライドする? – Druckles

+0

うーん..それは私が間違ってこの振る舞いを思い出したようです..私の例の場合、$ username-> setPerson($ person);実際には$ person-> addUsername($ username)を呼び出します。実際にコレクションを初期化します。少なくとも1.5以上。だからコレクションを初期化するために特別なことをする必要はありません。あなたのコードはうまくいくはずです。あなたの人のsave-methodでusername-collectionを完全に初期化する必要があります。 personのsave-methodは、人が実際に変更された場合にのみ呼び出されるため、手動で呼び出す必要があります。 – NiklasN

+0

ユーザー名がPersonで初期化されていない可能性があることは分かりますか? – Druckles

関連する問題