使用 Zend Lucene 对相关实体建立索引

发布于 2024-11-26 14:13:50 字数 1567 浏览 1 评论 0原文

我已在应用程序中设置了搜索,但希望将其扩展为以一对多方式索引相关属性。例如,一个人可以有多个用户名,因此必须将它们分开,如下例所示:

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,我可以搜索 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。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寄居人 2024-12-03 14:13:50

您没有指定您正在使用哪个推进版本。看到您正在使用 PDO,您很可能正在使用 1.3+。

如果Username对象初始化正确,即:

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

调用$username->save();还应该触发 $person 的 save() ,并且 $person 对象还应该包含 Username 对象。

但是 $person 初始化有一个“特征”。 (有些人可能称之为错误..)

如果您像这样初始化 $person:

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

$person 的用户名列表将为空。当您调用

 $username->setPerson($person);

$username 时, $username 将被添加到 $person 的用户名列表中,这反过来意味着调用 $person->getUsernames() 不会自动从数据库中获取用户名,因为该列表已经非空。

所以你需要用用户名初始化$person。要么喜欢

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

要么

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文