|
用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,实现了两个方法:
*publicStringcreateIndex(StringindexDir_path,StringdataDir_path)
*publicStringsearchword(Stringss,Stringindex_path)
其中createIndex是创建索引方法,传入了两个参数分别是indexDir_path(索引文件的目录),dataDir_path(被索引的文件目录),返回被索引的文件列表字符串,另一个是searchword,通过传入的关键字参数(ss)对索引进行检索,index_path就是索引文件的目录。返回所有检索到的文件。
这里是源代码,很简单,大家可以参考一下:TxtFileIndexer.java
packageTestLucene;
importjava.io.File;
importjava.io.FileReader;
importjava.io.Reader;
importjava.util.Date;
importorg.apache.lucene.analysis.Analyzer;
importorg.apache.lucene.analysis.standard.StandardAnalyzer;
importorg.apache.lucene.document.Document;
importorg.apache.lucene.document.Field;
importorg.apache.lucene.index.IndexWriter;
importorg.apache.lucene.index.Term;
importorg.apache.lucene.search.Hits;
importorg.apache.lucene.search.IndexSearcher;
importorg.apache.lucene.search.TermQuery;
importorg.apache.lucene.store.FSDirectory;
publicclassTxtFileIndexer...{
publicStringtest()...{
return"testisokhohoho";
}
/**//**
*@paramargs
*/
publicStringcreateIndex(StringindexDir_path,StringdataDir_path)throwsException...{
Stringresult="";
FileindexDir=newFile(indexDir_path);
FiledataDir=newFile(dataDir_path);
AnalyzerluceneAnalyzer=newStandardAnalyzer();
File[]dataFiles=dataDir.listFiles();
IndexWriterindexWriter=newIndexWriter(indexDir,luceneAnalyzer,true);
longstartTime=newDate().getTime();
for(inti=0;i<dataFiles.length;i++)...{
if(dataFiles.isFile()&&dataFiles.getName().endsWith(".html"))...{
result+="Indexingfile"+dataFiles.getCanonicalPath()+"<br/>";
Documentdocument=newDocument();
ReadertxtReader=newFileReader(dataFiles);
document.add(Field.Text("path",dataFiles.getCanonicalPath()));
document.add(Field.Text("contents",txtReader));
indexWriter.addDocument(document);
}
}
indexWriter.optimize();
indexWriter.close();
longendTime=newDate().getTime();
result+="Ittakes"+(endTime-startTime)
+"millisecondstocreateindexforthefilesindirectory"
+dataDir.getPath();
returnresult;
}
publicStringsearchword(Stringss,Stringindex_path)throwsException...{
StringqueryStr=ss;
Stringresult="Result:<br/>";
//ThisisthedirectorythathoststheLuceneindex
FileindexDir=newFile(index_path);
FSDirectorydirectory=FSDirectory.getDirectory(indexDir,false);
IndexSearchersearcher=newIndexSearcher(directory);
if(!indexDir.exists())...{
result="TheLuceneindexisnotexist";
returnresult;
}
Termterm=newTerm("contents",queryStr.toLowerCase());
TermQueryluceneQuery=newTermQuery(term);
Hitshits=searcher.search(luceneQuery);
for(inti=0;i<hits.length();i++)...{
Documentdocument=hits.doc(i);
result+="<br/><ahref='getfile.php?w="+ss+"&f="+document.get("path")+"'>File:"+document.get("path")+"</a> ";
}
returnresult;
}
}
而PHP程序就调用这两个方法,实现对Lucene的调用,从而达到全文检索的目的。
PHP的调用方法如下:
先创建一个我们写的TxtFileIndexer类的实例,
$tf=newJava('TestLucene.TxtFileIndexer');
然后就按正常PHP类的调用方法的方式进行调用,首先创建索引:
$data_path="F:/test/php_lucene/htdocs/data/manual";//定义被索引内容的目录
$index_path="F:/test/php_lucene/htdocs/data/search";//定义生成的索引文件存放目录
$s=$tf->createIndex($index_path,$data_path);//调用Java类的方法
print$s;//打印返回的结果
这次再试试检索:
$index_path="F:/test/php_lucene/htdocs/data/search";//定义生成的索引文件存放目录
$s=$tf->searchword("hereiskeywordforsearch",$index_path);
print$s;
另外要注意Java类的路径,可以在PHP里设置
java_require("F:/test/php_lucene/htdocs/lib/");//这是个例子,我的类和Lucene都放到这个目录下,这样就可以了,是不是很简单。
PHP源代码:test.php
<?php
error_reporting(0);
java_require("F:/test/php_lucene/htdocs/lib/");
$tf=newJava('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"<formmethod=get><inputtype=textname=w/><inputtype=submitvalue=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(例)
extension=php_java.dll
[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"
3.重启Apache即可。
4.可以找一些文件进行索引,在test.php里可以修改索引文件和数据文件的路径。TxtFileIndexer.java的37行限制了只索引html后缀的文件,有需要也可以修改。
根据目前的情况(JavaBridge支持Linux和Freebsd),完全可以在linux或freebsd/apache2/php4/lucene/JavaBridge环境下运行。 |
|
|