在 Zend Framework 中向 Lucene 索引添加内容
Adding content to a Lucene index in Zend Framework
我正在为基于 Precurio 的内联网开发新模块,Precurio 是一个内联网 PHP + MySQL 应用程序,曾经有一个免费版本。
本内网使用Zend Framework 2.0,使用Lucene提供搜索结果。每次我向 Intranet 添加一个新模块时,我都会添加一个功能来索引用户插入的模块的内容。
问题是,搜索工作正常,但前提是我从头开始重建所有索引。每当我向模块添加新内容时,它们都不会出现在搜索结果中(完全重建索引之前存在的内容仍然显示为搜索结果)。
我很困惑,因为重建整个索引的函数只是循环调用向其中添加单个项目的函数,所以据我所知,它应该可以正常工作。但显然,它不是。
这是我正在开发的模块的索引功能代码:
/**
* Adds a cabinet to the index
* @param $cabinet int | CabinetContent . you could either pass the cabinet_id or the CabinetContent object
* @return void
*/
public function indexCabinet($cabinet,$indexing = false)
{
if(!is_a($cabinet,'CabinetContent')) {
$cabinet = CabinetContents::getContent($cabinet);
}
if(Precurio_Utils::isNull($cabinet->title))
return;//cabinets without a title will be ignored.
//check if the cabinet already exists
if(!$indexing)
{
$hits = $this->index->find('id:' . $cabinet->id.' AND module:cabinet');
foreach ($hits as $hit)
{
$this->index->delete($hit->id);
}
}
try
{
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::keyword('id',$cabinet->id));
$doc->addField(Zend_Search_Lucene_Field::text('title',$cabinet->title));
if( $cabinet->identifier != '' )
$doc->addField(Zend_Search_Lucene_Field::text('identifier',$cabinet->identifier));
if( $cabinet->summary != '' )
$doc->addField(Zend_Search_Lucene_Field::text('summary',$cabinet->summary));
if( $cabinet->body != '' )
$doc->addField(Zend_Search_Lucene_Field::text('body',$cabinet->body));
$doc->addField(Zend_Search_Lucene_Field::keyword('user_id',$cabinet->user_id));
if( ($cabinet->url != '#') && ($cabinet->url != '') )
$doc->addField(Zend_Search_Lucene_Field::text('url',$cabinet->url));
if( $cabinet->keyword != '' )
$doc->addField(Zend_Search_Lucene_Field::text('keyword',$cabinet->keyword));
if( $cabinet->getFullName() != '' )
$doc->addField(Zend_Search_Lucene_Field::text('fullname',$cabinet->getFullName()));
$doc->addField(Zend_Search_Lucene_Field::unIndexed('date_added',$cabinet->getDateAdded()));
$doc->addField(Zend_Search_Lucene_Field::keyword('module','cabinet'));
}
catch(Exception $e)
{
}
$this->index->addDocument($doc);
return;
}
之前的函数似乎只有在我 运行 createIndexFromDB() 时才有效。这些是用于重新创建索引的函数:
private $index;
public function __construct()
{
if(!file_exists(self::PATH_INDEX))
$this->createIndexFromDb();
else
$this->index = Zend_Search_Lucene::open(self::PATH_INDEX);
}
private function createIndexFromDb()
{
set_time_limit(0);
mkdir(self::PATH_INDEX);
$this->index = Zend_Search_Lucene::create(self::PATH_INDEX);
$this->indexCabinets(); // Cabinets is the module I am developing
/* Here go a lot of indexing for other modules, like $this->indexEmployees(); but I have commented it out for simplicity during developement */
}
private function indexCabinets()
{
$table = new Zend_Db_Table(array('name'=>PrecurioTableConstants::CABINET_CONTENT,'rowClass'=>'CabinetContent'));
$select = $table->select(false);
$select->setIntegrityCheck(false);
$select->setTable($table);
$select = $select->distinct()
->from(array('a' => PrecurioTableConstants::CABINET_CONTENT))
->join(array('b' => PrecurioTableConstants::USERS),'a.user_id = b.user_id',array('first_name','last_name','profile_picture_id'))
->where('a.active=1');
$cabinets = $table->fetchAll($select);
foreach($cabinets as $cabinet)
{
$this->indexCabinet($cabinet,true);
}
}
现在,在我正在开发的模块中,插入一个新的柜子内容后,我运行下面的代码:
$dict = new My_Search();
$dict->indexCabinet($content_id);
$this->_redirect('/cabinet/view/index');
但是没用。我尝试使用 'true' 作为第二个参数调用 $dict->indexCabinet,同时传递 $content 对象,就像它们在搜索中所做的那样 class 而不是 $content_id... 我不知道我做错了什么,也不知道还有什么可以尝试的。
需要说明的是,所有的新模块都是在Precurio Intranet 原有模块的基础上,以及My_Search class 中添加的。据我所知,索引新内容可能在原始代码中不起作用。任何帮助将不胜感激。
**编辑 10/08/2016:我在上面的代码中添加了原始的 class 构造函数
我不太确定我是否确切地看到了您提供的代码是如何被使用的(我对 Zend 的熟悉程度最好是一触即发),但这听起来与一个非常常见的 lucene 错误一致: 创建新索引,而不是打开现有索引。
您应该使用 Zend_Search_Lucene::create
创建一个 全新的 索引。给定位置的任何现有索引都将被删除。
您应该使用 Zend_Search_Lucene::open
打开现有索引。
请参阅此 Zend 中的前两个示例 "Building Indexes" documentation。
我正在为基于 Precurio 的内联网开发新模块,Precurio 是一个内联网 PHP + MySQL 应用程序,曾经有一个免费版本。
本内网使用Zend Framework 2.0,使用Lucene提供搜索结果。每次我向 Intranet 添加一个新模块时,我都会添加一个功能来索引用户插入的模块的内容。
问题是,搜索工作正常,但前提是我从头开始重建所有索引。每当我向模块添加新内容时,它们都不会出现在搜索结果中(完全重建索引之前存在的内容仍然显示为搜索结果)。
我很困惑,因为重建整个索引的函数只是循环调用向其中添加单个项目的函数,所以据我所知,它应该可以正常工作。但显然,它不是。
这是我正在开发的模块的索引功能代码:
/**
* Adds a cabinet to the index
* @param $cabinet int | CabinetContent . you could either pass the cabinet_id or the CabinetContent object
* @return void
*/
public function indexCabinet($cabinet,$indexing = false)
{
if(!is_a($cabinet,'CabinetContent')) {
$cabinet = CabinetContents::getContent($cabinet);
}
if(Precurio_Utils::isNull($cabinet->title))
return;//cabinets without a title will be ignored.
//check if the cabinet already exists
if(!$indexing)
{
$hits = $this->index->find('id:' . $cabinet->id.' AND module:cabinet');
foreach ($hits as $hit)
{
$this->index->delete($hit->id);
}
}
try
{
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::keyword('id',$cabinet->id));
$doc->addField(Zend_Search_Lucene_Field::text('title',$cabinet->title));
if( $cabinet->identifier != '' )
$doc->addField(Zend_Search_Lucene_Field::text('identifier',$cabinet->identifier));
if( $cabinet->summary != '' )
$doc->addField(Zend_Search_Lucene_Field::text('summary',$cabinet->summary));
if( $cabinet->body != '' )
$doc->addField(Zend_Search_Lucene_Field::text('body',$cabinet->body));
$doc->addField(Zend_Search_Lucene_Field::keyword('user_id',$cabinet->user_id));
if( ($cabinet->url != '#') && ($cabinet->url != '') )
$doc->addField(Zend_Search_Lucene_Field::text('url',$cabinet->url));
if( $cabinet->keyword != '' )
$doc->addField(Zend_Search_Lucene_Field::text('keyword',$cabinet->keyword));
if( $cabinet->getFullName() != '' )
$doc->addField(Zend_Search_Lucene_Field::text('fullname',$cabinet->getFullName()));
$doc->addField(Zend_Search_Lucene_Field::unIndexed('date_added',$cabinet->getDateAdded()));
$doc->addField(Zend_Search_Lucene_Field::keyword('module','cabinet'));
}
catch(Exception $e)
{
}
$this->index->addDocument($doc);
return;
}
之前的函数似乎只有在我 运行 createIndexFromDB() 时才有效。这些是用于重新创建索引的函数:
private $index;
public function __construct()
{
if(!file_exists(self::PATH_INDEX))
$this->createIndexFromDb();
else
$this->index = Zend_Search_Lucene::open(self::PATH_INDEX);
}
private function createIndexFromDb()
{
set_time_limit(0);
mkdir(self::PATH_INDEX);
$this->index = Zend_Search_Lucene::create(self::PATH_INDEX);
$this->indexCabinets(); // Cabinets is the module I am developing
/* Here go a lot of indexing for other modules, like $this->indexEmployees(); but I have commented it out for simplicity during developement */
}
private function indexCabinets()
{
$table = new Zend_Db_Table(array('name'=>PrecurioTableConstants::CABINET_CONTENT,'rowClass'=>'CabinetContent'));
$select = $table->select(false);
$select->setIntegrityCheck(false);
$select->setTable($table);
$select = $select->distinct()
->from(array('a' => PrecurioTableConstants::CABINET_CONTENT))
->join(array('b' => PrecurioTableConstants::USERS),'a.user_id = b.user_id',array('first_name','last_name','profile_picture_id'))
->where('a.active=1');
$cabinets = $table->fetchAll($select);
foreach($cabinets as $cabinet)
{
$this->indexCabinet($cabinet,true);
}
}
现在,在我正在开发的模块中,插入一个新的柜子内容后,我运行下面的代码:
$dict = new My_Search();
$dict->indexCabinet($content_id);
$this->_redirect('/cabinet/view/index');
但是没用。我尝试使用 'true' 作为第二个参数调用 $dict->indexCabinet,同时传递 $content 对象,就像它们在搜索中所做的那样 class 而不是 $content_id... 我不知道我做错了什么,也不知道还有什么可以尝试的。
需要说明的是,所有的新模块都是在Precurio Intranet 原有模块的基础上,以及My_Search class 中添加的。据我所知,索引新内容可能在原始代码中不起作用。任何帮助将不胜感激。
**编辑 10/08/2016:我在上面的代码中添加了原始的 class 构造函数
我不太确定我是否确切地看到了您提供的代码是如何被使用的(我对 Zend 的熟悉程度最好是一触即发),但这听起来与一个非常常见的 lucene 错误一致: 创建新索引,而不是打开现有索引。
您应该使用 Zend_Search_Lucene::create
创建一个 全新的 索引。给定位置的任何现有索引都将被删除。
您应该使用 Zend_Search_Lucene::open
打开现有索引。
请参阅此 Zend 中的前两个示例 "Building Indexes" documentation。