用PHP调用Lucene包来实现全文检索
作者:张杰
来源:http://www.lucene.com.cn/php.htm
相关链接
Lucene中国:http://www.lucene.com.cn
Lucene官方网站:http://lucene.apache.org/
由于工作需要,需要使用PHP实现对网站内大量数量进行全文检索,而且目前最流行的全文检索的搜索引擎库就是Lucene了,它是Apache Jakarta的一个子项目,并且提供了简单实用的API,用这些API,就可以对任何基本文本的数据(包括数据库)进行全文检索。
因为PHP本身就支持调用外部Java类,所以先用Java写了一个类,这个类通过调用Lucene的API,实现了两个方法:
* public String searchword(String ss,String index_path)
其中createIndex是创建索引方法,传入了两个参数分别是indexDir_path(索引文件的目录),dataDir_path(被索引的文件目录),返回被索引的文件列表字符串,另一个是searchword,通过传入的关键字参数(ss)对索引进行检索,index_path就是索引文件的目录。返回所有检索到的文件。
这里是源代码,很简单,大家可以参考一下:TxtFileIndexer.java
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.Date;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.FSDirectory;
public class TxtFileIndexer ...{
public String test() ...{
return " test is ok hohoho " ;
}
/** //**
* @param args
*/
public String createIndex(String indexDir_path,String dataDir_path) throws Exception ...{
String result = "" ;
File indexDir = new File(indexDir_path);
File dataDir = new File(dataDir_path);
Analyzer luceneAnalyzer = new StandardAnalyzer();
File[] dataFiles = dataDir.listFiles();
IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer, true );
long startTime = new Date().getTime();
for ( int i = 0 ; i < dataFiles.length; i ++ ) ...{
if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith( " .html " )) ...{
result += " Indexing file " + dataFiles[i].getCanonicalPath() + " <br /> " ;
Document document = new Document();
Reader txtReader = new FileReader(dataFiles[i]);
document.add(Field.Text( " path " ,dataFiles[i].getCanonicalPath()));
document.add(Field.Text( " contents " ,txtReader));
indexWriter.addDocument(document);
}
}
indexWriter.optimize();
indexWriter.close();
long endTime = new Date().getTime();
result += " It takes " + (endTime - startTime)
+ " milliseconds to create index for the files in directory "
+ dataDir.getPath();
return result;
}
public String searchword(String ss,String index_path) throws Exception ...{
String queryStr = ss;
String result = " Result:<br /> " ;
// This is the directory that hosts the Lucene index
File indexDir = new File(index_path);
FSDirectory directory = FSDirectory.getDirectory(indexDir, false );
IndexSearcher searcher = new IndexSearcher(directory);
if ( ! indexDir.exists())...{
result = " The Lucene index is not exist " ;
return result;
}
Term term = new Term( " contents " ,queryStr.toLowerCase());
TermQuery luceneQuery = new TermQuery(term);
Hits hits = searcher.search(luceneQuery);
for ( int i = 0 ; i < hits.length(); i ++ )...{
Document document = hits.doc(i);
result += " <br /><a href='getfile.php?w= " + ss + " &f= " + document.get( " path " ) + " '>File: " + document.get( " path " ) + " </a> " ;
}
return result;
}
}
PHP的调用方法如下:
先创建一个我们写的TxtFileIndexer类的实例,
然后就按正常PHP类的调用方法的方式进行调用,首先创建索引:
$index_path = " F:/test/php_lucene/htdocs/data/search " ; // 定义生成的索引文件存放目录
$s = $tf -> createIndex( $index_path , $data_path ); // 调用Java类的方法
print $s ; // 打印返回的结果
$s = $tf -> searchword( " here is keyword for search " , $index_path );
print $s ;
另外要注意Java类的路径,可以在PHP里设置
PHP源代码:test.php
<? php
error_reporting ( 0 );
java_require( " F:/test/php_lucene/htdocs/lib/ " );
$tf = new Java( ' TestLucene.TxtFileIndexer ' );
$s = $tf -> test();
print " TestLucene.TxtFileIndexer->test()<br /> " . $s ;
echo " <hr /> " ;
$data_path = " F:/test/php_lucene/htdocs/data/manual " ;
$index_path = " F:/test/php_lucene/htdocs/data/search " ;
if ( $_GET [ " action " ] == " create " ) ... {
$s = $tf -> createIndex( $index_path , $data_path );
print $s ;
} else ... {
echo " <form method=get> <input type=text name=w /><input type=submit value=search /><br /> " ;
if ( $_GET [ " w " ] != "" ) ... {
$s = $tf -> searchword( $_GET [ " w " ] , $index_path );
print $s ;
}
}
?>
接下来我把环境配置说一下,先需要有Java SDK,是必须的,我使用的是1.4.2版的,其它版本应该也没问题。PHP5,试过PHP4,应该可以。由于PHP5带的Java扩展没调通,并且以前用过调用Java效率很低,很慢,所以使用了 Php/Java Bridge 这个项目。
1. 下载JavaBridge URL:http://sourceforge.net/projects/php-java-bridge/ ,目前版本是php-java-bridge_3.0.8_j2ee.zip ,解包后把
a.JavaBridge/WEB-INF/cgi/java-x86-windows.dll
b.JavaBridge/WEB-INF/lib/JavaBridge.jar
复制到 c:/php/ext 目录下,并把java-x86-windows.dll 改名为 php_java.dll
2.修改php.ini(例)
[ Java ]
java.class.path = " C:phpextJavaBridge.jar;F: estphp_lucenehtdocs "
java.java_home = " C:j2sdk1.4.2_10 "
java.library.path = " c:phpext;F: estphp_lucenehtdocs "
4.可以找一些文件进行索引,在test.php里可以修改索引文件和数据文件的路径。TxtFileIndexer.java的37行限制了只索引html后缀的文件,有需要也可以修改。
根据目前的情况(JavaBridge支持Linux和Freebsd),完全可以在linux或freebsd/apache2/php4/lucene/JavaBridge环境下运行。